Initiating a Phonegap plugin after device restart

2019-04-05 11:28发布

问题:

I am in the process of developing a hybrid Phonegap app for Android. The app uses just the one plugin which I am developing as well. The plugin does three things

  • Watches for geo-location changes (both foreground and background)
  • Sets up a half-hourly alarm to perform certain periodic tasks
  • Listens for push messages. I use the pushy.me service and the code I use follows their documentation.

I had implemented the code to get the application to tune in to device reboots with some trepidation but it turned out to be easy (thanks to information I found in other threads on SO)

package com.example.plugin;

import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaWebView;
import android.content.Context;
import android.content.BroadcastReceiver;
import android.content.pm.PackageManager;
import android.app.Activity;

import android.content.Intent;

public class Rebooter extends BroadcastReceiver
{
 @Override
 public void onReceive(Context context, Intent intent) 
 {
  Intent i = new Intent(context, MyAppCordovaPlugin.class); 
  i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  context.startActivity(i);  
 }
}

I register the reboot receiver thus

<receiver android:enabled="true" android:name=".Rebooter" 
 android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
 <intent-filter>
  <action android:name="android.intent.action.BOOT_COMPLETED" />
  <category android:name="android.intent.category.DEFAULT" />
 </intent-filter>
</receiver>

MyAppCordovaPlugin is the entry point to my app/plugin - the one that extends the CordovaPlugin class. Here is what I do there

public class MyAppCordovaPlugin extends CordovaPlugin
{
 private Context context;

 public void initialize(CordovaInterface cordova, CordovaWebView webView) 
 {
  super.initialize(cordova, webView);
  this.context = cordova.getActivity().getApplicationContext();
  //setup pushy.me broadcast receiver
  //setup geolocation changes receiver
  //setup broadcast receiver for a half-hourly alarm
 } 

 @Override
 public void onResume(boolean multitasking) 
 {
  super.onResume(multitasking);
  //unregister background location change receiver, if present
  //switch geolocation to foreground mode. i.e. using
  //FusedLocationApi.requestLocationUpdates
 }

 @Override
 public void onPause(boolean multitasking) 
 {
  super.onPause(multitasking);
  //stop request for foreground location updates, if present
  //switch geolocation to background mode, i.e by
  //registering a broadcast receiver that listens for location change 
  //broadcasts
 } 

When I start up the app manually on my Android 4.4.2 test device everything works perfectly. i.e.

  • Geo location changes are detected:both in the foreground and in the background
  • push messages are received. Once again both in f/g and in b/g
  • The half hourly alarm works

When I examine the running app I find that it consists of one service PushySocketService and the main process, com.example.app which is marked as being in use. Memory usage is considerable.

When I restart the phone I still find the same service and "main process" running. However, the memory usage reported for the main process is significantly lower.

Most importantly - the app does not recieve push messages and does not respond to geo location changes. This only starts happening after I have launched the app by main activity.

I must be missing something here - so the rebooted app does not automatically start its main activity? If so there must be something wrong with my Rebooter.onReceive code?

For completeness I should mention

  • Only the Pushy.me and Rebooter broadcast receivers are declared statically in the plugin.xml file. The Geo location and alarm broadcast receivers are registered dynamically from within my plugin code.
  • I am building the app using Phonegap CLI v 6.4.2 and JDK 7

I am clearly doing something wrong here. I'd be most grateful to anyone who might be able to put me on the right track.

回答1:

If you dont want to use any third party plugin for this functionality, then you can borrow the logic from cordova auto start plugin.

You can have a look at BootCompletedReceiver class in the plugin. It invokes everytime when the device reboots successfully which in turn invokes AppStarter helper class to start the respective app. You can implement the same logic in your plugin too.

Hope it helps. Cheers.



回答2:

Cordova Plugin

Let's look at this piece of code:

Intent i = new Intent(context, MyAppCordovaPlugin.class); 
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
  • CordovaPlugin is not an activity, so you cannot start it as if it were.
  • Cordova Android application are is a single Activity application with a WebView, which loads the plugins only after the WebView is created. You don't really want to launch the application / start app UI in order to listen to GCM messages or geofencing events.

Pushy.me

Pushy.me documentation recommend to declare the BroadcastReceiver in the app's manifest. Seems also that Pushy also take care of boot event for you. Why not use their recommended approach?

Running stuff in the background after boot

As mentioned above, the code in initialize() callback will run only when the application's activity has been started. But you want to invoke some of the code there in the background after boot-complete event.

What I recommend is moving the 'start listening to background events' logic to an IntentService, which you can start both from your plugin's initialize(), and your boot complete receiver.