Files
NativeScript/application/application.android.ts

261 lines
9.3 KiB
TypeScript

import appModule = require("application/application-common");
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;
require("utils/module-merge").merge(appModule, exports);
export var mainModule: string;
// 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: dts.AndroidApplication = exports.android;
// TODO: Verify whether the logic for triggerring application-wide events based on Activity callbacks is working properly
var lifecycleCallbacks = new android.app.Application.ActivityLifecycleCallbacks({
onActivityCreated: function (activity: any, bundle: any) {
if (!androidApp.startActivity) {
androidApp.startActivity = activity;
androidApp.notify(<dts.AndroidActivityBundleEventData>{ eventName: "activityCreated", object: androidApp, activity: activity, bundle: bundle });
if (androidApp.onActivityCreated) {
androidApp.onActivityCreated(activity, bundle);
}
}
androidApp.currentContext = activity;
},
onActivityDestroyed: function (activity: any) {
// Clear the current activity reference to prevent leak
if (activity === androidApp.foregroundActivity) {
androidApp.foregroundActivity = undefined;
}
if (activity === androidApp.currentContext) {
androidApp.currentContext = undefined;
}
if (activity === androidApp.startActivity) {
if (exports.onExit) {
exports.onExit();
}
exports.notify(<dts.ApplicationEventData>{ eventName: dts.exitEvent, object: androidApp, android: activity });
androidApp.startActivity = undefined;
}
androidApp.notify(<dts.AndroidActivityEventData>{ eventName: "activityDestroyed", object: androidApp, activity: activity });
if (androidApp.onActivityDestroyed) {
androidApp.onActivityDestroyed(activity);
}
// 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(<dts.ApplicationEventData>{ eventName: dts.suspendEvent, object: androidApp, android: activity });
}
androidApp.notify(<dts.AndroidActivityEventData>{ eventName: "activityPaused", 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(<dts.ApplicationEventData>{ eventName: dts.resumeEvent, object: androidApp, android: activity });
}
androidApp.notify(<dts.AndroidActivityEventData>{ eventName: "activityResumed", object: androidApp, activity: activity });
if (androidApp.onActivityResumed) {
androidApp.onActivityResumed(activity);
}
},
onActivitySaveInstanceState: function (activity: any, bundle: any) {
androidApp.notify(<dts.AndroidActivityBundleEventData>{ eventName: "saveActivityState", object: androidApp, activity: activity, bundle: bundle });
if (androidApp.onSaveActivityState) {
androidApp.onSaveActivityState(activity, bundle);
}
},
onActivityStarted: function (activity: any) {
androidApp.foregroundActivity = activity;
androidApp.notify(<dts.AndroidActivityEventData>{ eventName: "activityStarted", object: androidApp, activity: activity });
if (androidApp.onActivityStarted) {
androidApp.onActivityStarted(activity);
}
},
onActivityStopped: function (activity: any) {
androidApp.notify(<dts.AndroidActivityEventData>{ eventName: "activityStopped", object: androidApp, activity: activity });
if (androidApp.onActivityStopped) {
androidApp.onActivityStopped(activity);
}
}
});
return lifecycleCallbacks;
}
app.init({
getActivity: function (activity: android.app.Activity) {
var intent = activity.getIntent()
return exports.android.getActivity(intent);
},
onCreate: function () {
exports.android.init(this);
}
});
export class AndroidApplication extends observable.Observable implements dts.AndroidApplication {
public static activityCreatedEvent = "activityCreated";
public static activityDestroyedEvent = "activityDestroyed";
public static activityStartedEvent = "activityStarted";
public static activityPausedEvent = "activityPaused";
public static activityResumedEvent = "activityResumed";
public static activityStoppedEvent = "activityStopped";
public static saveActivityStateEvent = "saveActivityState";
public static activityResultEvent = "activityResult";
public static activityBackPressedEvent = "activityBackPressed";
public nativeApp: android.app.Application;
public context: android.content.Context;
public currentContext: android.content.Context;
public foregroundActivity: android.app.Activity;
public startActivity: android.app.Activity;
public packageName: string;
public hasActionBar: boolean;
/* tslint:disable */
@Deprecated
/* tslint:enable */
public onActivityCreated: (activity: android.app.Activity, bundle: android.os.Bundle) => void;
/* tslint:disable */
@Deprecated
/* tslint:enable */
public onActivityDestroyed: (activity: android.app.Activity) => void;
/* tslint:disable */
@Deprecated
/* tslint:enable */
public onActivityStarted: (activity: android.app.Activity) => void;
/* tslint:disable */
@Deprecated
/* tslint:enable */
public onActivityPaused: (activity: android.app.Activity) => void;
/* tslint:disable */
@Deprecated
/* tslint:enable */
public onActivityResumed: (activity: android.app.Activity) => void;
/* tslint:disable */
@Deprecated
/* tslint:enable */
public onActivityStopped: (activity: android.app.Activity) => void;
/* tslint:disable */
@Deprecated
/* tslint:enable */
public onSaveActivityState: (activity: android.app.Activity, bundle: android.os.Bundle) => void;
/* tslint:disable */
@Deprecated
/* tslint:enable */
public onActivityResult: (requestCode: number, resultCode: number, data: android.content.Intent) => void;
private _eventsToken: any;
public getActivity(intent: android.content.Intent): Object {
if (intent && intent.getAction() === android.content.Intent.ACTION_MAIN) {
// application's main activity
if (exports.onLaunch) {
exports.onLaunch(intent);
}
exports.notify({ eventName: dts.launchEvent, object: this, android: intent });
/* In the onLaunch event we expect the following setup, which ensures a root frame:
* var frame = require("ui/frame");
* var rootFrame = new frame.Frame();
* rootFrame.navigate({ pageModuleName: "mainPage" });
*/
}
var topFrame = frame.topmost();
if (!topFrame) {
// try to navigate to the mainModule (if specified)
if (mainModule) {
topFrame = new frame.Frame();
topFrame.navigate(mainModule);
} else {
// TODO: Throw an exception?
throw new Error("A Frame must be used to navigate to a Page.");
}
}
return topFrame.android.onActivityRequested(intent);
}
public init(nativeApp: any) {
this.nativeApp = nativeApp;
this.packageName = nativeApp.getPackageName();
this.context = nativeApp.getApplicationContext();
this._eventsToken = initEvents();
this.nativeApp.registerActivityLifecycleCallbacks(this._eventsToken);
this.context = this.nativeApp.getApplicationContext();
}
}
global.__onUncaughtError = function (error: Error) {
if (!types.isFunction(exports.onUncaughtError)) {
return;
}
var nsError = {
message: error.message,
name: error.name,
nativeError: (<any>error).nativeException
}
exports.onUncaughtError(nsError);
exports.notify({ eventName: dts.uncaughtErrorEvent, object: appModule.android, android: nsError });
}
exports.start = function () {
dts.loadCss();
}
exports.android = new AndroidApplication();