Merge pull request #374 from NativeScript/android-activity-events

Android activity events
This commit is contained in:
Vladimir Enchev
2015-07-01 16:03:22 +03:00
4 changed files with 226 additions and 17 deletions

View File

@ -11,17 +11,28 @@ var callbacks = android.app.Application.ActivityLifecycleCallbacks;
export var mainModule: string; export var mainModule: string;
export var androidActivityCreatedEvent = "androidActivityCreated";
export var androidActivityDestroyedEvent = "androidActivityDestroyed";
export var androidActivityStartedEvent = "androidActivityStarted";
export var androidActivityPausedEvent = "androidActivityPaused";
export var androidActivityResumedEvent = "androidActivityResumed";
export var androidActivityStoppedEvent = "androidActivityStopped";
export var androidSaveActivityStateEvent = "androidSaveActivityState";
export var androidActivityResultEvent = "androidActivityResult";
// We are using the exports object for the common events since we merge the appModule with this module's exports, which is what users will receive when require("application") is called; // We are using the exports object for the common events since we merge the appModule with this module's exports, which is what users will receive when require("application") is called;
// TODO: This is kind of hacky and is "pure JS in TypeScript" // TODO: This is kind of hacky and is "pure JS in TypeScript"
var initEvents = function () { var initEvents = function () {
var androidApp: AndroidApplication = exports.android; var androidApp: dts.AndroidApplication = exports.android;
// TODO: Verify whether the logic for triggerring application-wide events based on Activity callbacks is working properly // TODO: Verify whether the logic for triggerring application-wide events based on Activity callbacks is working properly
var lifecycleCallbacks = new callbacks({ var lifecycleCallbacks = new callbacks({
onActivityCreated: function (activity: any, bundle: any) { onActivityCreated: function (activity: any, bundle: any) {
if (!androidApp.startActivity) { if (!androidApp.startActivity) {
androidApp.startActivity = activity; androidApp.startActivity = activity;
exports.notify(<dts.AndroidActivityBundleEventData>{ eventName: androidActivityCreatedEvent, object: androidApp, activity: activity, bundle: bundle });
if (androidApp.onActivityCreated) { if (androidApp.onActivityCreated) {
androidApp.onActivityCreated(activity, bundle); androidApp.onActivityCreated(activity, bundle);
} }
@ -29,6 +40,7 @@ var initEvents = function () {
androidApp.currentContext = activity; androidApp.currentContext = activity;
}, },
onActivityDestroyed: function (activity: any) { onActivityDestroyed: function (activity: any) {
// Clear the current activity reference to prevent leak // Clear the current activity reference to prevent leak
if (activity === androidApp.foregroundActivity) { if (activity === androidApp.foregroundActivity) {
@ -44,11 +56,13 @@ var initEvents = function () {
exports.onExit(); exports.onExit();
} }
exports.notify({ eventName: dts.exitEvent, object: androidApp, android: activity }); exports.notify(<dts.ApplicationEventData>{ eventName: dts.exitEvent, object: androidApp, android: activity });
androidApp.startActivity = undefined; androidApp.startActivity = undefined;
} }
exports.notify(<dts.AndroidActivityEventData>{ eventName: androidActivityDestroyedEvent, object: androidApp, activity: activity });
if (androidApp.onActivityDestroyed) { if (androidApp.onActivityDestroyed) {
androidApp.onActivityDestroyed(activity); androidApp.onActivityDestroyed(activity);
} }
@ -56,47 +70,60 @@ var initEvents = function () {
// TODO: This is a temporary workaround to force the V8's Garbage Collector, which will force the related Java Object to be collected. // TODO: This is a temporary workaround to force the V8's Garbage Collector, which will force the related Java Object to be collected.
gc(); gc();
}, },
onActivityPaused: function (activity: any) { onActivityPaused: function (activity: any) {
if (activity === androidApp.foregroundActivity) { if (activity === androidApp.foregroundActivity) {
if (exports.onSuspend) { if (exports.onSuspend) {
exports.onSuspend(); exports.onSuspend();
} }
exports.notify({ eventName: dts.suspendEvent, object: androidApp, android: activity }); exports.notify(<dts.ApplicationEventData>{ eventName: dts.suspendEvent, object: androidApp, android: activity });
} }
exports.notify(<dts.AndroidActivityEventData>{ eventName: androidActivityPausedEvent, object: androidApp, activity: activity });
if (androidApp.onActivityPaused) { if (androidApp.onActivityPaused) {
androidApp.onActivityPaused(activity); androidApp.onActivityPaused(activity);
} }
}, },
onActivityResumed: function (activity: any) { onActivityResumed: function (activity: any) {
if (activity === androidApp.foregroundActivity) { if (activity === androidApp.foregroundActivity) {
if (exports.onResume) { if (exports.onResume) {
exports.onResume(); exports.onResume();
} }
exports.notify({ eventName: dts.resumeEvent, object: androidApp, android: activity }); exports.notify(<dts.ApplicationEventData>{ eventName: dts.resumeEvent, object: androidApp, android: activity });
} }
exports.notify(<dts.AndroidActivityEventData>{ eventName: androidActivityResumedEvent, object: androidApp, activity: activity });
if (androidApp.onActivityResumed) { if (androidApp.onActivityResumed) {
androidApp.onActivityResumed(activity); androidApp.onActivityResumed(activity);
} }
}, },
onActivitySaveInstanceState: function (activity: any, bundle: any) { onActivitySaveInstanceState: function (activity: any, bundle: any) {
exports.notify(<dts.AndroidActivityBundleEventData>{ eventName: androidSaveActivityStateEvent, object: androidApp, activity: activity, bundle: bundle });
if (androidApp.onSaveActivityState) { if (androidApp.onSaveActivityState) {
androidApp.onSaveActivityState(activity, bundle); androidApp.onSaveActivityState(activity, bundle);
} }
}, },
onActivityStarted: function (activity: any) { onActivityStarted: function (activity: any) {
androidApp.foregroundActivity = activity; androidApp.foregroundActivity = activity;
exports.notify(<dts.AndroidActivityEventData>{ eventName: androidActivityStartedEvent, object: androidApp, activity: activity });
if (androidApp.onActivityStarted) { if (androidApp.onActivityStarted) {
androidApp.onActivityStarted(activity); androidApp.onActivityStarted(activity);
} }
}, },
onActivityStopped: function (activity: any) { onActivityStopped: function (activity: any) {
exports.notify(<dts.AndroidActivityEventData>{ eventName: androidActivityStoppedEvent, object: androidApp, activity: activity });
if (androidApp.onActivityStopped) { if (androidApp.onActivityStopped) {
androidApp.onActivityStopped(activity); androidApp.onActivityStopped(activity);
} }

View File

@ -3,7 +3,6 @@
*/ */
declare module "application" { declare module "application" {
import cssSelector = require("ui/styling/css-selector"); import cssSelector = require("ui/styling/css-selector");
import observable = require("data/observable");
/** /**
* An extended JavaScript Error which will have the nativeError property initialized in case the error is caused by executing platform-specific code. * An extended JavaScript Error which will have the nativeError property initialized in case the error is caused by executing platform-specific code.
@ -48,7 +47,7 @@ declare module "application" {
/** /**
* Event data containing information for the application events. * Event data containing information for the application events.
*/ */
export interface ApplicationEventData extends observable.EventData { export interface ApplicationEventData {
/** /**
* Gets the native iOS event arguments. Valid only when running on iOS. * Gets the native iOS event arguments. Valid only when running on iOS.
*/ */
@ -58,6 +57,15 @@ declare module "application" {
* Gets the native Android event arguments. Valid only when running on Android. * Gets the native Android event arguments. Valid only when running on Android.
*/ */
android?: any; android?: any;
/**
* The name of the event.
*/
eventName: string;
/**
* The instance that has raised the event.
*/
object: any;
} }
/** /**
@ -140,7 +148,7 @@ declare module "application" {
* Notifies all the registered listeners for the event provided in the data.eventName. * Notifies all the registered listeners for the event provided in the data.eventName.
* @param data The data associated with the event. * @param data The data associated with the event.
*/ */
export function notify(data: ApplicationEventData): void; export function notify(data: any): void;
/** /**
* Checks whether a listener is registered for the specified event name. * Checks whether a listener is registered for the specified event name.
@ -151,32 +159,32 @@ declare module "application" {
/** /**
* This event is raised on application launchEvent. * This event is raised on application launchEvent.
*/ */
export function on(event: "onLaunch", callback: (args: any) => void, thisArg?: any); export function on(event: "onLaunch", callback: (args: ApplicationEventData) => void, thisArg?: any);
/** /**
* This event is raised when an uncaught error occurs while the application is running. * This event is raised when an uncaught error occurs while the application is running.
*/ */
export function on(event: "onUncaughtError", callback: (args: any) => void, thisArg?: any); export function on(event: "onUncaughtError", callback: (args: ApplicationEventData) => void, thisArg?: any);
/** /**
* This event is raised when the Application is suspended. * This event is raised when the Application is suspended.
*/ */
export function on(event: "onSuspend", callback: (args: any) => void, thisArg?: any); export function on(event: "onSuspend", callback: (args: ApplicationEventData) => void, thisArg?: any);
/** /**
* This event is raised when the Application is resumed after it has been suspended. * This event is raised when the Application is resumed after it has been suspended.
*/ */
export function on(event: "onResume", callback: (args: any) => void, thisArg?: any); export function on(event: "onResume", callback: (args: ApplicationEventData) => void, thisArg?: any);
/** /**
* This event is raised when the Application is about to exitEvent. * This event is raised when the Application is about to exitEvent.
*/ */
export function on(event: "onExit", callback: (args: any) => void, thisArg?: any); export function on(event: "onExit", callback: (args: ApplicationEventData) => void, thisArg?: any);
/** /**
* This event is raised when there is low memory on the target device. * This event is raised when there is low memory on the target device.
*/ */
export function on(event: "onLowMemory", callback: (args: any) => void, thisArg?: any); export function on(event: "onLowMemory", callback: (args: ApplicationEventData) => void, thisArg?: any);
/** /**
* This is the Android-specific application object instance. * This is the Android-specific application object instance.
@ -192,10 +200,140 @@ declare module "application" {
*/ */
export var ios: iOSApplication; export var ios: iOSApplication;
/**
* Data for the Android activity events.
*/
export interface AndroidActivityEventData {
/**
* The activity.
*/
activity: android.app.Activity;
/**
* The name of the event.
*/
eventName: string;
/**
* The instance that has raised the event.
*/
object: any;
}
/**
* Data for the Android activity events with bundle.
*/
export interface AndroidActivityBundleEventData extends AndroidActivityEventData {
/**
* The bundle.
*/
bundle: android.os.Bundle;
}
/**
* Data for the Android activity result event.
*/
export interface AndroidActivityResultEventData extends AndroidActivityEventData {
/**
* The request code.
*/
requestCode: number;
/**
* The result code.
*/
resultCode: number;
/**
* The intent.
*/
intent: android.content.Intent;
}
/**
* This event is raised on android application ActivityCreated.
*/
export function on(event: "activityCreated", callback: (args: AndroidActivityBundleEventData) => void, thisArg?: any);
/**
* This event is raised on android application ActivityDestroyed.
*/
export function on(event: "activityDestroyed", callback: (args: AndroidActivityEventData) => void, thisArg?: any);
/**
* This event is raised on android application ActivityStarted.
*/
export function on(event: "activityStarted", callback: (args: AndroidActivityEventData) => void, thisArg?: any);
/**
* This event is raised on android application ActivityPaused.
*/
export function on(event: "activityPaused", callback: (args: AndroidActivityEventData) => void, thisArg?: any);
/**
* This event is raised on android application ActivityResumed.
*/
export function on(event: "activityResumed", callback: (args: AndroidActivityEventData) => void, thisArg?: any);
/**
* This event is raised on android application ActivityStopped.
*/
export function on(event: "activityStopped", callback: (args: AndroidActivityEventData) => void, thisArg?: any);
/**
* This event is raised on android application SaveActivityState.
*/
export function on(event: "saveActivityState", callback: (args: AndroidActivityBundleEventData) => void, thisArg?: any);
/**
* This event is raised on android application ActivityResult.
*/
export function on(event: "activityResult", callback: (args: AndroidActivityResultEventData) => void, thisArg?: any);
/**
* String value used when hooking to ActivityCreated event.
*/
export var androidActivityCreatedEvent: string;
/**
* String value used when hooking to ActivityDestroyed event.
*/
export var androidActivityDestroyedEvent: string;
/**
* String value used when hooking to ActivityStarted event.
*/
export var androidActivityStartedEvent: string;
/**
* String value used when hooking to ActivityPaused event.
*/
export var androidActivityPausedEvent: string;
/**
* String value used when hooking to ActivityResumed event.
*/
export var androidActivityResumedEvent: string;
/**
* String value used when hooking to ActivityStopped event.
*/
export var androidActivityStoppedEvent: string;
/**
* String value used when hooking to SaveActivityState event.
*/
export var androidSaveActivityStateEvent: string;
/**
* String value used when hooking to ActivityResult event.
*/
export var androidActivityResultEvent: string;
/** /**
* The abstraction of an Android-specific application object. * The abstraction of an Android-specific application object.
*/ */
export interface AndroidApplication { export class AndroidApplication {
/** /**
* The [android Application](http://developer.android.com/reference/android/app/Application.html) object instance provided to the init of the module. * The [android Application](http://developer.android.com/reference/android/app/Application.html) object instance provided to the init of the module.
*/ */

View File

@ -1,6 +1,7 @@
import application = require("application"); import application = require("application");
application.mainModule = "app/mainPage"; application.mainModule = "app/mainPage";
// Common events for both Android and iOS.
application.on(application.launchEvent, function (args: application.ApplicationEventData) { application.on(application.launchEvent, function (args: application.ApplicationEventData) {
if (args.android) { if (args.android) {
// For Android applications, args.android is an android.content.Intent class. // For Android applications, args.android is an android.content.Intent class.
@ -61,4 +62,38 @@ application.on(application.uncaughtErrorEvent, function (args: application.Appli
} }
}); });
// Android activity events
application.on(application.androidActivityCreatedEvent, function (args: application.AndroidActivityBundleEventData) {
console.log("Event: " + args.eventName + ", Activity: " + args.activity + ", Bundle: " + args.bundle);
});
application.on(application.androidActivityDestroyedEvent, function (args: application.AndroidActivityEventData) {
console.log("Event: " + args.eventName + ", Activity: " + args.activity);
});
application.on(application.androidActivityPausedEvent, function (args: application.AndroidActivityEventData) {
console.log("Event: " + args.eventName + ", Activity: " + args.activity);
});
application.on(application.androidActivityResultEvent, function (args: application.AndroidActivityResultEventData) {
console.log("Event: " + args.eventName + ", Activity: " + args.activity +
", requestCode: " + args.requestCode + ", resultCode: " + args.resultCode + ", Intent: " + args.intent);
});
application.on(application.androidActivityResumedEvent, function (args: application.AndroidActivityEventData) {
console.log("Event: " + args.eventName + ", Activity: " + args.activity);
});
application.on(application.androidActivityStartedEvent, function (args: application.AndroidActivityEventData) {
console.log("Event: " + args.eventName + ", Activity: " + args.activity);
});
application.on(application.androidActivityStoppedEvent, function (args: application.AndroidActivityEventData) {
console.log("Event: " + args.eventName + ", Activity: " + args.activity);
});
application.on(application.androidSaveActivityStateEvent, function (args: application.AndroidActivityBundleEventData) {
console.log("Event: " + args.eventName + ", Activity: " + args.activity + ", Bundle: " + args.bundle);
});
application.start(); application.start();

View File

@ -426,6 +426,15 @@ var NativeActivity = {
if (result) { if (result) {
result(requestCode, resultCode, data); result(requestCode, resultCode, data);
} }
application.notify(<application.AndroidActivityResultEventData>{
eventName: application.androidActivityResultEvent,
object: application.android,
activity: this,
requestCode: requestCode,
resultCode: resultCode,
intent: data
});
}, },
onAttachFragment: function (fragment: android.app.Fragment) { onAttachFragment: function (fragment: android.app.Fragment) {