4

Under the Statusbar, there are five buttons - Wifi, Bluetooth, GPS, Silent Mode and Auto Rotation. I haven't figured out a way yet to detect when a user click the Auto Rotation button.

What I have done is have a Service that listen for orientation changes, like:

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.
          }
       }
    }  
}

The above BroadcastReceiver will only work if the phone is physically rotated, but if the Auto Rotation button is clicked without any physical rotation of the phone, then the BroadcastReceiver method is never called.

I have also tried OrientationEventListener - but same behaviour as the BroadcastReceiver method.

To set orientation, I used the following method:

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

So I know there's a method to interrogate System settings. Is there an Intent that traps system setting's [orientation] changes? I've gone through Android docs but can't find one - perhaps, I'm looking in the wrong place, or there's no Intent for it.

Does anyone know a way to trap changes to the Auto Rotation button in the Statusbar?

UPDATE 1: The devices I'm working with are: Samsung Galaxy S3, Samsung Galaxy S2, Samsung Galaxy S and Samsung Galaxy Ace and many other. All of these devices are running stock ROM and have the Auto Rotation button under the Statusbar.

UPDATE 2: There have been suggestions advising to use the ContentObserver to listen for changes to system setting, for example:

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

However, I found that the selfChange variable in onChange method always return false.

ChuongPham
  • 4,761
  • 8
  • 43
  • 53
  • 1
    Stock AOSP Android does not have the buttons you describe in the status bar. It might be helpful if you mentioned the device you're working with. – adamp Aug 19 '12 at 18:06
  • @adamp: See updated info in my question above. – ChuongPham Aug 19 '12 at 18:09
  • Does an actual orientation change result from clicking that button (does it reset to a default/natural orientation?) or does it simply lock the device to the current orientation? If the latter, it sounds like the behavior you're observing is working as intended - you're not getting orientation change events because the orientation has been locked and it isn't changing. What are you trying to accomplish? – adamp Aug 19 '12 at 18:14
  • @adamp: No orientation is "visible" until the phone is physically orientated but it's enabled nevertheless when the button is clicked. Clicking the Auto Rotation button is the same as [on ICS 4.0.3] clicking the Settings | Display | Auto-rotate screen checkbox. I'm trying to detect when orientation is enabled/disabled to provide a message via the TextView object in my app. I hope that makes sense. – ChuongPham Aug 19 '12 at 18:20
  • If you want to monitor changes of that setting: http://stackoverflow.com/questions/6190779/monitor-android-system-settings-values – zapl Aug 19 '12 at 18:48
  • @zapl: Could you explain the relevancy of the link you provided? How is the ContentObserver class related to system setting. I don't get it... – ChuongPham Aug 20 '12 at 03:42
  • @Chuong see @nandeesh answer. Settings are stored in a database exposed via a `ContentProvider`. Using a `ContentObserver` you can listen for changes of the data and hence the settings. If you like to do something when the user enables / disables the autorotation that's the way to go. – zapl Aug 20 '12 at 08:50
  • @zapl: Thanks for your reply. Maybe an example of how his method actually work might help. What he has is basically for registering the content observer. What are other steps needed to intercept changes to system settings wrt orientation? Any changes required in AndroidManifest.xml, etc? This part is not clear from his answer below. – ChuongPham Aug 20 '12 at 10:19
  • @ChuongPham: I'm facing the same issue as you. Did you have the solution? Please share this to me. Thanks – Huy Duong Tu Dec 23 '13 at 16:40
  • @HuyDuongTu: See my codes in the post. That's all you need. – ChuongPham Dec 25 '13 at 13:52
  • Thanks for replying me. I found the solution.:) – Huy Duong Tu Dec 25 '13 at 15:26
  • I have been looking for a way to do this. –  Apr 30 '15 at 16:04
  • In my experience, the autorotate toggle in system settings affects more than just ACCELEROMETER_ROTATION. Specifically: if you turn on the toggle, it sets ACCELEROMETER_ROTATION to 1; if you turn off the toggle, it sets ACCELEROMETER_ROTATION to 0 *and sets USER_ROTATION to ROTATION_0*. It might even do more than that-- hard to tell. – Don Hatch Apr 08 '17 at 10:28

1 Answers1

13

I guess you will have to listen for Settings.System.ACCELEROMETER_ROTATION. Havent tried but this should work.

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

Edit: Just like Onrecieve of BroadcastReceiver there is a onchange of contentobserver. SO whenever the button is clicked you will get a callback here.

private ContentObserver contentObserver = new ContentObserver(new Handler()) {
        @Override
        public void onChange(boolean selfChange) {
           // show a toast here
        }
};
nandeesh
  • 24,740
  • 6
  • 69
  • 79
  • @@nandeesh: Can you elaborate on your answer? The above is just for registering a content observer. What are the methods used to derive the result from the content observer? This is not clear from your answer. – ChuongPham Aug 20 '12 at 10:21
  • Thanks for your reply, @nandeesh. However, I separated the ContentObserver into a separate class and called it in main activity (See UPDATE 2 above). I noticed that the `selfChange` variable in `onChange` method always return `false`. This is not right, is it? – ChuongPham Aug 20 '12 at 11:23
  • 1
    selfchange indicates, that whether your own app changed it. In your case since you are changing it in statusbar , this will return false. You will have to query uri again to know the current status – nandeesh Aug 20 '12 at 11:27
  • You mean doing this `Settings.System.ACCELEROMETER_ROTATION` again in the `onChange` method? – ChuongPham Aug 20 '12 at 11:31
  • 2
    yeah doing this Settings.System.getInt(context.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) , to get the current value – nandeesh Aug 20 '12 at 11:45
  • OK, thanks, nandeesh. I got it. Have marked your answer as correct. I hope Google can make this easier in future SDK releases. Guess Android has a long way to go yet... – ChuongPham Aug 20 '12 at 11:59