如何收听已连接电源的 Android > 8

Ali*_*cia 4 android kotlin

我有一个简单的 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>
Run Code Online (Sandbox Code Playgroud)

充电实用程序

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`
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在以后的 Android 版本中,如何实现广播有一些变化:https : //developer.android.com/guide/components/broadcasts

到目前为止我尝试过的:

  • 我尝试遵循此文档,但它们的实现实际上与我当前的代码相同(仅适用于 Android 8 以下)。
  • 我也发现了这个问题,但唯一的解决方案是定期检查电源是否已连接。我认为这对我来说不太可行,因为我的应用程序需要立即知道充电状态何时发生变化。

所以我的问题是:

连接/断开电源时如何调用函数?同时考虑到运行 Android 8 或更高版本的系统对清单声明的接收器施加的额外限制。

注意:我正在使用 Kotlin,并希望避免使用已弃用的软件包


说到 Android,我有点菜鸟,很抱歉,如果我刚刚错过了一个明显的解决方案。在此先感谢您的帮助。

Deˣ*_*Deˣ 6

你提到的问题已经有了答案。

用于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
            }
        };
}
Run Code Online (Sandbox Code Playgroud)

您还可以JobScheduler使用setRequiresChargingtrue注册 a 。这将在电源状态改变时开始调用 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());
Run Code Online (Sandbox Code Playgroud)


Ben*_*uel 6

从 Android 8.0(API 级别 26 及更高版本)开始,您无法使用静态接收器接收大多数 Android 系统广播(请阅读此处)

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)
Run Code Online (Sandbox Code Playgroud)

您剩下的就是注册和注销您的注册

this.registerReceiver(mReceiver, filter); // using activity context.
this.unregisterReceiver(mReceiver); // implement on onDestroy().
Run Code Online (Sandbox Code Playgroud)