修改Android手机的Preferences配置文件
来源:互联网 发布:我叫mt3 源码 编辑:程序博客网 时间:2024/04/29 16:45
我们的目的是修改Android手机中某app下的配置文件(至于为什么要修改这个配置文件呢? 你猜呀!)
即 /data/data/{package_name}/shared_prefs/{xxx}.xml文件
附:
{package_name} 为某App的包名
{xxx}为某个配置文件
修改步骤:
1. 你得把手机root
2. 下载Root Explorer,定位到上面那个路径下修改即可。
(完了, xxx 不要打偶! T_T……)
实际上,由于手机屏幕略小,如果需要经常的修改文件,在软键盘上敲下一长串无意义的文件,非常非常滴不方便的说。
即使,像哥一样聪明的知道,通过把资料才电脑发送到手机QQ上,再复制到剪贴板,然后粘贴到Root Explorer打开的配置文件里,省去了手动敲的步骤了。
但是,但是每次用食指或大拇指小心翼翼的定位光标还是十分痛苦的说。如果在修改的部分附近,即使多删去一些字符也无妨,拷贝之后,再手动打回来,也比拼人品刚好定位到好。
另外一种同步文字到手机上的方法:浏览器打开notepad.cc/xxx, 把文字拷贝进去,然后用Android手机的浏览器访问这个路径即可。
后缀xxx自定义,尽量独特一些好记一些,毕竟这也是要手敲的。。。
第二种方法, 既然配置文件是XML文件,自己去写个App程序解析不就可以了吗。
对头,虽然Java有好几种方法解析XML文件的方法,但是哥懒呀!(别打头。。。)
第三种方法,看好,要放大招了。
因为Android SDK提供了读写自家App内置配置文件的方法,好像是getSharedPreferences({xxx}, MODE_PRIVATE),
那么可不可以利用这个方法呢??
为了安全,SDK并未提供可以直接访问其他App的配置文件的方法(CreatePackageContext 和 shareUserId 使用颇多限制),
所以我们可以这样做:
把要修改的配置文件拷贝到咱自己写的App的配置文件目录下,修改后再拷贝回去。 :)
当然前提是必须先root,(葵花宝典里不是说,欲练此功,必先自宫……)root不是阉割,而像开启了潜能,获得了强大力量,控制不好可能会误伤而已。
但是(“但是”,就意味着有问题呀)
其1,注意修改的时候最好把原App先退出,不然可能不会成功的。
举个例子:
假如App启动的时候调用了getSharedPreferences方法读取了配置文件,然后咱用Root Explorer去手动修改了这个配置文件的内容,如果App之后有写入配置文件的操作,会覆盖咱修改的内容的。
原因是SharedPreferences第一次读配置文件的时候,有个缓存在内存中,之后不会再去读这个配置文件的内容了,即使手动修改文件内容也不会反应到内存中。(纯属个人推测)
但是其2 注意文件权限,特别是所有者权限,读写执行权限倒无所谓。
不同的App安装时获得临时的不同的userId,如果拷贝之后,不是当前用户的所有者,用getSharedPreferences方法保存之后实际会生成一个新的文件,并不包含原来拷贝过来的文件的内容。
所以,实际步骤是:
拷贝原文件过来,然后修改目标文件的所有者为目标userId,修改内容,完毕后,再将文件拷贝回去,同样要把权限修改回去。
操作是用Java调用系统(Linux)命令来实现的。
关键代码如下:
拷贝文件的方法:
cp -f src srcBak 先拷贝一个临时文件
chown destUid:destUid srcBak 修改临时文件的所有者为目标文件的所有者, uid和gid默认是一样的
cp -pf srcBak dest 直接覆盖目标文件
至于uid的获取:使用Utils.getFileUid(),将配置文件所在的目录(/data/data/{package_name}/shared_prefs)传进去就可以获得了。
private boolean copy(String src, String dest, String destUid) { if(!new File(src).exists()){ return false; } String srcBak = src + "_bak"; List<String> cmdList = new ArrayList<>(); cmdList.add("cp -f " + src + " " + srcBak); cmdList.add("chown " + destUid +":" + destUid +" " + srcBak); cmdList.add("cp -pf " + srcBak + " " + dest); if(Utils.runSu(cmdList, null)){ return true; } return false; }
public class Utils { private static final String TAG = "Utils"; private static Context mContext; public static final String DEFAULT_SU = "/system/xbin/su"; public static boolean isInitialized = false; /** * execute a common system command * * @param cmd */ public static void run(String cmd) { Runtime runtime = Runtime.getRuntime(); Process process = null; try { process = runtime.exec(cmd); process.waitFor(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } /** * Get a result from inputstream * * @param in * @return */ private static String getResult(InputStream in) { if (in == null) { return ""; } byte[] bytes = new byte[1024]; StringBuffer sb = new StringBuffer(); try { while (in.read(bytes) != -1) { sb.append(new String(bytes)); } return sb.toString(); } catch (IOException e) { e.printStackTrace(); return ""; } finally { try { if (in != null) { in.close(); } } catch (IOException e) { e.printStackTrace(); } } } /** * Execute a system command with root permission * * @param cmdList */ public static boolean runSu(List<String> cmdList, CmdResult result) { return runSu(cmdList, DEFAULT_SU, result); } public static boolean runSu(List<String> cmdList, String suPath, CmdResult result) { File suFile = new File(suPath); if (!suFile.exists()) { showToast("Have your phone been rooted?\nSu not exits: " + suPath, Toast.LENGTH_LONG); Log.w(TAG, "su not exists: " + suPath); return false; } if (!suFile.canExecute()) { Log.w(TAG, "su can not be executed: " + suPath); return false; } if (cmdList == null || cmdList.size() == 0) { return false; } Runtime runtime = Runtime.getRuntime(); Process process = null; long startStamp = System.currentTimeMillis(); try { process = runtime.exec(suPath); DataOutputStream os = new DataOutputStream(process.getOutputStream()); for (String cmd : cmdList) { if (!cmd.endsWith("\n")) { cmd += "\n"; } os.writeBytes(cmd); Log.d(TAG, "su cmd: " + cmd); } os.writeBytes("exit\n"); os.flush(); os.close(); InputStream in = process.getInputStream(); in = (in!=null) ? in : process.getErrorStream(); if (result!=null) { result.retStr = getResult(in); result.ret = true; Log.d(TAG, "su result: " + result.retStr); } if(process.waitFor() == 0){ return true; }else { // cost too much time, check su if(System.currentTimeMillis() - startStamp > 3*1000) { if(mContext != null) { Toast.makeText(mContext, "Have your phone been rooted?", Toast.LENGTH_LONG).show(); } } return false; } } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } return false; } /** * Get a file owner's id * @param path * @return */ public static String getFileUid(String path) { File file = new File(path); if (!file.exists()) { return ""; } List<String> cmdList = new ArrayList<String>(); if(file.isDirectory()){ cmdList.add("ls -ld " + path); }else { cmdList.add("ls -l " + path); } CmdResult cmdResult = new CmdResult(); if( runSu(cmdList, cmdResult) ){ if (cmdResult.ret) { String result = cmdResult.retStr; String[] resArr = result.split(" "); if (resArr.length > 1 && !"".equals(resArr[1])) { return resArr[1]; } } } return ""; } public static void showToast(String text , int duration) { if(mContext != null){ Toast.makeText(mContext, text, duration).show(); } }}
public class CmdResult { public boolean ret; public String retStr;}
Over!
- 修改Android手机的Preferences配置文件
- sublimetext2的配置文件Preferences.sublme-settings文件
- 7.Android Preferences的使用
- Android Preferences的基本使用
- Android Preferences
- android Preferences
- Android Preferences!
- eclipse preferences 下没有 android 的选项
- Android中Preferences的基本使用
- android数据的持久化Shared Preferences
- android porting——配置文件的修改
- Android Studio配置文件修改
- Android手机修改Hosts的方法
- Android手机修改Hosts的方法
- 如何修改Android手机的hosts
- 修改 android 手机 hosts 文件的方法
- 【android基础】android preferences
- Android手机修改分辨率
- 4.7.6 使用 new 来创建动态数组
- C++中const加强
- 【Android UI设计与开发】第06期:底部菜单栏(一)使用TabActivity实现底部菜单栏
- 各类排序方法以及效率对比,以万为计数单位
- Swift - Swift添加方法描述
- 修改Android手机的Preferences配置文件
- BZOJ1188 [HNOI2007]分裂游戏(SG定理)
- 审批流程优选方案
- java自定义解析XML文件解析
- MongoDB安装
- 常用的PHP正则表达式收集整理
- window.onload与$.ready的区别
- ZipInputStream & ZipOutputStream
- 工作第八年