我正在监视传入的SMS。

我的应用与BroadcastReceiver完美兼容。但是,它是通过Activity运行的,并且希望使BroadcastReceiver始终保持运行(而不仅是我的Activity运行时)。

我该如何实现?我已经看过BroadcastReceiver的生命周期,但是文档中提到的全部是生命周期仅限于onReceive方法,而不是保持BroadcastReceiver检查传入SMS的生命周期。

如何使它持久化?

感谢

#1 楼

您需要在清单中定义一个动作名称为android.intent.action.BOOT_COMPLETED的接收方。

<!-- Start the Service if applicable on boot -->
<receiver android:name="com.prac.test.ServiceStarter">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>


请确保还包括完整的启动权限。

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>


使用Service可以使任何内容持久化。如果系统启动,请使用接收方接收启动事件以重新启动服务。.

启动时启动服务的代码。让服务做您检查短信或任何您想要的工作。您需要在MyPersistingService中做您自己的工作。

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class ServiceStarter extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Intent i = new Intent("com.prac.test.MyPersistingService");
        i.setClass(context, MyPersistingService.class);
        context.startService(i);
    }
}


评论


您可能还需要确保在应用清单文件中定义了RECEIVE_BOOT_COMPLETED权限,此功能才能起作用。

–杰伊·西德里(Jay Sidri)
2012年5月27日在18:01

如果应用程序上下文正在从项目库扩展另一个上下文,这是否可行?

– Maxrunner
2012年8月23日18:00

这项服务如何?

– Slayton
2013年9月25日14:03在

它是一种广播,可让您的服务在设备启动后继续运行。

–罗希特·夏尔马(Rohit Sharma)
2013年9月26日上午8:24

同样重要的是要注意,如果您的应用程序安装到内部存储中,则仅会接收启动完成广播,如果在外部存储中允许,则不会获得广播。如果使您的应用获得广播的启动至关重要,则您可能需要考虑仅允许内部安装。 developer.android.com/guide/topics/data/install-location.html

– Jawnnypoo
2015年3月10日在18:18

#2 楼

服务或引导完成不是强制性的

实际上,您不需要实现Service或注册到android.intent.action.BOOT_COMPLETED

一些示例显示了如何在以下情况下注册/注销BroadcastReceiver活动已创建并销毁。但是,这对于仅在打开应用程序时才有的意图很有用(例如,用于服务/活动之间的内部通信)。

但是,如果是SMS,则要收听意图一直(不仅在打开应用程序时)。

还有另一种方法

您可以创建一个class,它扩展了BroadcastReceiver并通过AndroidManifest.xml注册到所需的意图。这样,BroadcastReceiver就不会影响您的活动了(并且与活动的生命周期无关)

这样,即使您的应用收到短信,Android也会在收到短信后立即自动通知您BroadcastReceiver已关闭。

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest>
    ...
    <uses-permission android:name="android.permission.READ_SMS"/>
    <uses-permission android:name="android.permission.RECEIVE_SMS"/>

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


MyCustomBroadcastReceiver.java

public class MyCustomBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        if(intent != null) {
            String action = intent.getAction();
            if(action != null) {
                if(action.equals("android.provider.Telephony.SMS_RECEIVED")) {
                    // DO YOUR STUFF
                } else if (action.equals("ANOTHER ACTION")) {
                    // DO ANOTHER STUFF
                }
            }
        }
    }
}


注意事项

您可以将其他Intent过滤器添加到AndroidManifest,并在同一BroadcastReceiver中处理所有这些过滤器。

仅当您执行长任务时才启动服务。您只需要显示一个通知或更新一些数据库,只需使用上面的代码即可。

评论


如果应用崩溃次数过多或用户强行停止应用,则不会在广播事件中重新启动该应用

–盆地
17年11月22日在14:43

@ W0rmH0le当他不启动活动或应用程序而重新启动手机时会发生什么?他不需要引导完成的接收器吗?

– eawedat
18年7月13日在8:53

@eawedat由于所需的意图已在AndroidManifest中注册,因此即使您尚未打开应用,Android也会调用您的广播接收器类。仅当您计划在设备启动时立即采取措施时,才需要boot_completed意图。但是事实并非如此。他只有在SMS到达时才会采取措施。

– W0rmH0le
18年7月13日在16:20

#3 楼

在清单中添加广播接收器:

  <receiver android:name=".BootReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
            <category android:name="android.intent.category.DEFAULT"/>
        </intent-filter>
    </receiver>


创建类BootReciever.java

public class BootReceiver extends BroadcastReceiver {
   @Override
   public void onReceive(Context context, Intent intent) {
       if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){

           // +++ Do Operation Here +++

       }
   }
}


#4 楼

除了@Javanator回答,我想提供一个针对(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)的Android版本的保护套就我而言,这适用于Android SDK 29(10)

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
      context.startForegroundService(new Intent(context,FloatingWindow.class));
} else {
      context.startService(new Intent(context, FloatingWindow.class));
  }


#5 楼

使用此代码并在清单中还提及广播:

public class BootService extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
            Toast.makeText(context, "Boot Completed", Toast.LENGTH_SHORT).show();
            //write code here
        }
    }
}