Tips for Implementing with Android

When implementing your mobile app on Android, pay attention to the following tips.

Saving and restoring the Kii state

The Android system will reconstruct a mobile app and activity instance when the mobile app is moved into the background or when the language setting is changed. If this happens, the information Kii Cloud SDK stores in memory, including the information about the currently logged-in user, will be lost.

If you want to restore such information upon the reconstruction, please execute the Kii#onSaveInstanceState method in the target activity's Activity#onSaveInstanceState. This will save the information and later pass it to the Activity#onCreate when the instance is recreated.

To restore the information and load it to Kii Cloud SDK, just execute the Kii#onRestoreInstanceState method.

Here is an example of saving and restoring the state Kii Cloud SDK stores in memory.

public class AppActivity extends Activity {

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

    // Restore the Kii state information.
    Kii.onRestoreInstanceState(savedInstanceState);

    setContentView(R.layout.activity_second);
  }

  @Override
  protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    // Save the Kii state information.
    Kii.onSaveInstanceState(outState);
  }

}

Note: This feature uses "com.kii.cloud.storage.*" as a Bundle key. If you are storing states of other instances in Activity#onSaveInstanceState, please make sure not to use this key for them.

In the above example, we are restoring the state in Activity#onCreate. You can also restore it in Activity#onRestoreInstanceState.

To learn more about the activity lifecycle in Android, see Managing the Activity Lifecycle by Google.

Getting runtime permissions

A mechanism for requesting permission at runtime is introduced in Android 6.0 (API level 23 and later).

Kii Cloud accesses an external storage when uploading and downloading object bodies. If you specify a directory other than the application data directory (under /Android/data/_package_name_), you need to get permissions from a user.

If you are using an environment earlier than Android 6.0, you just need to Update the AndroidManifest.xml when you add the Kii Cloud SDK. If you are using Android 6.0 or later, you also need to implement a process for displaying a user interface to get the user's permission at runtime.

The following sample code will get the WRITE_EXTERNAL_STORAGE permisson at runtime. You can get the READ_EXTERNAL_STORAGE permission in the same manner.

int permission = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permission != PackageManager.PERMISSION_GRANTED) {
  ActivityCompat.requestPermissions(this,
       new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE },
       REQUEST_CODE_PERMISSION);
} else {
  // The user granted the permission.
}

The snippet first checks if the permission is already granted with the checkSelfPermission() method. The permission is not granted if the returned value is not PackageManager.PERMISSION_GRANTED, so the snippet executes the requestPermissions() method to show a user interface for getting the permission.

Note that this in the sample code represents the Activity's instance.

The REQUEST_CODE_PERMISSION is a request code that will be passed to the onRequestPermissionsResult() method when the user input is returned. Use the value that does not collide with other request codes.

private static final REQUEST_CODE_PERMISSION = 1000;

When the requestPermissions() method is executed, the user will be asked on the screen to select if he would grant or deny the permission. The user response is notified with the onRequestPermissionsResult() method.

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
  switch (requestCode) {
    case REQUEST_CODE_PERMISSION: {
      if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        // The user granted the permission.
      } else {
        // The user canceled the choice or denied the permission.
      }
      return;
    }
  }
}

Confirm that the request code passed to the method is the same as the one that you have specified in the requestPermissions() method. If they are the same, check the result of the permission request.

If the grantResults is an array with the length 0, it means that the user has either cancelled the choice or denied the request. If the array length is greater than 0 and has the value PackageManager.PERMISSION_GRANTED, it means that the user has granted the permission.

In the above snippets, blocks with the comment // The user granted the permission. correspond to the situations in which the user grants the permission; therefore, you can access object bodies. In blocks where the permission is not granted, it is ideal not to execute the object body related API since the API will return an error.

For more information such as using the shouldShowRequestPermissionRationale() method for presenting the rationale for asking the permission, see the Google official documenation.