Monday 1 December 2014

Resolving Last ShutDown State (Normal or Abrupt)

This blog post is about how to resolve if the last device shutdown happened normally or abruptly.

Actually the problem with which this post was started was to check in an application whether the last shutdown happened abruptly with a battery detachment.

But since there is no broadcast intent available to check for the  battery detachments. It means there is no direct way to deduce whether the last shutdown was caused by detaching battery from the device.

So we started to reduce the problem firstly to check if the last state was simply normal or abrupt. And then in later posts if possible finding the reason for the abrupt shutdown was due to the detaching of battery.

The two parts are :
1. First part mainly deals with the checking of the app that whether the last shutdown was successful or not.
2. Second part mainly deals with checking if last shutdown was abrupt and was due to battery detachment

Here in this post we will only deal with the first part.

Important point :
This investigative implementation is totally based upon the fact that the intent with action ACTION_SHUTDOWN is never called by the system before going dead when it happens abruptly.

We can accomplish the first problem of resolving reason of shutdown by implementing BroadcastReceiver that listens for two broadcast intents with actions namely ACTION_SHUTDOWN and BOOT_COMPLETED.

We will be achieving our this task by saving a value (currently in Preferences) when system sends broadcast for ACTION_SHUTDOWN and checking its value when device is rebooted and system send a broadcast for BOOT_COMPLETED.

Implemented classes are :

BroadcastReceiver

public class DisconnectReceiver extends BroadcastReceiver
{
 @Override
 public void onReceive(Context context, Intent intent)
 {
  if (intent.getAction().equalsIgnoreCase(Intent.ACTION_BOOT_COMPLETED))
  {
   int shutDownCode = PreferenceManager.getDefaultSharedPreferences(DroidApplication.getsContext()).getInt(
     DisconnectConstants.KEY_NORMAL, 0);

   // Checking for the last shutdown value (1 = Normal ShutDown and 0 = Abrupt ShutDown )
   if (shutDownCode == 1)
   {
    // Reset the last value
    Editor editor = PreferenceManager.getDefaultSharedPreferences(DroidApplication.getsContext()).edit();
    editor.putInt(DisconnectConstants.KEY_NORMAL, 0);
    editor.commit();

    // TODO Here goes the user code to be implemented 
    
   }
   else if (shutDownCode == 0)
   {
    // TODO Here goes the user code to be implemented 
    
   }
  }
  else if (intent.getAction().equalsIgnoreCase(Intent.ACTION_SHUTDOWN))
  {
   // Saving value in Preferences for ShutDown broadcast
   Editor editor = PreferenceManager.getDefaultSharedPreferences(DroidApplication.getsContext()).edit();
   editor.putInt(DisconnectConstants.KEY_NORMAL, 1);
   editor.commit();
  }
 }
}

Changes in AndroidManifest.xml

Under <manifest> tag

<!-- Permission for getting RECEIVE_BOOT_COMPLETED -->
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

Under <application> tag

<!-- Receiver to checks for broadcast for ACTIONs : ACTION_SHUTDOWN and ACTION_BOOT_COMPLETED -->
 <receiver android:name="com.droidutility.disconnect.utils.DisconnectReceiver" >
  <intent-filter>
   <action android:name="android.intent.action.ACTION_SHUTDOWN" />
   <action android:name="android.intent.action.BOOT_COMPLETED" />
  </intent-filter>
 </receiver>


 
 
Please check here the code added in a library project with usage instructions in README.md.