Multi Window Support in Android N

Android N adds support for displaying more than one app at the same time. On handheld devices, two apps can run side-by-side or one-above-the-other in split-screen mode. On TV devices, apps can use picture-in-picture mode to continue video playback while users are interacting with another app.
In below picture, you can see two apps running side by side.


Multi-window mode does not change the activity life cycle.

In multi-window mode, an app can be in the paused state and still be visible to the user. An app might need to continue its activities even while paused. For example, a video-playing app that is in paused mode but is visible should continue showing its video. For this reason, we recommend that activities that play video not pause the video in their onPause() handlers. Instead, they should pause video in onStop(), and resume playback in onStart().


If the app declares a fixed orientation, you should attempt to put the app in multi-window mode. Verify that when you do so, the app remains in full-screen mode.

API:
  • android:resizeableActivity=["true" | "false"]
  • android:supportsPictureInPicture=["true" | "false"]
  • Activity.isInMultiWindowMode()
  • Activity.isInPictureInPictureMode()
  • Activity.onMultiWindowModeChanged()
  • Activity.onPictureInPictureModeChanged()
  • Intent.FLAG_ACTIVITY_LAUNCH_TO_ADJACENT
  • ActivityOptions.setLaunchBounds()
  • Layout attributes
How to implement:

By default, Multi window feature will be enabled for all the apps for Android N. You can disable/enable multi window feature with below property.

Set this attribute in your manifest's <activity> or <application> node to enable or disable multi-window display:

             android:resizeableActivity=["true" | "false"]
Test:
    Open the application and go to overview screen(recent screen) long press on the app and drag to highlighted area.

Tizen: Native Application Lifecycle

Every Application (UI application or service application) in an application package can be identified by its own ID.

The following figure shows the UI and service application life-cycle.

Tizen native application can be in one of the several states. Applications can be launched from the user by launcher or by another application.

Apps that use the Native API rely on a series of lifecycle events in order to operate; these events put the app in various states that enable certain controls or operations.

Ready – Application is launched.
Created – Application starts the main loop.
Running – Application is running and visible to the user.
Paused – Application is running but invisible to the user.
Terminated – Application is terminated.


Below are Registering Callbacks for Events:

app_create_cb() Used to take necessary actions before the main event loop starts. Place the UI generation code here to prevent missing any events from your application UI.

app_pause_cb() Used to take necessary actions when the application becomes invisible. For example, release memory resources so other applications can use them. Do not starve the foreground application that is interacting with the user.

app_resume_cb() Used to take necessary actions when the application becomes visible. If you relinquish anything in the app_pause_cb() callback, re-allocate those resources here before the application resumes.

app_terminate_cb() Used to take necessary actions when the application is terminating. Release all resources, especially any allocations and shared resources, so that other running applications can fully use any shared resources.

Application State Transitions:

The Application API defines 5 states with corresponding transition handlers. The state transition is notified through a state transition callback function, whether the application is created, running, paused, resumed, or terminated. The application must react to each state change appropriately.


Tizen: Launching Applications

Application framework starts the application by creating a new process and calling entry point of the application.

The main() function is entry of the application. In the Tizen application, the main task is to hand over control to the application framework by calling the ui_app_main() function

bool app_create(void *user_data)
{
   // Take necessary actions before the main event loop starts
   // Initialize UI resources and application data
   // If this function returns true, the application main loop starts
   // If this function returns false, the application terminates
   return true;
}

void app_control(app_control_h app_control, void *user_data)
{
   // Handle the launch request
}

void app_pause(void *user_data)
{
   // Take necessary actions when application becomes invisible
}

void app_resume(void *user_data)
{
   // Take necessary actions when application becomes visible
}

void app_terminate(void *user_data)
{
   // Release all resources
}

int main(int argc, char *argv[])
{
   struct appdata ad;
 
   ui_app_lifecycle_callback_s event_callback;
     
   event_callback.create = app_create;
   event_callback.terminate = app_terminate;
   event_callback.pause = app_pause;
   event_callback.resume = app_resume;
   event_callback.app_control = app_control;
     
   memset(&ad, 0x0, sizeof(struct appdata));
 
   return ui_app_main(argc, argv, &event_callback, &ad);
}

The App control API provides functions for launching other applications with a specific operation, URI, and MIME type.

To launch an application with the app control API, use one of the following methods:
  • Explicit launch: Launch the application with the application ID.
  • Implicit launch: Launch the application with an operation, URI, or MIME type.
The application launched by the app control can return the result to the caller application



Explicit Launch:


When you request an explicit launch:If the underlying application launcher framework finds an application matched with the given application ID in the installed application list, it launches the application in a new process.

The following code example launches a calculator application explicitly with the application ID:

#include <app.h>
#include <dlog.h>
 
#define TAG "MY_TAG"

app_control_h app_control;
 
app_control_create(&app_control);
app_control_set_operation(app_control, APP_CONTROL_OPERATION_DEFAULT);
app_control_set_app_id(app_control, "org.tizen.calculator");
 
if (app_control_send_launch_request(app_control, NULL, NULL) == APP_CONTROL_ERROR_NONE) 
{
   dlog_print(DLOG_INFO, TAG, "Succeeded to launch a calculator app.");
} 
else 
{
   dlog_print(DLOG_ERROR, TAG, "Failed to launch a calculator app.");
}
 
app_control_destroy(app_control);

Implicit Launch:

When you request an implicit launch: Only 3 data categories are used to determine which application can be launched: Operation, URI scheme, and MIME type.

The application launcher framework iterates the desktop files of installed applications on the device to find applications where the 3 categories are exactly matched.

If only one application is matched for the given categories, that application is launched. If multiple matching applications are found, the application selector is shown and the user can select the proper application.

The following code example launches a camera application with the operation and MIME type:
#include <app.h>
#include <dlog.h>

#define TAG "MY_TAG"

app_control_h app_control;
 
app_control_create(&app_control);
app_control_set_operation(app_control, APP_CONTROL_OPERATION_CREATE_CONTENT);
app_control_set_mime(app_control, "image/jpg");
if (app_control_send_launch_request(app_control, NULL, NULL) == APP_CONTROL_ERROR_NONE) 
{
   dlog_print(DLOG_INFO, TAG, "Succeeded to launch a viewer app.");
} 
else 
{
   dlog_print(DLOG_ERROR, TAG, "Failed to launch a viewer app.");
}
 
app_control_destroy(app_control);

The following code example launches a gallery application with the operation, URI, and MIME type:
#include <app.h>
#include <dlog.h>

#define TAG "MY_TAG"
 
app_control_h app_control;
 
app_control_create(&app_control);
app_control_set_operation(app_control, APP_CONTROL_OPERATION_VIEW);
app_control_set_uri(app_control, "file:///home/myhome/Photos/1_photo.jpg");
app_control_set_mime(app_control, "image/*");
 
if (app_control_send_launch_request(app_control, NULL, NULL) == APP_CONTROL_ERROR_NONE) 
{
   dlog_print(DLOG_INFO, TAG, "Succeeded to launch a viewer app.");
} 
else 
{
   dlog_print(DLOG_ERROR, TAG, "Failed to launch a viewer app.");
}
 
app_control_destroy(app_control);

How to get Results Back:

The app control result from the requested application is delivered to the caller application in the app_control handle with extra data.

The following code example gets the result of an app control request by implementing an app_control result callback:
#include <app.h>
#include <dlog.h>
 
#define TAG "MY_TAG"
 
// Callback function to get result
static void app_control_result(app_control_h request, app_control_h reply, app_control_result_e result, void *user_data) 
{
   char *value;
 
   if (result == APP_CONTROL_RESULT_SUCCEEDED) 
   {
      if (app_control_get_extra_data(reply, APP_CONTROL_DATA_SELECTED, &value) == APP_CONTROL_ERROR_NONE)
      {
         dlog_print(DLOG_INFO, TAG, "[app_control_result_cb] Succeeded: value(%s)", value);
      } 
      else 
      {
         dlog_print(DLOG_ERROR, TAG, "[app_control_result_cb] Failed");
      }
 
   } 
   else 
   {
      dlog_print(DLOG_ERROR, TAG, "[app_control_result_cb] APP_CONTROL_RESULT_FAILED.");
   }
}

Android: Retrieve All the permissions declared in Android Manifest

Using below code you can retrieve all the permissions declared in Android Manifest file.

try { 
PackageInfo pkgInfo = getPackageManager().getPackageInfo(mPkg, PackageManager.GET_PERMISSIONS); 

String[] requestedPermissions = pkgInfo.requestedPermissions; 
if (requestedPermissions == null) { 
       source.setText("No declared permissions"); 
} else { 
       String permissionsText = ""; 
       for (int i = 0; i < pkgInfo.requestedPermissions.length; i++) 
       { 
                 permissionsText += requestedPermissions[i] + "\n"; 
       } 
       source.setText(permissionsText); 
} catch (PackageManager.NameNotFoundException e) {
       source.setText("Package Not Found"); 
}

Android: Snack Bar example

Google released Snackbar component in Android Design support library.

Snackbars are just like Toast messages except they provide action to interact with. Snackbar will be displayed at the bottom of the screen and they automatically time out after the given time length by animating off the screen. In addition, users can swipe them away before the timeout.

Sample code to use Snackbar:
-> add design support library in build.gradle
     compile 'com.android.support:design:22.2.0'

-> Simple Snack Bar:
     Snackbar snackbar = Snackbar .make(coordinatorLayout, "Welcome" ,                         Snackbar.LENGTH_LONG); 
     snackbar.show();

-> Snack Bar with Action: 
     Snackbar snackbar = Snackbar
         .make(coordinatorLayout, "Message is deleted", Snackbar.LENGTH_LONG)
         .setAction("UNDO", new View.OnClickListener() {
            @Override
            public void onClick(View view) {
               Snackbar snackbar1 = Snackbar.make(coordinatorLayout, "Message is                         restored!", Snackbar.LENGTH_SHORT);
               snackbar1.show();
           }
         });
    snackbar.show();


-> Customize Snack Bar:
     Snackbar snackbar = Snackbar
         .make(coordinatorLayout, "Welcome",   Snackbar.LENGTH_LONG)
         .setAction("RETRY", new View.OnClickListener() {
            @Override
             public void onClick(View view) {
             }
         });
       // Changing message text color
      snackbar.setActionTextColor(Color.RED);
      // Changing action button text color
      View view= snackbar.getView();
      TextView textView = (TextView)                                                                        view.findViewById(android.support.design.R.id.snackbar_text);
      textView.setTextColor(Color.YELLOW);
      snackbar.show();