开发者

onConfigurationChanged not called at rotation with configChanges="keyboardHidden|orientation" set?

开发者 https://www.devze.com 2023-04-13 09:52 出处:网络
I\'m not the first one to have problems with getting onConfigurationChanged called at rotation. But since the common solution is to set configChanges=\"keyboardHidden|orientation\"

I'm not the first one to have problems with getting onConfigurationChanged called at rotation. But since the common solution is to set configChanges="keyboardHidden|orientation" in the manifest, and that does not help me, I posting this question regardless of the thousands of “similar” ones.

This is a simple widget that turns the ringer volume on and off when clicked. It works fine until the screen is rotated, after that nothing happens on click.

To deal with this issue I want to catch onConfigurationChanged, but it never gets called! I never get to see the log message from onConfigurationChanged, I do however see another message in the log “I/ActivityManager( 63): Config changed: ” indicating that the configuration gets changed and that it would be reasonable to expect a call to onConfigurationChanged.

Please help :)

Manifest:

<?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: package 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);  
    }  
}  

Service: package 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
    {
        mAu开发者_StackOverflowdioManager.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);
    }
}  

Log when rotating the screen:

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 


Jon,

onConfigurationChanged() is not really meant for Services. As Services do not have a UI, there is no guarantee that onConfigurationChanged() will not fire dependably. It is best to stick this in an Activity, as Activities are guaranteed to have a User Interface. If you are concerned about your Widget realigning to an orientation change, that is ultimately a job for the containing Activity to handle. This means if the Activity does not rotate, your Widget will not reorient itself.

If, however, you still need to manage configuration changes yourself, then you need to do your checks manually against the DefaultDisplay which automatically changes if the orientation changes. This simple check works as follows:

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

Now, the issue you describe, while it manifests itself when the Orientation changes, it is not specifically an Orientation Change problem. If you look at the code for your onUpdate(), you will see that you are only handling one widget at a time. The issue with this is that the default behavior of an orientation change destroys all UIs and recreates them. Since all updates to multiple copies of a Widget happen at once and you cannot determine how the Activity that holds your widget is going to handle orientation changes, you should account for all of your possible appWidgetIds. The following may help:

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);
}

Hope this helps.

FuzzicalLogic

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号