diff --git a/application/application.android.ts b/application/application.android.ts index 9de127b80..54439290b 100644 --- a/application/application.android.ts +++ b/application/application.android.ts @@ -2,6 +2,7 @@ import dts = require("application"); import frame = require("ui/frame"); import types = require("utils/types"); +import observable = require("data/observable"); // merge the exports of the application_common file with the exports of this file declare var exports; @@ -11,17 +12,28 @@ var callbacks = android.app.Application.ActivityLifecycleCallbacks; 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; // TODO: This is kind of hacky and is "pure JS in TypeScript" 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 var lifecycleCallbacks = new callbacks({ onActivityCreated: function (activity: any, bundle: any) { if (!androidApp.startActivity) { androidApp.startActivity = activity; + exports.notify({ eventName: androidActivityCreatedEvent, object: androidApp, activity: activity, bundle: bundle }); + if (androidApp.onActivityCreated) { androidApp.onActivityCreated(activity, bundle); } @@ -29,6 +41,7 @@ var initEvents = function () { androidApp.currentContext = activity; }, + onActivityDestroyed: function (activity: any) { // Clear the current activity reference to prevent leak if (activity === androidApp.foregroundActivity) { @@ -44,11 +57,13 @@ var initEvents = function () { exports.onExit(); } - exports.notify({ eventName: dts.exitEvent, object: androidApp, android: activity }); + exports.notify({ eventName: dts.exitEvent, object: androidApp, android: activity }); androidApp.startActivity = undefined; } + exports.notify({ eventName: androidActivityDestroyedEvent, object: androidApp, activity: activity }); + if (androidApp.onActivityDestroyed) { androidApp.onActivityDestroyed(activity); } @@ -56,47 +71,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. gc(); }, + onActivityPaused: function (activity: any) { if (activity === androidApp.foregroundActivity) { if (exports.onSuspend) { exports.onSuspend(); } - exports.notify({ eventName: dts.suspendEvent, object: androidApp, android: activity }); - + exports.notify({ eventName: dts.suspendEvent, object: androidApp, android: activity }); } + exports.notify({ eventName: androidActivityPausedEvent, object: androidApp, activity: activity }); + if (androidApp.onActivityPaused) { androidApp.onActivityPaused(activity); } }, + onActivityResumed: function (activity: any) { if (activity === androidApp.foregroundActivity) { if (exports.onResume) { exports.onResume(); } - exports.notify({ eventName: dts.resumeEvent, object: androidApp, android: activity }); - + exports.notify({ eventName: dts.resumeEvent, object: androidApp, android: activity }); } + exports.notify({ eventName: androidActivityResumedEvent, object: androidApp, activity: activity }); + if (androidApp.onActivityResumed) { androidApp.onActivityResumed(activity); } }, + onActivitySaveInstanceState: function (activity: any, bundle: any) { + exports.notify({ eventName: androidSaveActivityStateEvent, object: androidApp, activity: activity, bundle: bundle }); + if (androidApp.onSaveActivityState) { androidApp.onSaveActivityState(activity, bundle); } }, + onActivityStarted: function (activity: any) { androidApp.foregroundActivity = activity; + exports.notify({ eventName: androidActivityStartedEvent, object: androidApp, activity: activity }); + if (androidApp.onActivityStarted) { androidApp.onActivityStarted(activity); } }, + onActivityStopped: function (activity: any) { + exports.notify({ eventName: androidActivityStoppedEvent, object: androidApp, activity: activity }); + if (androidApp.onActivityStopped) { androidApp.onActivityStopped(activity); } diff --git a/application/application.d.ts b/application/application.d.ts index f650ac148..506e99981 100644 --- a/application/application.d.ts +++ b/application/application.d.ts @@ -48,7 +48,7 @@ declare module "application" { /** * 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. */ @@ -58,6 +58,15 @@ declare module "application" { * Gets the native Android event arguments. Valid only when running on Android. */ android?: any; + + /** + * The name of the event. + */ + eventName: string; + /** + * The instance that has raised the event. + */ + object: any; } /** @@ -140,7 +149,7 @@ declare module "application" { * Notifies all the registered listeners for the event provided in the data.eventName. * @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. @@ -151,32 +160,32 @@ declare module "application" { /** * 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. */ - 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. */ - 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. */ - 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. */ - 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. */ - 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. @@ -192,10 +201,140 @@ declare module "application" { */ 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. */ - 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. */ diff --git a/apps/tests/app/app.ts b/apps/tests/app/app.ts index e919261a9..ed33d6bf3 100644 --- a/apps/tests/app/app.ts +++ b/apps/tests/app/app.ts @@ -61,4 +61,38 @@ application.on(application.uncaughtErrorEvent, function (args: application.Appli } }); +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(); diff --git a/ui/frame/frame.android.ts b/ui/frame/frame.android.ts index fdf205011..441790041 100644 --- a/ui/frame/frame.android.ts +++ b/ui/frame/frame.android.ts @@ -426,6 +426,15 @@ var NativeActivity = { if (result) { result(requestCode, resultCode, data); } + + application.notify({ + eventName: application.androidActivityResultEvent, + object: application.android, + activity: this, + requestCode: requestCode, + resultCode: resultCode, + intent: data + }); }, onAttachFragment: function (fragment: android.app.Fragment) { @@ -670,7 +679,7 @@ function findPageForFragment(fragment: android.app.Fragment, frame: Frame) { } function startActivity(activity: android.app.Activity, entry: definition.NavigationEntry) { - var intent = new android.content.Intent(activity,(com).tns.NativeScriptActivity.class); + var intent = new android.content.Intent(activity, (com).tns.NativeScriptActivity.class); intent.setAction(android.content.Intent.ACTION_DEFAULT); // TODO: Put the navigation context (if any) in the intent activity.startActivity(intent);