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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions