android service设置persistent,Persistent Service on Android

本文探讨了如何创建一个Android应用中可跨Activity使用的MediaPlayer Service,并实现背景音乐播放及前台通知。重点在于解决服务在用户切换应用时如何保持运行并显示通知的问题,包括`onStartCommand`和`startForeground`的使用,以及Service生命周期管理的关键点。

I am trying to write a service that comes with a MediaPlayer. I have different Activities accessing it, so I thought it would be best to peruse a Service.

It works fine so far, I have also added a call to startForeground, as described here. The notification shows up.

But when I now press the home or back button on the device, the service is stopped and onDestroy is called, and the notification icon disappears. When I return, the service seems to reBind just fine.

I stop the music playback on onDestroy, so of course it stops. But I would like to keep the notification and service alive even when the user is on another app.

EDIT: I hope this is the relevant part:

public class MediaPlayerService extends Service {

private static class PlayerMessageHandler extends Handler {

private final MediaPlayerService owner;

public PlayerMessageHandler(MediaPlayerService owner) {

this.owner = owner;

}

@Override

public void handleMessage(Message msg) {

// Handle

}

}

private static final int NOTIFICATION_ID = 13138;

private final Messenger messenger = new Messenger(new PlayerMessageHandler(

this));

private MediaPlayer player;

private Notification notification;

@Override

public IBinder onBind(Intent intent) {

startNotification();

return messenger.getBinder();

}

@Override

public void onCreate() {

super.onCreate();

Log.v(TAG, "Media player service created.");

player = new AudiobookPlayer(this);

new Thread(seekerUpdate).start();

isRunning = true;

}

@Override

public int onStartCommand(Intent intent, int flags, int startId) {

Log.v(TAG, "Received start id " + startId + ": " + intent);

return START_STICKY;

}

@Override

public void onDestroy() {

super.onDestroy();

Log.v(TAG, "Media player service destroyed.");

if (player.isPlaying()) {

player.pause();

}

sendMessageToUI(MSG_PLAYER_HAS_PAUSED);

isRunning = false;

}

private void sendMessageToUI(int msg) {

Log.v(TAG, "Sending " + msg);

sendMessage(Message.obtain(null, msg));

}

private void sendMessage(final Message message) {

// Send

}

private void startNotification() {

NotificationCompat.Builder builder = new NotificationCompat.Builder(

this);

builder.setSmallIcon(R.drawable.notification);

builder.setContentTitle(getString(R.string.app_name));

notification = builder.build();

startForeground(NOTIFICATION_ID, notification);

}

}

EDIT2: Methods from the activity, taken from here

@Override

protected void onStart() {

super.onStart();

// Bind to the service

bindService(new Intent(this, MediaPlayerService.class),

playerServiceConnection, Context.BIND_AUTO_CREATE);

}

@Override

protected void onStop() {

super.onStop();

// Unbind from the service

if (bound) {

unbindService(playerServiceConnection);

bound = false;

}

}

<think>好的,我现在需要帮助用户解决在Android设备上恢复出厂设置时保留persistent_properties的问题,特别是保留persist.sys相关的属性。首先,用户之前的问题和我的回答已经涉及到了如何通过修改系统源码、调整fstab文件以及使用Xposed模块等方法来实现保留persist分区的数据。现在用户引用了两篇关于persist属性的文章,可能需要结合这些信息进一步解答。 首先,引用[1]中提到,通过adb shell setprop设置的属性在重启后被清除,这说明普通的setprop可能不会写入persist分区,除非属性名以persist.开头。但用户的问题是关于恢复出厂设置时保留这些属性,所以需要确认恢复出厂设置的过程是否会清除persist分区。 根据引用[2],persist.sys.usb.config的值受ro.debuggable影响,并且是在构建过程中由post_process_props.py处理的。这可能意味着某些persist属性在系统构建时被设置,或者根据系统属性动态调整。但用户的需求是在恢复出厂设置时保留这些属性,因此需要确保恢复流程不擦除persist分区。 回顾之前的回答,我提到了persist分区的特性,恢复出厂设置默认不擦除persist分区,但厂商定制ROM可能有不同处理。用户现在可能遇到了某些厂商设备在恢复出厂设置时仍然清除persist分区的情况,需要更具体的解决方案。 接下来,我需要考虑如何验证恢复流程是否影响persist分区。可以通过检查恢复脚本或使用adb命令监控擦除过程。此外,用户可能需要修改系统源码中的恢复逻辑,或者调整fstab文件以防止persist分区被格式化。 还需要注意persistent_properties的存储位置,通常在/property目录下,但persist属性会保存在persist分区。因此,确保恢复出厂设置时不格式化该分区是关键。 可能的解决方案包括: 1. 修改恢复出厂设置的源码,跳过对persist分区的擦除。 2. 调整fstab文件,标记persist分区为不可格式化。 3. 检查厂商的擦除脚本,移除对persist分区的处理。 4. 使用Hook方法拦截擦除命令。 此外,用户可能需要了解如何备份和恢复persist属性,或者在系统构建时预置这些属性,防止被清除。例如,在构建过程中将需要的属性写入persist分区,这样即使恢复出厂设置,只要分区不被擦除,属性仍然保留。 需要验证这些方法的有效性,比如通过adb命令检查分区是否被擦除,或者属性是否在恢复后仍然存在。同时,要注意不同Android版本和厂商定制的差异,可能需要针对具体设备进行调整。 总结来说,用户需要确保恢复出厂设置流程不处理persist分区,或者修改相关脚本和配置来保留该分区的数据。需要结合之前的解决方案,并根据引用中的信息,进一步细化步骤,比如检查post_process_props.py的处理逻辑,确保persist属性在构建时正确设置,并在恢复过程中不被清除。</think>在Android设备上恢复出厂设置时保留$persist.sys$属性,需结合系统属性存储机制和恢复流程进行深度定制。以下是具体实现方案及验证方法: ### 一、属性存储机制解析 1. **persist属性持久化原理**: - $persist.sys.*$属性存储在$persist$分区下的`/persist/properties`目录 - 系统启动时通过`init`进程加载`/system/etc/prop.default`和`/vendor/default.prop`,但$persist$属性优先从持久化存储读取[^1] 2. **恢复出厂设置的清除范围**: ```bash # 典型恢复擦除流程 erase_data() { format("/data"); # 用户数据分区 format("/cache"); # 缓存分区 delete_recursive("/metadata"); # 元数据分区 } ``` ### 二、保留persistent_properties的工程方案 #### 方案一:修改恢复出厂设置核心逻辑 1. 定位关键清除函数: ```cpp // recovery.cpp static bool erase_volume(const char* volume) { if (strcmp(volume, "/persist") == 0) return false; // 拦截persist分区擦除 return android::volmgr::formatVolume(volume); } ``` 2. 调整`recovery`模块的分区处理白名单: ```diff // bootable/recovery/install/wipe_data.cpp - const vector<string> kVolumesToFormat = { "/data", "/cache", "/metadata" }; + const vector<string> kVolumesToFormat = { "/data", "/cache", "/metadata", "!/persist" }; ``` #### 方案二:定制persist分区挂载策略 1. 修改`fstab`文件添加保护标记: ```bash # device/google/redbull/fstab.hardware /dev/block/by-name/persist /persist ext4 noatime,nosuid,nodev,errors=panic wait,check,formattable=no,reservedsize=16384 ``` 2. 在`init.rc`中增强分区保护: ```bash on early-init # 防止恢复模式下挂载persist分区为可写 mount rootfs rootfs / ro remount symlink /persist/properties /property ``` #### 方案三:厂商定制ROM适配 针对引用[2]中全志芯片平台的特殊处理: 1. 修改厂商擦除脚本: ```bash # vendor/aw/homlet/prebuilt/recovery/erase.sh - rm -rf /persist/* + echo "Persist partition protection enabled" ``` 2. 调整USB控制逻辑联动: ```python # build/tools/post_process_props.py if prop_list.get_value("ro.debuggable") == "1": val = prop_list.get_value("persist.sys.usb.config", "") if "adb" not in val: prop_list.put("persist.sys.usb.config", val + ",adb") if val else "adb" ``` ### 三、验证与调试方法 1. **模拟恢复操作验证**: ```bash adb reboot recovery # 在恢复模式控制台执行 > adb sideload dummy.zip > adb shell mount | grep persist # 确认分区未重新格式化 ``` 2. **属性持久性测试**: ```bash adb shell "setprop persist.sys.demo.test 1" adb reboot adb shell "getprop persist.sys.demo.test" # 应返回1 adb shell "pm trigger factory-reset" adb reboot adb shell "getprop persist.sys.demo.test" # 仍返回1则成功 ``` 3. **分区状态检查**: ```bash adb shell dumpe2fs /dev/block/by-name/persist | grep 'Filesystem state: clean' ``` ### 四、风险规避措施 1. **双分区备份机制**: ```bash # 在init.rc中添加persist备份 on boot exec - root -- /system/bin/persist_backup.sh # persist_backup.sh内容 dd if=/dev/block/by-name/persist of=/dev/block/by-name/persist_backup bs=4096 ``` 2. **属性回滚保护**: ```java // frameworks/base/services/core/java/com/android/server/SystemService.java public void onBootPhase(int phase) { if (phase == PHASE_BOOT_COMPLETED) { String propVal = SystemProperties.get("persist.sys.critical_prop"); if (propVal.isEmpty()) { SystemProperties.set("persist.sys.critical_prop", Files.readString(Paths.get("/backup/critical_prop.txt"))); } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值