上节完成Activity内容。主要内容是Activity三种常用传参方式,分别是
- 传递基本数据类型
- 传递Bundle对象(适合传递大量数据)
- 通过Serializable传递对象数据 服务(Service)是Android实现后台程序运行的解决方案,非常适合去执行不需要与用户交互而且要求长期运行的任务。程序的运行不依赖任何用户界面,即使程序被切换到后台,或者用户打开另一程序,服务仍然能够正常运行。服务分为两种
- 后台服务,执行用户不会直接注意到的操作,如数据处理,日志清理等,资源不足可能会被系统终止
- 前台服务,执行用户能注意到的操作,必须显示一个Notification,优先级高,系统不容易主动终止它
由于嘟宝使用MQTT一直保持后台连接在线,属后台静默程序。现今Android对于功耗设计,在锁屏之后,后台程序占用资源过多,会被暂停,这就要求嘟宝后台程序驻留线程对资源的暂用极低,且必须使用前台服务,持续激活状态。
创建后台服务
后台服务是应用程序在不直接与用户交互时执行的操作,它也是创建前台服务一部分。嘟宝工程目前含有MainActivity、HelloWorldActivity两个页面,Fish类,只保留MainActivity页面。
- 删除其他不需要内容,创建后台服务
- 重载onCreate、onStartCommand、onDestroy函数
创建MyService
右键app目录>new > Service>Service
点击Finish完成后台服务创建,其中,
- 自定义类名:MyService类型
- Exported服务是否被外界调用
- Enbled服务是否打开
- Srouce Language 开发语言
- Target Source Set 创建后台服务代码存放位置,服务的用途归谁,如下图:
通过IDE创建后台服务,生成两部分内容
- 一是创建类名MyService
- 二是在AndroidManifest中声明后台服务 MyService源码
package com.zilong.dubao;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
AndroidManifest文件代码
<?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.zilong.dubao">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@drawable/fav"
android:label="@string/app_name"
android:roundIcon="@drawable/favround"
android:supportsRtl="true"
android:theme="@style/Theme.DuBao"
tools:targetApi="31">
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
<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>
</activity>
</application>
</manifest>
重载onCreate、onStartCommand、onDestroy函数
- 在MainActivity类中添加两个按钮
- 介绍Toast用法
- 在MyService类中,重载onCreate、onStartCommand、onDestroy Toast 是 Android 中一个非常常用的系统组件,用于在屏幕上以浮窗的形式显示简短的通知信息。它不会获取焦点,显示一小段时间后会自动消失,不会影响用户对当前应用的操作。 如下代码,单击按钮创建Toast 显示一小段文字
Button startbtn=findViewById(R.id.startbtn);
startbtn.setOnClickListener(v->{
Toast.makeText(this,"hello,我是Toast",Toast.LENGTH_SHORT).show();
});
效果如下:
- onCreate首次创建后台服务时调用,且只被调用一次
- onStartCommand多次创建后台服务,每次服务被创建都被调用
- onDestroy后台服务被销毁时,调用 MainActivity代码
package com.zilong.dubao;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startbtn=findViewById(R.id.startbtn);
startbtn.setOnClickListener(v->{
Intent intent = new Intent(this, MyService.class);
startService(intent);
});
Button stopbtn=findViewById(R.id.stopbtn);
stopbtn.setOnClickListener(v->{
Intent intent = new Intent(this, MyService.class);
stopService(intent);
});
}
}
MyService代码
package com.zilong.dubao;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
public class MyService extends Service {
public MyService() {
}
@Override
public void onCreate() {
super.onCreate();
Toast.makeText(this,"后台服务onCreate",Toast.LENGTH_SHORT).show();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this,"后台服务onStartCommand",Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Toast.makeText(this,"后台服务onDestroy",Toast.LENGTH_SHORT).show();
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
运行效果如下:
创建前台服务
- 根据创建后台服务的方法创建服务MyService
- 在AndroidManifest添加权限前台服务权限
- 在MyService启动后创建前台图标
- 在MainActivity启动服务 MainActivity代码
package com.zilong.dubao;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startbtn=findViewById(R.id.startbtn);
startbtn.setOnClickListener(v->{
Intent intent = new Intent(this, MyService.class);
startForegroundService(intent);
});
Button stopbtn=findViewById(R.id.stopbtn);
stopbtn.setOnClickListener(v->{
Intent intent = new Intent(this, MyService.class);
stopService(intent);
});
}
}
MyService代码
package com.zilong.dubao;
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 android.widget.Toast;
import androidx.core.app.NotificationCompat;
public class MyService extends Service {
public MyService() {
}
@Override
public void onCreate() {
super.onCreate();
Toast.makeText(this,"后台服务onCreate",Toast.LENGTH_SHORT).show();
createNotificationChannel();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this,"后台服务onStartCommand",Toast.LENGTH_SHORT).show();
startForeground(10001, createNotification());
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Toast.makeText(this,"后台服务onDestroy",Toast.LENGTH_SHORT).show();
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
private void createNotificationChannel() {
// Android 8.0+ 需要创建通知渠道
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
"DUBAO",
"嘟宝安心守护孩子安全",
NotificationManager.IMPORTANCE_LOW
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
}
}
private Notification createNotification() {
// 点击通知返回应用
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(
this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
);
return new NotificationCompat.Builder(this, "DUBAO")
.setContentTitle("嘟宝")
.setContentText("嘟宝安心守护孩子安全...")
.setSmallIcon(android.R.drawable.ic_menu_info_details)
.setContentIntent(pendingIntent)
.setOngoing(true) // 不可滑动删除
.build();
}
}
AndroidManifest代码
<?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.zilong.dubao">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@drawable/fav"
android:label="@string/app_name"
android:roundIcon="@drawable/favround"
android:supportsRtl="true"
android:theme="@style/Theme.DuBao"
tools:targetApi="31">
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
<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>
</activity>
</application>
</manifest>
运行效果如下:
至此前台服务启动完成