onConfigurationChanged не вызывается при вращении с установленным configChanges = "клавиатура скрытая | ориентация"? - PullRequest
1 голос
/ 15 октября 2011

Я не первый, у кого возникают проблемы с вызовом onConfigurationChanged при ротации.Но поскольку общее решение состоит в том, чтобы установить configChanges = "клавиатура скрытая | ориентация" в манифесте, и это не помогает мне, я отправляю этот вопрос независимо от тысяч «похожих».

Это простой виджет, который включает и выключает громкость звонка при нажатии.Он работает нормально, пока экран не поворачивается, после этого ничего не происходит при нажатии.

Чтобы разобраться с этой проблемой, я хочу поймать onConfigurationChanged, но он никогда не вызывается!Мне никогда не удается увидеть сообщение журнала от onConfigurationChanged, однако я вижу другое сообщение в журнале «I / ActivityManager (63): Config change:», указывающее, что конфигурация изменилась и что было бы разумно ожидать вызова onConfigurationChanged.

Пожалуйста, помогите:)

Манифест:

<?xml version="1.0" encoding="utf-8"?>  
<manifest xmlns:android="http://schemas.android.com/apk/res/android"  
    package="aa.android.x10.mini.mywidget" android:versionCode="1"  
    android:versionName="1.0">  
<application android:icon="@drawable/icon" 
             android:label="@string/app_name">  

    <receiver android:name="MyWidgetProvider" android:label="My Widget">  
        <intent-filter>  
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />  
            <action android:name="android.appwidget.action.ACTION_BATTERY_CHANGED" /> 
        </intent-filter>  
        <meta-data android:name="android.appwidget.provider"  
                   android:resource="@xml/widget_info" />  
    </receiver>  
    <service android:name=".UpdateWidgetService"
             android:configChanges="keyboardHidden|orientation"></service>  
    <activity android:name=".Test"></activity>  

    </application>  
    <uses-sdk android:minSdkVersion="7" />  

</manifest>   

WidgetProvider: пакет aa.android.x10.mini.mywidget;

import android.app.PendingIntent;  
import android.appwidget.AppWidgetManager;  
import android.appwidget.AppWidgetProvider;  
import android.content.Context;  
import android.content.Intent;  
import android.util.Log;
import android.widget.RemoteViews;  

public class MyWidgetProvider extends AppWidgetProvider 
{   
@Override  
public void onUpdate(Context context, AppWidgetManager appWidgetManager,  
        int[] appWidgetIds) 
{  
    Log.i("MyWidgetProvider onUpdate", "#### CALLED!");  

    RemoteViews remoteViews = new RemoteViews(context.getPackageName(),  
            R.layout.widget_layout);  
    Intent intent = new Intent(context.getApplicationContext(), UpdateWidgetService.class);  
    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);  

    PendingIntent pendingIntent = PendingIntent.getService(context.getApplicationContext(), 0, intent, 
                                                            PendingIntent.FLAG_UPDATE_CURRENT);

    remoteViews.setOnClickPendingIntent(R.id.TextView01, pendingIntent);  

    appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);  

    context.startService(intent);  
    }  
}  

Сервис: пакет aa.android.x10.mini.mywidget;

import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.content.Intent;
import android.content.res.Configuration;
import android.media.AudioManager;
import android.os.IBinder;
import android.util.Log;
import android.widget.RemoteViews;

public class UpdateWidgetService extends Service 
{  
@Override  
public void onStart(Intent intent, int startId) 
{  
    Log.i("UpdateWidgetService", "#### CALLED!");  

    String state = null;  

    AudioManager mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);

    if (mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL )
    {
        mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
        mAudioManager.setStreamVolume(AudioManager.STREAM_RING,mAudioManager.getStreamMaxVolume(AudioManager.STREAM_RING),AudioManager.VIBRATE_SETTING_ON);
        state = "ON"; 
    }
    else
    {
        mAudioManager.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
        mAudioManager.setStreamVolume(AudioManager.STREAM_RING,0,AudioManager.VIBRATE_SETTING_ON);
        state = "OFF"; 
    }

    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this.getApplicationContext());  

    int[] appWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);  
    if (appWidgetIds.length > 0) 
    {  
        for (int widgetId : appWidgetIds) 
        {  
            RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.widget_layout);  
            remoteViews.setTextViewText(R.id.TextView01, "\n" +"         "+ state);  
                appWidgetManager.updateAppWidget(widgetId, remoteViews);  
            }  
            stopSelf();  
        }  
        super.onStart(intent, startId);  
    }  

    @Override  
    public IBinder onBind(Intent intent) 
    {  
        return null;  
    }  

    @Override 
    public void onConfigurationChanged(Configuration newConfig) 
    { 
        Log.i("onConfigurationChanged", "##### CALLED! #####");  
        super.onConfigurationChanged(newConfig);
    }
}  

Журнал при повороте экрана:

I/WindowManager(   63): Setting rotation to 1, animFlags=0 
I/ActivityManager(   63): Config changed: { scale=1.0 imsi=310/260 loc=en_US touch=3 keys=2/1/1 nav=3/1 orien=2 layout=17} 
I/UsageStats(   63): Unexpected resume of com.android.launcher while already resumed in com.android.launcher 

1 Ответ

6 голосов
/ 16 октября 2011

Джон,

onConfigurationChanged() на самом деле не предназначен для Services. Поскольку Services не имеет пользовательского интерфейса, нет гарантии, что onConfigurationChanged() не будет работать надежно. Лучше всего вставить это в Activity, поскольку Activities гарантированно имеет пользовательский интерфейс. Если вы беспокоитесь о том, чтобы ваш виджет перестраивался на изменение ориентации, это, в конечном счете, задача, которую должен обработать содержащий Activity. Это означает, что если действие не вращается, ваш виджет не переориентируется.

Если, тем не менее, вам все еще нужно управлять изменениями конфигурации самостоятельно, то вам нужно выполнить свои проверки вручную на DefaultDisplay, который автоматически изменяется при изменении ориентации. Эта простая проверка работает следующим образом:

Display display = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
if (display.getWidth() > display.getHeight())
    // In Landscape...
else if (display.getWidth() < display.getHeight())
    // In Portrait...

Теперь, проблема, которую вы описываете, хотя она проявляется при изменении ориентации, это не является проблемой изменения ориентации. Если вы посмотрите на код вашего onUpdate(), вы увидите, что вы одновременно обрабатываете только один виджет. Проблема заключается в том, что поведение изменения ориентации по умолчанию разрушает все пользовательские интерфейсы и создает их заново. Поскольку все обновления нескольких копий виджета происходят одновременно, и вы не можете определить, как Activity, которая содержит ваш виджет, будет обрабатывать изменения ориентации, вы должны учитывать все ваши возможные appWidgetIds. Может помочь следующее:

for (int i : appWidgetIds) {
    int widgetId = appWidgetIds[i];
// Set the RemoteViews for the Widget
    RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget_layout);
// Set the Pending Intent
    Intent intent = new Intent(context.getApplicationContext(),
                               UpdateWidgetService.class);  
    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);  

    PendingIntent pendingIntent = PendingIntent.getService(context.getApplicationContext(), 
                     0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

    remoteViews.setOnClickPendingIntent(R.id.TextView01, pendingIntent);  
// Update the individual widget
    appWidgetManager.updateAppWidget(widgetId, remoteViews);
}

Надеюсь, это поможет.

FuzzicalLogic

...