应用程序从后台删除后,服务内的广播接收器未收听

Posted

技术标签:

【中文标题】应用程序从后台删除后,服务内的广播接收器未收听【英文标题】:Broadcast receiver inside service did not listen after app removed from background 【发布时间】:2019-08-04 04:42:13 【问题描述】:

我注册了一个广播接收器以在服务内接收 SMS。该应用程序的目的是接收短信并将来自预期发件人的短信内容保存在 Sqlite 存储中。即使应用不在后台运行,应用也需要捕获收到的短信。

public class SMSService extends Service 

    private final BroadcastReceiver receiver = new BroadcastReceiver() 
        public static final String SMS_BUNDLE = "pdus";
        ContentValues userValues;
        Object[] sms;

        @Override
        public void onReceive(Context context, Intent intent) 
            String action = intent.getAction();
            if (action.equals("android.provider.Telephony.SMS_RECEIVED")) 
                Log.d("~~~ SMS !!!", "~~~ SMS ~~~ SMS ~~~ SMS~~~ SMS ~~~");
                AsyncSmsHandler asyncSmsHandler = new AsyncSmsHandler(context, intent);
                asyncSmsHandler.execute("");
            
        


        class AsyncSmsHandler extends AsyncTask<String, Void, String> 

            Context context;
            Intent intent;

            public AsyncSmsHandler(Context context, Intent intent) 
                this.context = context;
                this.intent = intent;
            

            @Override
            protected String doInBackground(String... params) 

                String smsBody = "", address = "";
                Bundle intentExtras = intent.getExtras();
                SmsMessage smsMessage = null;
                if (intentExtras != null) 
                    sms = (Object[]) intentExtras.get(SMS_BUNDLE);

                    String smsMessageStr = "";
                    for (int i = 0; i < sms.length; ++i) 
                        smsMessage = SmsMessage.createFromPdu((byte[]) sms[i]);
                        smsBody = smsBody + smsMessage.getMessageBody();

                   smsMessageStr += smsBody + "\n";
                    


                    address = smsMessage.getOriginatingAddress();

                    Log.d("SMS RECEIVER NUMBER", " " + smsBody + " -- " + sms.length);

                    //SAVE THE MESSAGE AND NUMBER

                
                return "";
            

            @Override
            protected void onPostExecute(String result) 


                // Create an explicit intent for an Activity in your app
                Intent intent = new Intent(context, AquaOrderList.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

                NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "CHANNEL_ID")
                        .setSmallIcon(R.drawable.logo)
                        .setContentTitle(“TITLE”)
                        .setContentText(“Message”)
                        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                        .setContentIntent(pendingIntent)
                        .setAutoCancel(true);

                NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);

                // notificationId is a unique int for each notification that you must define
                notificationManager.notify(1, builder.build());
            

        
    ;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) 
        return START_STICKY;
    


    @Override
    public IBinder onBind(Intent arg0) 
        return null;
    

    @Override
    public void onCreate() 
        IntentFilter filter = new IntentFilter();
        filter.addAction("android.provider.Telephony.SMS_RECEIVED");

        registerReceiver(receiver, filter);
    

    @Override
    public void onDestroy() 
        unregisterReceiver(receiver);
    

以这种方式在 onCreate 和 unregisterReceiver 中注册接收器 onDestroy 方法。

这按预期工作,但是当我杀死应用程序并在一段时间后,如果我收到短信,它不会被触发。如果我再次打开该应用程序,则该短信开始保存在存储中。

服务被破坏了吗?我在移动设备中检查了“正在运行的服务”,我可以看到该服务正在运行。

我还在清单文件中添加了权限。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xyz.app”>

    <uses-permission android:name="android.permission.READ_SMS" />
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <uses-permission android:name="android.permission.WRITE_SMS" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <service
            android:name=".SMSService"
            android:enabled="true"
            android:exported="true"></service>

        <activity
            android:name=".OrderList"
            android:configChanges="orientation|keyboardHidden|screenSize"
            android:label="@string/title_activity_order_list"
            android:theme="@style/FullscreenTheme"></activity>
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

我想让应用程序监听传入的短信,即使应用程序不在堆栈中。我可以采用什么方法来完成这项工作。

【问题讨论】:

你必须使用清单声明的接收者developer.android.com/guide/components/… 但我没有使用独立的接收器。我正在添加 IntentFilter,它以编程方式在服务内部执行。它在应用程序处于前台时工作。如果应用程序有一段时间没有运行,也可以工作。过了一段时间,就会出现收不到短信的情况。 那是因为你的服务被破坏了。您不能在后台永久运行您的服务。所以对于这些情况,当我们想要在应用程序没有运行的情况下监听一些事件时,我们需要向系统注册一个广播接收器。从那里你开始你的服务来执行一些工作。 你能给我一个例子来实现这个吗?永久运行服务。 这是不可能的。您必须使用清单声明的接收器,没有其他方法。 【参考方案1】:

我不完全同意@Ranjan 的 cmets。是的,服务是 被android破坏并继续运行,是的,很难运行 永久服务。但是,如果您已正确完成所有操作, 您的服务被销毁多少次,它将被启动 再次(自动),在发射时,你的接收器应该是 已注册。


我的建议是:

首先,确保您的目标不是最新的 SDK。我正在使用 targetSDK 10、minSDK 17 和 compileSDK 26。这可能会对您的服务的处理方式产生影响。使用这些值来检查是否仅此一项就可以工作。

接下来,请关注这个帖子HERE 并尝试正确创建您的接收器。

我不确定您的问题究竟是什么,但我可以告诉您,我们有一个视频会议应用程序,可以监听来电和消息。所以当然需要注册 BroadcastReceiver 并且 Service 应该在后台运行。这个应用程序有点旧,并且是使用 targetSDK 10 等开发的。所以他们以当时常见的方式进行操作。我们还没有移植我们的应用程序,所以我们不知道较新的 Android 存在什么问题。正如我所提到的,我们的应用使用 SDK26 编译。


代码示例:

public SampleService() 
    super();
    Log.d(TAG, "SampleService: Constructor");
    final HandlerThread mHandlerThread = new HandlerThread(BR_THREAD_NAME, Process.THREAD_PRIORITY_BACKGROUND);
    mHandlerThread.start();
    bgLooper = mHandlerThread.getLooper();
    mBRHandler = new Handler(bgLooper);


@Override
public void onCreate() 
    super.onCreate();
    Log.d(TAG, "onCreate: ");
    registerReceiver();


private void registerReceiver() 
    final IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(SOME_ACTION);
    myReceiver = new MyReceiver();
    registerReceiver(myReceiver, intentFilter, null, mBRHandler);

这应该够好了

【讨论】:

以上是关于应用程序从后台删除后,服务内的广播接收器未收听的主要内容,如果未能解决你的问题,请参考以下文章

使用 Android 收听广播

从最近删除应用程序时后台服务停止

BroadcastReceiver广播接收者

广播接收器未被呼叫

当应用程序关闭时,GCM 广播接收器未检测到 gcm 通知

android 如何实现后台时用通知栏显示有新的消息,当在前台时不显示通知