我有一个简单的Android Kotlin应用程序,它的一部分工作是在接通和断开电源时监听并执行操作
这是我的旧代码,在定位Oreo以下的设备时效果很好。
AndroidManifest.xml
<receiver android:name=".ChargingUtil$PlugInReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
</intent-filter>
</receiver>
ChargingUtil.kt
class ChargingUtil (context: Context){
/*... Some other charging-related functions here ... */
class PlugInReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Log.d("thisistest", "Power was changed")
// Here I do some logic with `intent.action`
}
}
}
在更高的Android版本中,对实现广播的方式进行了一些更改:https://developer.android.com/guide/components/broadcasts
到目前为止,我已经尝试过:
所以我的问题是:
电源连接/断开时如何调用功能? 考虑到运行Android 8或更高版本的系统对清单施加的其他限制,声明接收者。
注意:我正在使用Kotlin,并希望避免使用不赞成使用的软件包
在Android方面,我有点菜鸟,如果实际上有一个我刚错过的明显解决方案,对不起。在此先感谢您的帮助。
答案 0 :(得分:4)
您提到的问题已经有了答案。
启动后,使用ACTION_BOOT_COMPLETED
启动前台服务。此服务应注册ACTION_POWER_CONNECTED
广播。您也可以在单独的过程中启动此服务。一旦电源接通/断开,您将收到服务类别中的广播,您可以在其中运行所需的方法。
public class MyService extends Service {
private String TAG = this.getClass().getSimpleName();
@Override
public void onCreate() {
Log.d(TAG, "Inside onCreate() API");
if (Build.VERSION.SDK_INT >= 26) {
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
mBuilder.setSmallIcon(R.drawable.ic_launcher);
mBuilder.setContentTitle("Notification Alert, Click Me!");
mBuilder.setContentText("Hi, This is Android Notification Detail!");
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// notificationID allows you to update the notification later on.
mNotificationManager.notify(100, mBuilder.build());
startForeground(100, mBuilder.mNotification);
IntentFilter filter1=new IntentFilter();
filter1.addAction(Intent.ACTION_POWER_CONNECTED);
registerReceiver(myBroadcastReceiver,filter1);
}
}
@Override
public int onStartCommand(Intent resultIntent, int resultCode, int startId) {
Log.d(TAG, "inside onStartCommand() API");
return startId;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "inside onDestroy() API");
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
BroadcastReceiver myBroadcastReceiver =new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// call your method
}
};
}
您也可以将JobScheduler
设置为setRequiresCharging
为真。更改电源状态后,这将开始调用JobScheduler的作业。
ComponentName serviceComponent = new ComponentName(context, TestJobService.class);
JobInfo.Builder builder = new JobInfo.Builder(0, serviceComponent);
builder.setMinimumLatency(1 * 1000); // wait at least
builder.setOverrideDeadline(3 * 1000); // maximum delay
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);
builder.setRequiresDeviceIdle(true);
builder.setRequiresCharging(true);
JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
jobScheduler.schedule(builder.build());
答案 1 :(得分:0)
从Android 8.0(API级别26和更高版本)开始,您不能使用静态接收器来接收大多数Android系统广播read here,
BroadcastReceiver是静态接收器还是动态接收器,具体取决于您如何注册:
要静态注册接收器,请在您的计算机中使用<receiver>
元素
AndroidManifest.xml
个文件。静态接收者也称为清单声明的接收者。
要动态注册接收者,请使用应用程序上下文或活动上下文。的 只要注册上下文有效,接收方就接收广播,即 只要相应的应用或活动正在运行。动态接收器也称为 上下文注册的接收者。
因此,您需要动态注册接收器,转到AndroidManifest.xml
并删除<receiver>
标签,然后在活动时进行注册。
private MyBatteryReceiver mReceiver = new MyBatterReceiver();
然后使用IntentFilter
进行强行操作:
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
filter.addAction(Intent.ACTION_POWER_CONNECTED)
剩下的就是注册和撤消您的注册
this.registerReceiver(mReceiver, filter); // using activity context.
this.unregisterReceiver(mReceiver); // implement on onDestroy().
答案 2 :(得分:0)
感谢@Derek的回答,加上一些修改,我终于可以使用了。将工作解决方案发布到此处,以防对其他人有帮助。
PowerConnectionReciever.kt
import android.content.Intent
import android.content.BroadcastReceiver
import android.os.IBinder
import android.content.IntentFilter
import android.app.Service
import android.content.Context
class PowerConnectionService : Service() {
private var connectionChangedReceiver: BroadcastReceiver =
object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// This block gets run whenever the power connection state is changed
when {
intent.action == Intent.ACTION_POWER_CONNECTED ->
powerWasConnected()
intent.action == Intent.ACTION_POWER_DISCONNECTED ->
powerWasDisconnected()
}
}
}
override fun onCreate() {
val connectionChangedIntent = IntentFilter()
connectionChangedIntent.addAction(Intent.ACTION_POWER_CONNECTED)
connectionChangedIntent.addAction(Intent.ACTION_POWER_DISCONNECTED)
registerReceiver(connectionChangedReceiver, connectionChangedIntent)
}
override fun onStartCommand(
resultIntent: Intent, resultCode: Int, startId: Int): Int {
return startId
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(connectionChangedReceiver)
}
override fun onBind(intent: Intent): IBinder? {
return null
}
private fun powerWasConnected() {
// Do whatever you need to do when the power is connected here
}
private fun powerWasDisconnected() {
// And here, do whatever you like when the power is disconnected
}
}
然后在我的 MainActivity.kt 文件中,添加了此函数,该函数在onCreate
挂钩中调用。
private fun startPowerConnectionListener() {
val serviceComponent = ComponentName(this, PowerConnectionService::class.java)
val builder = JobInfo.Builder(0, serviceComponent)
builder.setMinimumLatency((200)) // wait time
builder.setOverrideDeadline((200)) // maximum delay
val jobScheduler = this.getSystemService(JobScheduler::class.java)
jobScheduler.schedule(builder.build())
}
我唯一需要做的其他更改是在 AndroidMainifest.xml
中将FOREGROUND_SERVICE
的权限添加为第一级项目:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
当然,还需要注册新的PowerConnectionService
,这要在相关的activity
节点内
<service
android:name=".PowerConnectionService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="true">
</service>