Android 如何确保广播接收器保持运行并侦听传入的文本消息,而不会被操作系统杀死

Android 如何确保广播接收器保持运行并侦听传入的文本消息,而不会被操作系统杀死,android,broadcastreceiver,Android,Broadcastreceiver,我正在编写一个android应用程序,它可以监听传入的文本消息,然后与后端同步。到目前为止,应用程序运行正常,但一段时间后,除非我再次打开应用程序,否则应用程序不会收到任何传入消息。已经探索了各种建议实施JobService或just service的选项,但我做的研究越多,我就越感到困惑。对于JobService,我可以看到它只意味着在一段时间后安排作业,并且一旦作业完成,服务可能会被终止。我需要帮助找到解决问题的最佳方法。下面是我的广播接收器类代码 公共类MessageReceiver扩展了

我正在编写一个android应用程序,它可以监听传入的文本消息,然后与后端同步。到目前为止,应用程序运行正常,但一段时间后,除非我再次打开应用程序,否则应用程序不会收到任何传入消息。已经探索了各种建议实施JobService或just service的选项,但我做的研究越多,我就越感到困惑。对于JobService,我可以看到它只意味着在一段时间后安排作业,并且一旦作业完成,服务可能会被终止。我需要帮助找到解决问题的最佳方法。下面是我的广播接收器类代码

公共类MessageReceiver扩展了BroadcastReceiver{

private static MessageListener messageListener;
Handler mHandler;

private static final String TAG = "MessageReceiver";

public MessageReceiver() {

}

@TargetApi(Build.VERSION_CODES.M)
@Override
public void onReceive(final Context context, Intent intent) {

   if (Telephony.Sms.Intents.SMS_RECEIVED_ACTION.equals(intent.getAction())) {
       final Bundle data = intent.getExtras();
       HandlerThread bgHandlerThread=new HandlerThread("MyCoolBackgroundThread");
       bgHandlerThread.start();
       mHandler=new Handler(bgHandlerThread.getLooper());

       Runnable backgroundRunnable = new Runnable() {
           @Override
           public void run() {
               passReceivedMsg(data);
           }
       };
       mHandler.post(backgroundRunnable);

   }

}
我已经实现了一个接口,在该接口中我传递接收到的TextMessage对象

    private void passReceivedMsg(final Bundle bundleData) {
    if (bundleData !=null ){
        try {
            final Object[] pdusObj = (Object[]) bundleData.get("pdus");
            if (pdusObj != null) {
                for (int i = 0; i < pdusObj.length; i++) {
                    SmsMessage currentMessage =
                            SmsMessage.createFromPdu((byte[]) pdusObj[i]);
                    Log.d(TAG, "run: currentMessage: "+currentMessage);

                    messageListener.getReceivedMessage(currentMessage);
                    Log.d(TAG, "handleMessage: message "+currentMessage);

                }
            }
        }
        catch (Exception e){
            Log.d(TAG, "onReceive: Error occurred "+e);

        }

    }

}

public static void bindListener (MessageListener listener){
        messageListener = listener;
}
下面是我的舱单

       <receiver
            android:name=".utils.MessageReceiver"
            android:enabled="true"
            android:exported="true"
            android:permission="android.permission.BROADCAST_SMS">

            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
        </receiver>

我不知道您认为您的
MessageListener
对象来自哪里

请理解,您的应用程序进程不会永远运行。一旦您的应用程序的UI移动到后台,。这将清除任何可能存在的
MessageListener
对象

因此,最有可能发生的情况是,您设置了此
MessageListener
,它会工作一段时间,直到原始进程终止。未来的SMS消息将为您的应用程序启动一个新进程,但您不再拥有
MessageListener
,因此您的工作无法完成


取而代之的是,去掉
MessageListener
和任何你用来保存引用的
static
字段。让你的
BroadcastReceiver
使用
WorkManager
做后台工作,你的
Worker
可以自己处理所有事情,而不依赖应用程序nec的任何活动等已在当前进程中运行。

您在何处以及如何注册
MessageReceiver
?我已创建了一个类(MessageReceiver)实现广播接收器的。我有一个侦听器接口,在其中传递接收到的TextMessage对象。抱歉,这不是我要问的。清单中是否有指向
MessageReceiver
元素?或者您正在调用
registerReceiver()
在哪里注册
MessageReceiver
?我在清单上有它。注意到。但我仍然对广播接收器有一些担心,因为在某个时候,如果广播接收器的onReceive方法在一段时间后没有被调用,应用程序可能会被杀死,有没有办法克服这个问题。我问这个问题是因为我想知道什么时候用户安装此应用程序时,它应该开始拦截所有传入的消息,而不需要用户继续重新启动应用程序。@杰克:您的接收者已在清单中注册。即使您没有运行进程(“应用程序可能会被终止”),您仍将接收广播。Android将为您提供一个新的进程,然后调用
onReceive()在这个过程中,你的
MessageReceiver
。但是,在这一点上,你没有
MessageListener
。这就是为什么你需要摆脱
MessageListener
,让
MessageReceiver
不要假设你的应用程序的某个前一个过程中有任何东西在内存中。现在,这对我来说很有意义。非常重要谢谢。这就是我出错的地方。很快,我删除了侦听器,一切正常,但当我关闭android系统时,广播接收器不活动,在我启动应用程序之前无法接收任何文本。@Jack:你可能无法从
广播接收器
可靠地显示
土司
。And网络I/O需要卸载到
WorkManager
JobIntentService
、或前台
服务
。不仅在接收广播之前,您的应用程序进程可能不存在,而且在
onReceive()之后,您的应用程序进程可能会在几毫秒后关闭
返回。
WorkManager
和其他列出的选项将有助于解决此问题。如果仍然存在问题,请提出一个新的堆栈溢出问题,显示当前代码,并提供您看到(和未看到)的详细信息。
       <receiver
            android:name=".utils.MessageReceiver"
            android:enabled="true"
            android:exported="true"
            android:permission="android.permission.BROADCAST_SMS">

            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
        </receiver>