Android手把手编写儿童手机远程监控App之前台服务
- 移动开发
- 3天前
- 7热度
- 0评论
引言
本文将详细介绍如何在Android应用中实现前台服务,以确保应用在后台持续运行并执行重要任务。前台服务是一种高优先级的服务,能够在用户注意到的情况下持续运行,并且不容易被系统终止。这对于需要长时间保持连接的应用(如儿童手机远程监控)尤为重要。
什么是服务(Service)
服务(Service) 是Android中用于在后台执行长时间运行操作的一种组件。它可以独立于用户界面运行,即使应用被切换到后台或用户打开其他应用,服务仍然能够正常运行。服务主要分为两种类型:
- 后台服务:执行用户不会直接注意到的操作,如数据处理、日志清理等。当系统资源不足时,后台服务可能会被系统终止。
- 前台服务:执行用户能注意到的操作,必须显示一个通知,优先级高,系统不容易主动终止它。
由于现代Android系统对功耗的严格管理,后台服务在锁屏后可能会被暂停。因此,为了确保应用在后台持续运行,通常需要使用前台服务。
创建后台服务
项目结构
假设我们有一个名为DemoApp的项目,目前包含MainActivity页面。我们将删除其他不必要的内容,并创建一个后台服务。
创建MyService
- 右键点击app目录,选择New > Service > Service。
- 在弹出的对话框中,填写以下信息:
- 自定义类名:MyService
- Exported:选择“否”,表示该服务不会被外部应用调用。
- Enabled:选择“是”,表示该服务默认启用。
- Source Language:选择开发语言(例如Java)。
- Target Source Set:选择创建后台服务代码存放的位置。
点击“Finish”完成后台服务的创建。IDE会自动生成MyService类,并在AndroidManifest.xml文件中声明该服务。
MyService源码
package com.example.demoapp;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class MyService extends Service {
@Override
public IBinder onBind(Intent intent) {
// 返回与服务通信的通道
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.example.demoapp">
<application
android:allowBackup="true"
android:icon="@drawable/app_icon"
android:label="@string/app_name"
android:roundIcon="@drawable/app_icon_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:targetApi="31">
<service
android:name=".MyService"
android:enabled="true"
android:exported="false"></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中添加按钮
为了方便测试,我们在MainActivity中添加两个按钮,分别用于启动和停止服务。
package com.example.demoapp;
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.start_btn);
Button stopBtn = findViewById(R.id.stop_btn);
startBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, MyService.class);
startService(intent);
Toast.makeText(MainActivity.this, "服务已启动", Toast.LENGTH_SHORT).show();
}
});
stopBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, MyService.class);
stopService(intent);
Toast.makeText(MainActivity.this, "服务已停止", Toast.LENGTH_SHORT).show();
}
});
}
}重载MyService中的方法
在MyService类中,我们需要重载onCreate、onStartCommand和onDestroy方法,以便在服务的不同生命周期阶段执行相应的操作。
package com.example.demoapp;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
public class MyService extends Service {
private static final String CHANNEL_ID = "ForegroundServiceChannel";
@Override
public void onCreate() {
super.onCreate();
createNotificationChannel();
Notification notification = new Notification.Builder(this, CHANNEL_ID)
.setContentTitle("前台服务")
.setContentText("服务正在运行")
.setSmallIcon(R.drawable.ic_notification)
.build();
startForeground(1, notification);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 执行长时间运行的任务
return START_STICKY; // 服务被杀死后会重新创建
}
@Override
public void onDestroy() {
super.onDestroy();
// 清理资源
}
@Override
public IBinder onBind(Intent intent) {
// 返回与服务通信的通道
return null;
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"前台服务",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
}
}解释关键代码
- createNotificationChannel:创建通知渠道,适用于Android 8.0及以上版本。
- startForeground:将服务设置为前台服务,并显示通知。
- onStartCommand:返回START_STICKY,表示如果服务被系统杀死,系统会尝试重新创建服务。
- onDestroy:在服务被销毁时清理资源。
总结
本文详细介绍了如何在Android应用中创建和使用前台服务。通过创建前台服务,可以确保应用在后台持续运行并执行重要任务,从而提高应用的稳定性和用户体验。建议在开发需要长时间后台运行的应用时,优先考虑使用前台服务。
希望本文对你有所帮助,如果你有任何问题或建议,欢迎在评论区留言交流。
创建前台服务
在上一部分中,我们介绍了如何创建一个简单的后台服务。接下来,我们将进一步扩展这个功能,使其成为一个前台服务。前台服务在运行时会显示一个通知,这样用户可以随时了解服务的状态,并且系统也不会轻易将其终止。
添加前台服务权限
首先,我们需要在AndroidManifest.xml文件中添加前台服务所需的权限。这一步是必不可少的,因为从Android 8.0(API级别26)开始,所有前台服务都需要显式声明这一权限。
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />创建通知渠道
为了在Android 8.0及以上版本中显示通知,我们需要创建一个通知渠道。通知渠道允许用户管理和控制不同类型的通知。
private void createNotificationChannel() {
// Android 8.0+ 需要创建通知渠道
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
"SERVICE_CHANNEL",
"Service Channel",
NotificationManager.IMPORTANCE_LOW
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
}
}启动前台服务
在MyService类中,我们需要重写onStartCommand方法,并在其中调用startForeground方法来启动前台服务。startForeground方法需要两个参数:一个唯一的ID和一个Notification对象。
@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);
}创建通知
我们还需要创建一个Notification对象,该对象将在前台服务运行时显示。这个通知可以包含一些基本信息,如标题、内容和图标。此外,我们还可以设置点击通知时的行为,例如返回到主活动页面。
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, "SERVICE_CHANNEL")
.setContentTitle("儿童手机远程监控")
.setContentText("正在守护孩子的安全...")
.setSmallIcon(android.R.drawable.ic_menu_info_details)
.setContentIntent(pendingIntent)
.setOngoing(true) // 不可滑动删除
.build();
}更新主活动代码
在MainActivity中,我们需要更新按钮的点击事件,以便启动和停止前台服务。这里我们使用startForegroundService方法来启动前台服务,而不是startService。
package com.example.childmonitor;
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代码
以下是完整的MyService类代码,包含了所有必要的方法和逻辑:
package com.example.childmonitor;
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(
"SERVICE_CHANNEL",
"Service Channel",
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, "SERVICE_CHANNEL")
.setContentTitle("儿童手机远程监控")
.setContentText("正在守护孩子的安全...")
.setSmallIcon(android.R.drawable.ic_menu_info_details)
.setContentIntent(pendingIntent)
.setOngoing(true) // 不可滑动删除
.build();
}
}运行效果
完成以上步骤后,运行应用程序,点击“启动”按钮,你会看到一个通知出现在通知栏中,表示前台服务已经启动。点击“停止”按钮,通知将消失,前台服务也会被终止。
至此,我们已经成功地创建了一个前台服务,用于儿童手机的远程监控。希望这篇文章对你有所帮助!如果有任何问题或建议,请在评论区留言。