如何使用服务监测Android设备的方向变化

23
我正在编写一个小部件,用于显示倒计时器。当我将手机从横屏翻转到竖屏时,我的小部件不更新并返回到初始状态,直到由我重复的闹钟调用了onupdate。我希望在方向更改后手动调用onupdate以更新我的小部件。我已经进行了一段时间的研究,发现我需要使用一个服务来监视方向更改并调用我的小部件的onupdate。
我的问题是,我找不到如何使用服务监视更改的直接答案。我看到可以为活动添加“android:configChanges =” orientation | keyboardHidden “”到清单中,并使用onConfigurationChanged,但我是否可以对服务执行此操作?如果可以,怎么做?有更好的方法来监视方向更改吗?我还读过互联网上的一些文章,说服务不是做这个的最好方法。
我看到一些创建方向监听器的教程,但它们似乎使用了已弃用的函数调用。
先行感谢

你有没有找到一个好的解决方案? - Patrick Jackson
4个回答

40

Service#onConfigurationChanged(Configuration newConfig) 对我有效。我认为不需要注册接收器。我也没有在AndroidManifest中添加任何过滤器。自从没有人建议这个解决方案,我是否在讨论中遗漏了什么?我的服务在前台运行。

只需在您的服务中添加:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    //Your handling
}

2
是的,这个方法可行,而且比注册广播意图简单多了! - Flyview
对我来说,当设备旋转到横向并且我从横向退出应用程序时,该方法被调用。当我从纵向退出应用程序时,不会调用onConfigurationChanged(),只会调用onUnbind()。@Flyview 你知道为什么会这样吗? - Nikola Samardzija
@Nikola 可能是因为当你的应用程序退出时,屏幕会返回到竖屏状态? - Flyview
@Flyview 可能是这样,但解决方案还不确定。这不是应用程序本身的方向更改,而是设备(例如主屏幕)为纵向。 onUnbind() 不会被调用两次。因此,实际上它是用于解除绑定和方向解除绑定的相同事件。您对如何在这种情况下区分这两个事件有什么建议吗? - Nikola Samardzija
我有些困惑。当你在横屏模式下退出时,onConfigurationChanged会被调用两次还是onUnbind会被调用? - Flyview

14
请看下面的例子,它可以达到你所要求的效果,希望这可以帮到你。
public class ScreenOrientationListener extends Activity {

    private static final String TAG = "ScreenOrientationListener";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mContext = this;

        setContentView(R.layout.main);

        startService( new Intent(this, MyService.class) );
    }
}

这里是MyService类的实现

public class MyService extends Service {
    private static final String TAG = "MyService";

    private static final String BCAST_CONFIGCHANGED = "android.intent.action.CONFIGURATION_CHANGED";
    private static Context mContext;

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

    @Override
    public void onCreate() {
        Log.d(TAG, "onCreate()");

        mContext = this;

        IntentFilter filter = new IntentFilter();
        filter.addAction(BCAST_CONFIGCHANGED);
        this.registerReceiver(mBroadcastReceiver, filter);
    }

    @Override
    public void onDestroy() {           
        Log.d(TAG, "onDestroy()");
        //Unregister receiver to avoid memory leaks
        mContext.unregisterReceiver(mBroadcastReceiver);
    }

    @Override
    public void onStart(Intent intent, int startid) {
        Log.d(TAG, "onStart()");
    }

    public BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent myIntent) {

            if ( myIntent.getAction().equals( BCAST_CONFIGCHANGED ) ) {

                Log.d(TAG, "received->" + BCAST_CONFIGCHANGED);


                if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
                    // it's Landscape
                    Log.d(TAG, "LANDSCAPE");
                }
                else {
                    Log.d(TAG, "PORTRAIT");
                }
            }
        }
    };
}

这里是在清单文件中定义MyService的部分。

<!-- Services -->
        <service android:enabled="true"  android:name="com.wareninja.android.external.screenorientationlistener.services.MyService">
            <intent-filter>
                <action android:name="android.intent.action.CONFIGURATION_CHANGED"/>
            </intent-filter>
        </service>

问题是只有在应用程序支持旋转的情况下才能起作用。因此,如果您的启动器不支持横向旋转,则无法从服务中使用它。我猜测可以使用传感器来获取它,但我不确定具体怎么做。 - Archimedes Trajano
@WareNinja:如果用户通过在通知栏中点击“自动旋转”按钮手动更改了方向,则以上内容无效。 - ChuongPham
@ChuongPham:自动旋转和手动更改方向?您能否详细解释一下,因为您之前的表述有些令人困惑。 - xmen

2
你可以创建一个BroadcastReceiver来监听Intent.ACTION_CONFIGURATION_CHANGED(android.intent.action.CONFIGURATION_CHANGED)。
注意,它确实说:

您不能通过清单中声明的组件接收此内容,只能通过使用Context.registerReceiver()显式注册来接收。

这意味着您无法在清单文件中注册接收器。您需要在代码中注册它。
然后获取配置并检查方向是否与Floern所述相同。

可以在appwidgetprovider中使用_Intent.ACTION_CONFIGURATION_CHANGED_吗,因为它是一个修改后的广播接收器?我猜想不行。当我创建广播接收器时,我需要在某个地方启动它,还是它会自动启动当我的小工具启动时? - Dysen
我终于弄清楚了如何实现你所说的内容。我的下一个问题是,为什么要在服务中注册接收器?服务注册后不会退出吗?我能在widgetconfiguration活动中注册接收器吗?注册广播接收器的实体必须保持在内存中才能运行吗? - Dysen
@Dysen,你能提供一些示例代码吗?我已经尝试实现上述内容,但在Android模拟器中无法工作。 - Raghav Satyadev

1
我建议您使用OrientationEventListener对象。它完全符合您所寻找的,并且未被弃用。自API级别3以来就一直存在。

2
如果用户通过通知栏中的“自动旋转”按钮手动更改了方向并将手机平放在表面上,则OrientationEventListener将无法工作。只有当用户拿起手机并移动/旋转它时,它才能正常工作。 - ChuongPham

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接