Skip to content

如何兼容前台服务 #1413

@mikelhm

Description

@mikelhm

作者你好,请教一下如何兼容前台服务?

问题:插件模式下启动前台服务无反应;独立APP 模式下启动前台服务正常

我基于 Sample-app 添加了启动前台服务的代码,

我 fork 的代码就2笔提交:

  1. [[feature]sample demo 升级target sdk 35 gradle 8.5.2 kotlin 1.9.25] (ad736c4)

  2. [feature] sample plugin 添加前台服务启动的user case

Image

PluginForegrounService的实现

public class PluginForegrounService extends Service {

    private static final String TAG = "PluginForegrounService";
    private static final String CHANNEL_ID = "plugin_foreground_channel";
    private static final String CHANNEL_NAME = "插件前台服务";
    private static final int NOTIFICATION_ID = 10001;

    @Override
    public void onCreate() {
        Log.d(TAG, "PluginForegrounService onCreate ");
        createNotificationChannel();
    }

    @Override
    public void onDestroy() {
        Log.d(TAG, "PluginForegrounService onDestroy ");
    }

    @SuppressLint("ForegroundServiceType")
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "PluginForegrounService onStartCommand ");
        startForeground(NOTIFICATION_ID, createNotification());
        return START_STICKY;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    /**
     * 创建通知channel
     */
    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                    CHANNEL_ID,
                    CHANNEL_NAME,
                    NotificationManager.IMPORTANCE_HIGH
            );
            channel.setDescription("插件前台服务运行通知");

            NotificationManager manager = (NotificationManager)
                    getSystemService(Context.NOTIFICATION_SERVICE);
            if (manager != null) {
                manager.createNotificationChannel(channel);
            }
        }
    }

    /**
     * 创建通知
     */
    private Notification createNotification() {
        NotificationCompat.Builder builder;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            builder = new NotificationCompat.Builder(this, CHANNEL_ID);
        } else {
            builder = new NotificationCompat.Builder(this);
            builder.setPriority(NotificationCompat.PRIORITY_DEFAULT);
        }

        return builder
                .setContentTitle("插件服务运行中")
                .setContentText("插件前台服务正在运行...")
                .setSmallIcon(android.R.drawable.ic_btn_speak_now)
                .setOngoing(true)
                .setAutoCancel(false)
                .setWhen(System.currentTimeMillis())
                .build();
    }

    /**
     * 启动前台服务的静态方法(供外部调用)
     */
    public static void start(Context context) {
        Intent intent = new Intent(context.getApplicationContext(), PluginForegrounService.class);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // Android 8.0+ 必须使用 startForegroundService
            context.getApplicationContext().startForegroundService(intent);
        } else {
            // Android 8.0以下使用普通startService
            context.getApplicationContext().startService(intent);
        }
    }

    /**
     * 停止服务的静态方法
     */
    public static void stop(Context context) {
        Intent intent = new Intent(context.getApplicationContext(), PluginForegrounService.class);
        context.getApplicationContext().stopService(intent);
    }
}

AndroidManifest 新增前台服务权限:

    <!--通知权限-->
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
    <!-- 前台服务权限 -->
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />

       <service android:name=".usecases.service.PluginForegrounService" android:exported="true"
            android:foregroundServiceType="specialUse">
        </service>

我理解应该要在宿主弄一个壳子服务来处理?
那它怎么和插件的服务关联起来呢?——当插件中代码调用 context.getApplicationContext().startForegroundService(intent)的时候怎么走到宿主的壳子服务里进行响应,然后再分发呢?

像Activity 可以定义壳子代理和插件组件的关联,那服务应该也有类似的关联机制么?

    @Override
    public ComponentName onBindContainerActivity(ComponentName pluginActivity) {
        switch (pluginActivity.getClassName()) {
            /**
             * 这里配置对应的对应关系
             */
        }
        return new ComponentName(context, DEFAULT_ACTIVITY);
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions