如何从状态栏检测屏幕方向变化

4
在状态栏下面有五个按钮——Wifi、蓝牙、GPS、静音模式和自动旋转。我还没有找到一种方法来检测用户何时单击自动旋转按钮。
我已经编写了一个服务来监听方向变化,例如:
public class MyService extends Service {

    @Override
    public void onCreate() {
       super.onCreate();
       IntentFilter intentFilter = new IntentFilter();
       intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
       this.registerReceiver(myReceiver, intentFilter);     
    }

    public BroadcastReceiver myReceiver = new BroadcastReceiver() {
       @Override
       public void onReceive(Context context, Intent intent) {
          if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
             // Show a message about orientation changes.
             // This method is only called when the phone is physically rotated.
          }
       }
    }  
}

以上的BroadcastReceiver仅在手机被物理旋转时才起作用,但如果点击自动旋转按钮而没有任何物理旋转,则不会调用BroadcastReceiver方法。

我也尝试了OrientationEventListener - 但与BroadcastReceiver方法相同。

为了设置方向,我使用了以下方法:

Settings.System.getInt(context.getContentResolver(), "accelerometer_rotation")

我知道有一种方法可以查询系统设置。是否有一个Intent来拦截系统设置的[方向]更改?我已经查阅了Android文档,但找不到这样的Intent - 也许是我在错的地方寻找,或者确实没有相关的Intent。
有人知道如何捕获状态栏中“自动旋转”按钮的更改吗?
更新1:我正在使用的设备是:三星Galaxy S3,三星Galaxy S2,三星Galaxy S和三星Galaxy Ace等许多其他设备。所有这些设备都运行着原始的ROM,并在状态栏下具有“自动旋转”按钮。
更新2:有建议建议使用ContentObserver来监听对系统设置的更改,例如:
public class SettingsContentObserver extends ContentObserver {
    public SettingsContentObserver(Handler handler) {
       super(handler);
    }

    @Override
    public boolean deliverSelfNotifications() {
       return super.deliverSelfNotifications(); 
    }

    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        Logging.writeDebug("Settings change detected: " + selfChange);
    }

    public void registerContentObserver(Context context) {
        context.getContentResolver().registerContentObserver(Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION), true, this);
    }

    public void unregisterContentObserver(Context context) {
       context.getContentResolver().unregisterContentObserver(this);
    }
}

然而,我发现在onChange方法中的selfChange变量总是返回false

1
原生AOSP Android系统中没有您在状态栏中描述的按钮。如果您能提供您所使用的设备型号,那将会更有帮助。 - adamp
@ChuongPham:我和你遇到了同样的问题。你有解决方案吗?请分享给我。谢谢。 - Huy Duong Tu
@HuyDuongTu:请在帖子中查看我的代码。那就是你需要的全部。 - ChuongPham
谢谢你的回复。我已经找到了解决方案。:) - Huy Duong Tu
根据我的经验,系统设置中的自动旋转开关影响的不仅仅是ACCELEROMETER_ROTATION。具体来说:如果您打开开关,它会将ACCELEROMETER_ROTATION设置为1;如果您关闭开关,它会将ACCELEROMETER_ROTATION设置为0 并将USER_ROTATION设置为ROTATION_0。它甚至可能会做更多——很难确定。 - Don Hatch
显示剩余8条评论
1个回答

13

我猜你需要监听Settings.System.ACCELEROMETER_ROTATION。没试过但应该可以工作。

getContentResolver().registerContentObserver(Settings.System.getUriFor
(Settings.System.ACCELEROMETER_ROTATION),
true,contentObserver);

编辑: 就像BroadcastReceiver的OnReceive一样,ContentObserver也有一个OnChange方法。所以每当按钮被点击时,你会在这里得到一个回调。

private ContentObserver contentObserver = new ContentObserver(new Handler()) {
        @Override
        public void onChange(boolean selfChange) {
           // show a toast here
        }
};

@@nandeesh:你能详细说明一下你的答案吗?上面只是用于注册内容观察器。从内容观察器中获取结果使用了哪些方法?这在你的回答中并不清楚。 - ChuongPham
感谢您的回复,@nandeesh。但是,我将ContentObserver分离成一个单独的类,并在主活动中调用它(请参见上面的UPDATE 2)。我注意到onChange方法中的selfChange变量总是返回false。这不对,是吗? - ChuongPham
1
selfchange 表示是否是您自己的应用程序更改了它。在您的情况下,由于您正在状态栏中更改它,因此这将返回 false。您需要再次查询 URI 以了解当前状态。 - nandeesh
你是指在 "onChange" 方法中再次执行 Settings.System.ACCELEROMETER_ROTATION 吗? - ChuongPham
2
嗯,执行以下代码 Settings.System.getInt(context.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) ,以获取当前值。 - nandeesh
好的,谢谢,nandeesh。我明白了。我已将您的答案标记为正确。希望Google在未来的SDK版本中能够使这更容易。Android还有很长的路要走... - ChuongPham

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