Service (二) 前台服务&通知

1. 配置清单

  1.1 build.gradle 添加 lifecycle 库

dependencies {
    implementation 'androidx.lifecycle:lifecycle-service:2.6.0-alpha02'
    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.0-alpha03'
    implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.0-alpha03'
   // implementation 'androidx.work:work-runtime-ktx:2.7.1'
}

  1.2 AndroidManifest.xml 添加权限

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

  1.3 添加服务

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

  1.4 Activity 添加单例模式

        <activity
            android:name=".MainActivity"
            android:launchMode="singleInstance"
            android:exported="true">

  1.5 添加系统矢量图标 ic_android_black_24dp.xml

2. 布局文件 activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:textSize="34sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.376" />

</androidx.constraintlayout.widget.ConstraintLayout>

3. 创建是否打开权限工具类 UtilsNew.kt

object UtilsNew {
    //监测通知权限
    fun isPermissionOpen(context: Context?): Boolean {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationManagerCompat.from(context!!).importance != NotificationManager.IMPORTANCE_NONE
        } else NotificationManagerCompat.from(context!!).areNotificationsEnabled()
    }

    fun openPermissionSetting(context: Context) {
        try {
            val localIntent = Intent()
            localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            //直接跳转到应用通知设置的代码:
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                localIntent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
                localIntent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName())
                context.startActivity(localIntent)
                return
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                localIntent.action = "android.settings.APP_NOTIFICATION_SETTINGS"
                localIntent.putExtra("app_package", context.getPackageName())
                localIntent.putExtra("app_uid", context.getApplicationInfo().uid)
                context.startActivity(localIntent)
                return
            }
            if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
                localIntent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
                localIntent.addCategory(Intent.CATEGORY_DEFAULT)
                localIntent.data = Uri.parse("package:" + context.getPackageName())
                context.startActivity(localIntent)
                return
            }

            //4.4以下没有从app跳转到应用通知设置页面的Action,可考虑跳转到应用详情页面,
            if (Build.VERSION.SDK_INT >= 9) {
                localIntent.action = "android.settings.APPLICATION_DETAILS_SETTINGS"
                localIntent.data = Uri.fromParts("package", context.getPackageName(), null)
                context.startActivity(localIntent)
                return
            }
            localIntent.action = Intent.ACTION_VIEW
            localIntent.setClassName(
                "com.android.settings",
                "com.android.setting.InstalledAppDetails"
            )
            localIntent.putExtra(
                "com.android.settings.ApplicationPkgName",
                context.getPackageName()
            )
        } catch (e: Exception) {
            e.printStackTrace()
            println(" cxx   pushPermission 有问题")
        }
    }
}

4. 创建服务 MyService.kt

const val CHANNEL_ID = "my notification channel ID"

class MyService : LifecycleService() {
    private var mTAG = "MyTag"
    private var number = 0
    val numberLive = MutableLiveData(0)

    @SuppressLint("UnspecifiedImmutableFlag")
    override fun onCreate() {
        super.onCreate()
        lifecycleScope.launch {
            while (true) {
                delay(1_000)
                numberLive.value = numberLive.value?.plus(1)
                Log.i(mTAG, "onCreate ${number++}")
            }
        }
        createChannel()
        val notificationIntent = Intent(this, MainActivity::class.java)
        val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
            PendingIntent.getActivity(this, 1, notificationIntent, PendingIntent.FLAG_IMMUTABLE)
        else
            PendingIntent.getActivity(this, 1, notificationIntent, PendingIntent.FLAG_ONE_SHOT)

        val notification = NotificationCompat.Builder(this, CHANNEL_ID)
            .setSmallIcon(R.drawable.ic_android_black_24dp)
            .setWhen(System.currentTimeMillis())
            .setContentTitle("This is a title.")
            .setContentText("This is a notification.")
            .setContentIntent(pendingIntent)
            .build()
        startForeground(1, notification)
    }

    //内部类
    inner class MyBinder: Binder(){
        val getService = this@MyService
    }

    override fun onBind(intent: Intent): IBinder {
        super.onBind(intent)
        return MyBinder()
    }

    //创建 通道ID
    private fun createChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // Create the NotificationChannel
            val name = "My notification channel No.1"
            //IMPORTANCE_HIGH IMPORTANCE_DEFAULT
            val importance = NotificationManager.IMPORTANCE_DEFAULT
            val mChannel = NotificationChannel(CHANNEL_ID, name, importance)
            // Register the channel with the system; you can't change the importance
            // or other notification behaviors after this
            val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(mChannel)
        }
    }
}

5. 调用 MainActivity.kt

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //also apply 里边的主语不一样
        if (!UtilsNew.isPermissionOpen(this)){
            UtilsNew.openPermissionSetting(this)
        }else{
            //跳转Service
            jumpService()
        }
    }

    private fun jumpService(){
        val textView: TextView = findViewById(R.id.textView)
        val serviceConnection = object : ServiceConnection{
            override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
                (service as MyService.MyBinder).getService.numberLive.observe(this@MainActivity){
                    textView.text = it.toString()
                }
            }
            override fun onServiceDisconnected(name: ComponentName?) {
            }
        }
        Intent(this,MyService::class.java).apply {
            startService(this)
            bindService(this,serviceConnection,Context.BIND_AUTO_CREATE)
        }
    }
}

6. 效果图

       

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要搭建前台服务,需要创建一个服务类并在其中实现服务的逻辑,然后将该服务绑定到应用程序的UI界面上。 下面是一个简单的前台服务搭建的步骤: 1. 创建一个服务类,继承自 Service 类。 ``` public class MyForegroundService extends Service { ... } ``` 2. 在服务类中实现服务的逻辑。 ``` public class MyForegroundService extends Service { ... @Override public int onStartCommand(Intent intent, int flags, int startId) { // 在此处编写服务逻辑 ... return START_STICKY; } ... } ``` 3. 在服务类中创建一个通知,用于在系统通知栏中显示服务的状态。 ``` public class MyForegroundService extends Service { ... @Override public void onCreate() { super.onCreate(); // 创建通知 Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("My Foreground Service") .setContentText("Service is running...") .setSmallIcon(R.drawable.ic_notification) .build(); // 启动服务,并将服务设置为前台服务 startForeground(1, notification); } ... } ``` 4. 在服务类中实现 onBind() 方法,返回 null。 ``` public class MyForegroundService extends Service { ... @Nullable @Override public IBinder onBind(Intent intent) { return null; } ... } ``` 5. 在应用程序的 UI 界面中绑定服务,并启动服务。 ``` Intent intent = new Intent(this, MyForegroundService.class); startService(intent); ``` 以上就是搭建前台服务的基本步骤。需要注意的是,在 Android 8.0 及以上版本中,前台服务必须创建一个 NotificationChannel 并将其与通知相关联,否则服务将无法启动。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hanyang Li

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值