当前位置: 首页 > news >正文

[Android]APP自启动

APP添加自启动权限,重启设备后自动打开APP。

1.AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.mofang.call.callphone">

    <!-- 声明前台服务的权限 -->
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <!--  注册 BOOT_COMPLETED 广播接收器  -->
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
  
    <application
        android:name=".App"
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:extractNativeLibs="true"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:requestLegacyExternalStorage="true"
        android:roundIcon="@mipmap/ic_launcher"
        android:supportsRtl="true"
        android:theme="@style/Theme.MFCallPhone"
        android:usesCleartextTraffic="true"
        tools:targetApi="31">

        <service android:name=".MyAppLaunchService"
            android:exported="true" />

        <!-- 注册接收 BOOT_COMPLETED 广播的接收器 -->
        <receiver
            android:name=".BootReceiver"
            android:enabled="true"
            android:exported="true"
            android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

2.BootReceiver

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build

/// 创建一个接收 BOOT_COMPLETED 广播的接收器类 BootReceiver。
class BootReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if (intent.action == Intent.ACTION_BOOT_COMPLETED) {
            // 启动你的服务或活动
            val serviceIntent = Intent(context, MyAppLaunchService::class.java)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                context.startForegroundService(serviceIntent)
            } else {
                context.startService(serviceIntent)
            }
        }
    }
}

3.MyAppLaunchService

import android.annotation.SuppressLint
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Intent
import android.os.Build
import android.os.IBinder
import androidx.core.app.NotificationCompat

/// 创建一个服务(例如 MyAppLaunchService),在设备重启后由 BootReceiver 启动。
class MyAppLaunchService : Service() {

    override fun onCreate() {
        super.onCreate()
        createNotificationChannel()
    }

    override fun onBind(intent: Intent?): IBinder? {
        return null
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        // 你的业务逻辑...
        // 启动前台服务
        startForegroundService()
        // 启动应用的主活动
        restartApp()
        return START_STICKY
    }

    private fun restartApp() {
        val packageManager = packageManager
        val intent = packageManager.getLaunchIntentForPackage(packageName)
        if (intent != null) {
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            startActivity(intent)
        }
    }

    private fun createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val serviceChannel = NotificationChannel(
                MyForegroundService.CHANNEL_ID,
                "Foreground Service Channel",
                NotificationManager.IMPORTANCE_DEFAULT
            )
            val manager = getSystemService(NotificationManager::class.java)
            manager.createNotificationChannel(serviceChannel)
        }
    }

    @SuppressLint("ForegroundServiceType")
    private fun startForegroundService() {
        val notificationIntent = Intent(this, StartPageActivity::class.java)//MainActivity::class.java)
        val pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent,
            PendingIntent.FLAG_IMMUTABLE)//0
        val notification: Notification = NotificationCompat.Builder(this,
            MyForegroundService.CHANNEL_ID
        )
            //.setContentTitle("前台服务")
            //.setContentText("前台保活服务") // 你的应用程序在前台运行
            .setSmallIcon(R.mipmap.icon_home_2_s) 
            .setContentIntent(pendingIntent)
            .build()

        startForeground(1, notification)
    }
}

注意调用startForegroundService时有可能的报错

在 Android 8.0(API 26)及更高版本中,如果你调用 startForegroundService 方法启动服务,服务必须在短时间内调用 startForeground 方法来显示通知,否则系统会抛出 RemoteServiceException。

报错:
FATAL EXCEPTION: main
Process: com.my.call.callphone, PID: 3202
android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{3336361 u0 com.mofang.call.callphone/.MyAppLaunchService}
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1970)
    at android.os.Handler.dispatchMessage(Handler.java:107)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7386)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:980)

解决:
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        NSLog("启动4")
        // 你的业务逻辑...
        // 启动前台服务
        startForegroundService()

        // 启动应用的主活动
        restartApp()

        return START_STICKY
    }

相关文章:

  • 探寻 AI 发展新航道:下一个 “S 曲线” 的突破点在哪?
  • 探索关键领域的AI工具:机器学习、深度学习、计算机视觉与自然语言处理
  • 深入理解 Java Servlet:从基础到实战
  • vue3学习1
  • Spring Boot 应用(官网文档解读)
  • 新能源汽车核心元件揭秘:二极管、三极管结构与工作原理解析(2/2)
  • 算法基础(思想)
  • OSPF | 理论 / 实验
  • 技术成长战略是什么?
  • Windows 主机与安卓设备网线直连配置教程
  • spark
  • RNN中远距离时间步梯度消失问题及解决办法
  • git使用-克隆远程项目、分支管理
  • I2C实践开发 ---【STM32-I2C-HDC1080温湿度采集系统】
  • 期权帮|股指期货中的套期保值如何操作?
  • Redis三剑客解决方案
  • 模板方法模式原理结构以及在Spring源码中的使用。
  • 前端接收后端19位数字参数,精度丢失的问题
  • 二叉树层序遍历的三种情况(总结)
  • ResponseUtil.out 方法分析
  • 农行再回应客户办理业务期间离世:亲属连续三次输错密码,理解亲属悲痛,将协助做好善后
  • MSCI中国指数5月调整:新增5只A股、1只港股
  • 白天气温超30℃的北京,晚间下起了冰雹
  • 超新星|18岁冲击中超金靴,王钰栋的未来无限可能
  • 权益类基金发行回暖,这些老将挂帅新基,谁值得买?
  • 影子调查丨三名“淘金客”殒命雪峰山:千余废弃金矿洞的监管难题