一、继承
java.lang.Object
↳ android.content.Context
↳ android.content.ContextWrapper
↳ android.app.Service
二、简介
service:Android四大组件之一,处理不需要在界面上显示的工作
三、配置
需要在AndroidManifest.xml中,注册service基本信息
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.ServiceDemo"
tools:targetApi="31">
<service
android:name=".TestService"
android:enabled="true"
android:exported="true"/>
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
</application>
</manifest>
四、公共方法
- getApplication() 返回当前服务应用程序
- getForegroundServiceType() 如果服务已通过调用成为前台服务 startForeground(int, android.app.Notification) 或 startForeground(int, android.app.Notification, int), getForegroundServiceType() 返回当前前台服务类型
- onBind(intent: Intent) 将通信信道返回到服务。如果不绑定到服务,设置为null
- onCreate() 首次创建服务时由系统调用,如果服务存在,则不在调用
- onStartCommand(intent: Intent, flags: Int, startId: Int) 每次启动服务时,系统都会调用该方法
- onUnbind(intent: Intent) 断开与服务链接时调用
- onDestroy() 服务销毁时调用
- onConfigurationChanged(newConfig: Configuration) 当设备配置更改时由系统调用,而 组件正在运行
- onLowMemory() 当整个系统内存不足时,将调用此值,并且 主动运行的进程应减少其内存使用量。
- onRebind(Intent intent) 当新客户端连接到该服务时调用,此前该服务在其onUnbind中被通知所有客户端都已断开连接。只有当onUnbind的实现被重写以返回true时,才会调用此函数。
- onTaskRemoved(Intent rootIntent) 如果服务当前正在运行,并且用户删除了来自服务应用程序的任务,则调用此操作。如果您已设置ServiceInfo.FLAG_STOP_WITH_TASK,则不会收到此回调;相反,该服务将被简单地停止。
- onTimeout(int startId) 超时调用
- onTrimMemory(int level) 当操作系统确定它是好的时调用 进程从其进程中修剪不需要的内存的时间。
- startForeground(int id, Notification notification) 如果您的服务已启动(运行 Context#startService(Intent)),然后 还要使此服务在前台运行,提供正在进行的 处于此状态时向用户显示的通知。
- stopForeground(int notificationBehavior) 从前台状态删除此服务,允许在以下情况下将其终止 需要更多的内存。
- stopSelf() 停止该服务
五、生命周期
1.不绑定服务,通过startService启动服务
- onCreate() 创建Service,首次创建调用
- onStartCommand() 服务开始运行
- onDestroy() 销毁服务
2.绑定服务,通过startService启动服务
- onCreate() 创建Service,首次创建调用
- onBind() 绑定服务,服务开始运行
- onUnbind() 解除绑定
- onDestroy() 销毁服务
六、实例
1.不绑定服务
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.ServiceDemo"
tools:targetApi="31">
<service
android:name=".TestService"
android:enabled="true"
android:exported="true"/>
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
</application>
</manifest>
class TestService : Service() {
val TAG = "TestService"
override fun onCreate() {
super.onCreate()
Log.i(TAG, "onCreate")
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.i(TAG, "onStartCommand")
return super.onStartCommand(intent, flags, startId)
}
override fun onBind(intent: Intent): IBinder? {
Log.i(TAG, "onBind")
return null
}
override fun onUnbind(intent: Intent?): Boolean {
Log.i(TAG, "onUnbind")
return super.onUnbind(intent)
}
override fun onDestroy() {
super.onDestroy()
Log.i(TAG, "onDestroy")
}
}
class MainActivity : AppCompatActivity() {
private lateinit var btn_startService: Button
private lateinit var btn_stopService: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initView()
initData()
initClick()
}
private fun initView() {
btn_startService = findViewById(R.id.btn_startService)
btn_stopService = findViewById(R.id.btn_stopService)
}
private fun initData() {
}
private fun initClick() {
btn_startService.setOnClickListener {
startService(Intent(this, TestService::class.java))
}
btn_stopService.setOnClickListener {
stopService(Intent(this, TestService::class.java))
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_startService"
android:layout_width="300dp"
android:layout_height="100dp"
android:text="启动服务"
android:textSize="40sp" />
<Button
android:id="@+id/btn_stopService"
android:layout_width="300dp"
android:layout_height="100dp"
android:layout_marginTop="30dp"
android:text="停止服务"
android:textSize="40sp" />
</LinearLayout>
2.绑定服务
class TestService : Service() {
val TAG = "TestService"
override fun onCreate() {
super.onCreate()
Log.i(TAG, "onCreate")
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.i(TAG, "onStartCommand")
return super.onStartCommand(intent, flags, startId)
}
override fun onBind(intent: Intent): IBinder? {
Log.i(TAG, "onBind")
return TestBinder()
}
override fun onUnbind(intent: Intent?): Boolean {
Log.i(TAG, "onUnbind")
return true
}
override fun onDestroy() {
super.onDestroy()
Log.i(TAG, "onDestroy")
}
class TestBinder : Binder() {
fun dragon(mContext: Context) {
Toast.makeText(mContext, "呜呼~", Toast.LENGTH_LONG).show()
}
}
}
class TestServiceConnection : ServiceConnection {
val TAG = "TestServiceConnection"
lateinit var testBinder: TestService.TestBinder
lateinit var mContext: Context;
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
Log.i("TAG", "onServiceConnected")
testBinder = service as TestService.TestBinder;
testBinder.dragon(mContext)
}
override fun onServiceDisconnected(name: ComponentName?) {
Log.i("TAG", "onServiceDisconnected")
}
fun getContext(context: Context) {
mContext = context
}
}
class MainActivity : AppCompatActivity() {
private lateinit var btn_startService: Button
private lateinit var btn_stopService: Button
private lateinit var mServiceConnection: TestServiceConnection
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initView()
initData()
initClick()
}
private fun initView() {
btn_startService = findViewById(R.id.btn_startService)
btn_stopService = findViewById(R.id.btn_stopService)
}
private fun initData() {
mServiceConnection= TestServiceConnection()
mServiceConnection.getContext(applicationContext)
}
private fun initClick() {
btn_startService.setOnClickListener {
bindService(
Intent(this, TestService::class.java),
mServiceConnection,
BIND_AUTO_CREATE
)
}
btn_stopService.setOnClickListener {
unbindService(mServiceConnection)
}
}
}
七、IntentService
private const val UPDATE_APP = "com.example.second.action.UpdateApp"
class DownloadService : IntentService("DownloadService") {
override fun onHandleIntent(intent: Intent?) {
//执行耗时工作
when (intent?.action) {
UPDATE_APP -> {
val url = intent.getStringExtra("updateApp")
if (null != url) {
download(applicationContext, url)
}
}
}
}
companion object {
@JvmStatic
fun startDownload(context: Context, url: String) {
val intent = Intent(context, DownloadService::class.java).apply {
action = UPDATE_APP
putExtra("updateApp", url)
}
context.startService(intent)
}
}
private fun download(context: Context, url: String) {
val request = DownloadManager.Request(Uri.parse(url))
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "test.apk")
request.setAllowedOverRoaming(false)
request.setTitle("test")
request.setDescription("version update")
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)
val downloadManager: DownloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
downloadManager.enqueue(request)
context.registerReceiver(receiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
}
private fun getDownloadPath(): String {
val download: File = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
if (!download.exists()) {
download.mkdirs()
}
return download.path + "/test.apk"
}
private val receiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val downloadManager = context.getSystemService(DOWNLOAD_SERVICE) as DownloadManager
val downloadID = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0)
val query = DownloadManager.Query()
query.setFilterById(downloadID)
val cursor: Cursor = downloadManager.query(query)
if (cursor.moveToFirst()) {
val state = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS))
if (state == DownloadManager.STATUS_SUCCESSFUL) {
val intent = Intent(Intent.ACTION_VIEW)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
if (Build.VERSION.SDK_INT >= 24) {
val file= File(getDownloadPath())
if (!file.exists()) {
return
}
val apkUri = FileProvider.getUriForFile(
context,
context.packageName +".provider",
file
)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent.setDataAndType(apkUri, "application/vnd.android.package-archive")
} else {
intent.setDataAndType(
Uri.fromFile(
File(
context.getExternalFilesDir(
Environment.DIRECTORY_DOWNLOADS
), "test"
)
), "application/vnd.android.package-archive"
)
}
context.startActivity(intent)
}
}
cursor.close()
}
}
override fun onDestroy() {
super.onDestroy()
//注销广播
unregisterReceiver(receiver)
}
}
<service
android:name=".DownloadService"
android:exported="false" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_path" />
</provider>
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http:/android:/schemas.android.com/apk/res/android">
<!--res->xml->file_path.xml-->
<external-path
name="external"
path="." />
<external-files-path
name="external_files"
path="." />
<cache-path
name="cache"
path="." />
<external-cache-path
name="external_cache"
path="." />
<files-path
name="files"
path="." />
</paths>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
//调用
DownloadService.startDownload(this,"下载路径")