设备重启后启动 Phonegap 插件

Posted

技术标签:

【中文标题】设备重启后启动 Phonegap 插件【英文标题】:Initiating a Phonegap plugin after device restart 【发布时间】:2017-06-01 01:18:39 【问题描述】:

我正在开发适用于 android 的混合 Phonegap 应用程序。该应用程序仅使用我正在开发的一个插件。该插件做了三件事

监视地理位置变化(前景和背景) 设置半小时警报以执行某些周期性任务 监听推送消息。我使用pushy.me 服务,我使用的代码遵循their documentation。

我已经实现了让应用程序调整到设备重启的代码,但结果很容易(感谢我在 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);  
 

我因此注册了重启接收器

<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 是我的应用程序/插件的入口点 - 扩展了 CordovaPlugin 类的入口点。这就是我在那里做的事情

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
  

当我在我的 Android 4.4.2 测试设备上手动启动应用程序时,一切正常。即

在前台和后台都检测到地理位置变化 收到推送消息。再次在 f/g 和 b/g 中进行 半小时闹铃有效

当我检查正在运行的应用程序时,我发现它包含一个服务PushySocketService 和主进程com.example.app,它被标记为正在使用。内存使用量很大。

当我重新启动手机时,我仍然发现相同的服务和“主进程”正在运行。但是,报告的主进程的内存使用情况要低得多。

最重要的是 - 应用程序不会收到推送消息,也不会响应地理位置更改。这只有在我通过main activity 启动应用程序后才开始发生。

我必须在这里遗漏一些东西 - 所以重新启动的应用程序不会自动启动它的main activity?如果是这样,我的Rebooter.onReceive 代码一定有问题?

为了完整性,我应该提一下

只有 Pushy.me 和 Rebooter 广播接收器在 plugin.xml 文件中静态声明。地理位置和警报广播接收器是在我的插件代码中动态注册的。 我正在使用 Phonegap CLI v 6.4.2 和 JDK 7 构建应用程序

我显然在这里做错了什么。我将非常感谢任何能够让我走上正轨的人。

【问题讨论】:

你试过使用github.com/ToniKorin/cordova-plugin-autostart吗?它还指出“安装到 SD 卡将阻止您的应用在启动后自动启动。” @DroidOS 尝试使用 getInstance(实现单例模式)并调用 mainactivity 的相应方法,而不是在 OnReceive 中启动主要活动。 @AkshayTilekar,你能详细说明一下吗?我认为BroadcastReceiver.OnReceive 事件是重新启动活动的合乎逻辑的地方。你似乎在暗示别的东西。 你到底想要什么? 我只是想让你澄清你的评论,因为很难理解你的建议 【参考方案1】:

如果你不想为此功能使用任何第三方插件,那么你可以借用cordova auto start plugin的逻辑。

您可以查看插件中的BootCompletedReceiver 类。每次设备成功重新启动时都会调用它,这反过来又会调用AppStarter helper 类来启动相应的应用程序。您也可以在插件中实现相同的逻辑。

希望对您有所帮助。干杯。

【讨论】:

试过这个 - 甚至尝试使用插件。它什么都不做,并且有一个不幸的副作用,就是在重启后阻止我的应用程序调入推送消息。去掉所有插件代码,它所做的只是用`packageName.mainActivity.class 创建一个意图。这有效,但在我将应用程序带到前台之前似乎不会初始化应用程序使用的插件 DroidOS 将检查并返回 据我了解,问题是 Cordova 插件在创建 CordovaWebView 之前不会初始化,并且当应用程序通过引导接收器从 packageName.mainActivity.class 意图重新启动时似乎不会发生这种情况。鉴于我在自己的插件初始化代码中调入推送、启动警报、观看地理位置等,启动的应用程序在我手动将其带到前台之前什么都不做 @DroidOS 嗨,看起来您的问题的解决方案可在以下链接中找到 - github.com/ToniKorin/cordova-plugin-autostart/issues/15 查看链接中 jorantos 的评论......它应该会给您一些线索。希望对您有所帮助。 谢谢。几天后,我将在此处发布所有这些问题的完整解决方案,以使遇到此线程的其他人受益。【参考方案2】:

科尔多瓦插件

我们来看这段代码:

Intent i = new Intent(context, MyAppCordovaPlugin.class); 
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
CordovaPlugin 不是一个活动,所以你不能像它一样启动它。 Cordova Android 应用程序是一个带有 WebView 的单个 Activity 应用程序,它仅在创建 WebView 后加载插件。您并不想为了收听 GCM 消息或地理围栏事件而启动应用程序/启动应用程序 UI。

Pushy.me

Pushy.me documentation 建议在应用的清单中声明 BroadcastReceiver。似乎 Pushy 也为您处理启动事件。为什么不使用他们推荐的方法?

开机后在后台运行东西

如上所述,initialize() 回调中的代码只有在应用程序的活动启动时才会运行。但是您想在启动完成事件后在后台调用其中的一些代码。

我建议将“开始监听后台事件”逻辑移动到IntentService,您可以从插件的initialize() 和启动完成接收器开始。

【讨论】:

我赞成您的回答,因为您强调了几个重要问题。显然,传递MyAppCordovaPlugin 类是错误的。其次,考虑到我不仅想重新启动推送消息监听,还想重新启动其他一些事情——警报、地理位置等——我根本不应该使用 PushyMe 启动接收器。 我不认为一个应用程序中有两个BroadcastReceiver用于同一个事件有问题,所以如何集成pushy.me是你考虑的。我更喜欢尽可能少写代码。无论如何,将警报、地理位置等的初始化移至 IntentService 应该可以解决您的问题。

以上是关于设备重启后启动 Phonegap 插件的主要内容,如果未能解决你的问题,请参考以下文章

iOS 上 PhoneGap 2.0 的应用内购买 (IAP) 插件?

Phonegap Facebook 插件 - 从 Android 设备中删除应用程序后密钥哈希无效

我只想使用 Phonegap 定位 iPhone(不是 iPad)

PhoneGap Build 和 CLI 的相对图标路径

构建后phonegap推送插件不起作用

WebView 应用程序(PhoneGap Build),重启后不保存 localStorage