skimemo


skimemo - 日記/2019-07-29/NativeScriptでServiceを実装する のバックアップの現在との差分(No.1)


  • 追加された行はこの色です。
  • 削除された行はこの色です。
#blog2navi()
*NativeScriptでServiceを実装する [#s51b7dce]

NativeScriptでAndroidのサービスを実装する方法は概ねマニュアル通りなのですが、若干はまったのでメモです。
~NativeScriptでAndroidのサービスを実装する方法は概ねマニュアル通りなのですが、若干はまったのでメモです。
~NativeScript+Serviceで検索すると[[このへん:https://www.nativescript.org/blog/using-android-background-services-in-nativescript]]とかが出てくるのですが、なんだか分かりづらいです。~
私が参考にしたのは[[こちら:https://github.com/NativeScript/nativescript-geolocation/blob/master/demo/app/background-service.ts]]でした。シンプルです。~
以下、手順です。
+ サービスの初期化~
app/app.jsに以下のように書きます。
#code(php){{{
const utils = require("tns-core-modules/utils/utils");
const application = require("tns-core-modules/application");
const Platform = require("tns-core-modules/platform");

const jobId = 1;

function stopBackgroundJob() {
    if (application.android) {
        let context = utils.ad.getApplicationContext();
        const jobScheduler = context.getSystemService(android.content.Context.JOB_SCHEDULER_SERVICE);
        if (jobScheduler.getPendingJob(jobId) !== null) {
            jobScheduler.cancel(jobId);
            console.log(`initservice: Job Canceled: ${jobId}`);
        }
    }
}
// アプリを閉じたらサービスも止める
// application.on(application.exitEvent, stopBackgroundJob);

function startBackground() {
	console.log('startBackground sdkver='+Platform.device.sdkVersion);
    if (application.android) {
        let context = utils.ad.getApplicationContext();
        if (Platform.device.sdkVersion < "26") {
            let intent = new android.content.Intent(context, jp.inxray.scop.BackgroundService.class);
            context.startService(intent);
        } else {
            const jobScheduler = context.getSystemService(android.content.Context.JOB_SCHEDULER_SERVICE);
            const component = new android.content.ComponentName(context, jp.inxray.scop.BackgroundService26.class);
            const builder = new (android.app).job.JobInfo.Builder(jobId, component);
            builder.setOverrideDeadline(0);
            return jobScheduler.schedule(builder.build());
        }
    }
}

function stopBackgroundTap() {
    if (application.android) {
        if (Platform.device.sdkVersion < "26") {
            let context = utils.ad.getApplicationContext();
            let intent = new android.content.Intent(context, jp.inxray.scop.BackgroundService.class);
            context.stopService(intent);
        } else {
            stopBackgroundJob();
        }
    }
}

// 開始
startBackground();
}}}
~
+ サービス本体です~
app/service/background.js
#code(php){{{
const application = require("tns-core-modules/application");
const Timer = require("tns-core-modules/timer");
const Platform = require("tns-core-modules/platform");

let timerid = null;

if (application.android) {
	if (Platform.device.sdkVersion < "26") {
		(android.app.Service).extend("jp.inxray.scop.BackgroundService", {
			onStartCommand: function (intent, flags, startId) {
				this.super.onStartCommand(intent, flags, startId);
				return android.app.Service.START_STICKY;
			},
			onCreate: function () {
				startTimer(30);
				console.log("background: start Service");
			},
			onBind: function (intent) {
				console.log("background: on Bind Services");
			},
			onUnbind: function (intent) {
				console.log('background: UnBind Service');
			},
			onDestroy: function () {
				console.log('background: service onDestroy');
				stopTimer();
			}
		});
	} else {
		(android.app).job.JobService.extend("jp.inxray.scop.BackgroundService26", {
			onStartJob() {
				startTimer(30);
				console.log('background: service onStartJob');
				return true;
			},
			onStopJob(jobParameters) {
				console.log('background: service onStopJob');
				this.jobFinished(jobParameters, false);
				stopTimer();
				return false;
			},
		});
	}
}

/**
 * 定期実行設定
 * @param {number} interval 時間間隔(sec)
 */
function startTimer(interval) {
	if(interval>0 && timerid==null){
		timerid = Timer.setInterval(() => {
			const randNumber = Math.random();
			console.log(randNumber);
		}, interval*1000);
		console.log('worker: set timer to interval '+ interval*1000 + 'ms.');
	}
}

/**
 * 定期実行停止
 */
function stopTimer() {
	if(timerid!=null){
		Timer.clearInterval(timerid);
		timerid = null;
		console.log('background: stop timer.');
	}
}

}}}
~
+ manifestにサービスを記述します~
app/App_Resources/Android/src/main/AndroidManifest.xml
#code(xml){{{
	<application
            :
		<service android:name="jp.inxray.scop.BackgroundService" android:exported="false"></service>
		<service android:name="jp.inxray.scop.BackgroundService26" android:permission="android.permission.BIND_JOB_SERVICE" android:enabled="true" android:exported="false"></service>
	</application>
}}}
~
+ webpack.configの設定~
webpack(--bundle)を使わない場合はここまでで動くのですが、NativeScript6からwebpack必須になりました。~
webpackに対応するには以下の設定が必要です。~
~webpack.config.js
#code(php){{{
    const appComponents = [
        "tns-core-modules/ui/frame",
        "tns-core-modules/ui/frame/activity",
        resolve(__dirname, "app/service/background.js"),
    ];
}}}
4行目にサービスの実行ファイルを追記しています。

~以上で、&inlinecode{tns run android --bundle};すると、アプリを閉じてもタスクリストから終了しても、30秒ごとにランダムな数字がコンソールにログ出力されます。
~以上です。
#htmlinsert(twitterbutton.html)
RIGHT:Category: &#x5b;[[NativeScript>日記/Category/NativeScript]]&#x5d; - 14:15:52
----
#htmlinsert(20191130_service.html)
----
RIGHT:&blog2trackback();
#comment(above)
#blog2navi()