反射修改其它 APP SharedPreferences 数据

反射修改其它 APP SharedPreferences 数据

  • 前提条件
  • 可用代码

前提条件

设备已 root,不然无法访问 data/data 目录

问题现象:

HIE_Find(com.estrongs.android.pop) APP 可直接打开 usb 存储设备,但每次插拔后 usb 设备节点名称发生改变,再次打开 app 总会记住上一次打开路径

导致无法正常返回其它目录。通过分析,上次路径存储在了 SharedPreferences 中的 last_content_chooser_path

其实还有一种方法,但是只能用 adb 指令跳转

shell am start -n com.estrongs.android.pop/com.estrongs.android.pop.app.ESContentChooserActivity -d “file:///storage/emulated/0/DCIM/”

就可以打开指定路径选择文件,但在高版本上,由于文件权限机制问题,必须要用 FileProvider 来构造 uri,但这样 HIE_Find 不兼容,所以无法成功跳转

所以可行办法就是直接修改 last_content_chooser_path

注意: 修改完 SharedPreferences 后,对应 app 需要重新启动一次才会读取修改后的值

可用代码

public void setLastContentChooserPath() {

        //   /data/data/com.estrongs.android.pop/shared_prefs/com.estrongs.android.pop_preferences.xml
        //  /storage/emulated/0/DCIM/
		
        String cmd1 = "chmod 777 /data/data/com.estrongs.android.pop/";
        String cmd2 = "chmod 777 /data/data/com.estrongs.android.pop/shared_prefs/";
        String cmd3 = "chmod 777 /data/data/com.estrongs.android.pop/shared_prefs/com.estrongs.android.pop_preferences.xml";
        String[] cmds = {cmd1, cmd2, cmd3};
        ShellUtils.CommandResult result = ShellUtils.execCmd(cmds, true);
        Log.i(TAG, "result======"+result.successMsg);

        try {
            File preffile = new File("/data/data/com.estrongs.android.pop/shared_prefs/com.estrongs.android.pop_preferences.xml");
            Class prefimplclass = Class.forName("android.app.SharedPreferencesImpl");
            Constructor prefimplconstructor = prefimplclass.getDeclaredConstructor(File.class, int.class);
            prefimplconstructor.setAccessible(true);
            SharedPreferences prefimpl = (SharedPreferences) prefimplconstructor.newInstance(preffile, Context.MODE_WORLD_READABLE
                    | Context.MODE_WORLD_WRITEABLE);
            String chooserPath = prefimpl.getString("last_content_chooser_path", "");
            Log.i(TAG, "chooserPath======"+chooserPath);
            SharedPreferences.Editor editor = (SharedPreferences.Editor) prefimplclass.getMethod("edit").invoke(prefimpl);
            editor.putString("last_content_chooser_path", "/storage/emulated/0/DCIM/");
            editor.commit();
            Log.i(TAG, "set last_content_chooser_path======");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

ShellUtils.java


public final class ShellUtils {

    private static final String LINE_SEP = System.getProperty("line.separator");

    private ShellUtils() {
        throw new UnsupportedOperationException("u can't instantiate me...");
    }
    /**
     * Execute the command.
     *
     * @param command  The command.
     * @param isRooted True to use root, false otherwise.
     * @return the single {@link CommandResult} instance
     */
    public static CommandResult execCmd(final String command, final boolean isRooted) {
        return execCmd(new String[]{command}, isRooted, true);
    }
    /**
     * Execute the command.
     *
     * @param commands The commands.
     * @param isRooted True to use root, false otherwise.
     * @return the single {@link CommandResult} instance
     */
    public static CommandResult execCmd(final List<String> commands, final boolean isRooted) {
        return execCmd(commands == null ? null : commands.toArray(new String[]{}), isRooted, true);
    }

    /**
     * Execute the command.
     *
     * @param commands The commands.
     * @param isRooted True to use root, false otherwise.
     * @return the single {@link CommandResult} instance
     */
    public static CommandResult execCmd(final String[] commands, final boolean isRooted) {
        return execCmd(commands, isRooted, true);
    }

    /**
     * Execute the command.
     *
     * @param command         The command.
     * @param isRooted        True to use root, false otherwise.
     * @param isNeedResultMsg True to return the message of result, false otherwise.
     * @return the single {@link CommandResult} instance
     */
    public static CommandResult execCmd(final String command,
                                        final boolean isRooted,
                                        final boolean isNeedResultMsg) {
        return execCmd(new String[]{command}, isRooted, isNeedResultMsg);
    }

    /**
     * Execute the command.
     *
     * @param commands        The commands.
     * @param isRooted        True to use root, false otherwise.
     * @param isNeedResultMsg True to return the message of result, false otherwise.
     * @return the single {@link CommandResult} instance
     */
    public static CommandResult execCmd(final List<String> commands,
                                        final boolean isRooted,
                                        final boolean isNeedResultMsg) {
        return execCmd(commands == null ? null : commands.toArray(new String[]{}),
                isRooted,
                isNeedResultMsg);
    }

    /**
     * Execute the command.
     *
     * @param commands        The commands.
     * @param isRooted        True to use root, false otherwise.
     * @param isNeedResultMsg True to return the message of result, false otherwise.
     * @return the single {@link CommandResult} instance
     */
    public static CommandResult execCmd(final String[] commands,
                                        final boolean isRooted,
                                        final boolean isNeedResultMsg) {
        int result = -1;
        if (commands == null || commands.length == 0) {
            return new CommandResult(result, "", "");
        }
        Process process = null;
        BufferedReader successResult = null;
        BufferedReader errorResult = null;
        StringBuilder successMsg = null;
        StringBuilder errorMsg = null;
        DataOutputStream os = null;
        try {
            process = Runtime.getRuntime().exec(isRooted ? "su" : "sh");
            os = new DataOutputStream(process.getOutputStream());
            for (String command : commands) {
                if (command == null) {
                    continue;
                }
                os.write(command.getBytes());
                os.writeBytes(LINE_SEP);
                os.flush();
            }
            os.writeBytes("exit" + LINE_SEP);
            os.flush();
            result = process.waitFor();
            if (isNeedResultMsg) {
                successMsg = new StringBuilder();
                errorMsg = new StringBuilder();
                successResult = new BufferedReader(
                        new InputStreamReader(process.getInputStream(), "UTF-8")
                );
                errorResult = new BufferedReader(
                        new InputStreamReader(process.getErrorStream(), "UTF-8")
                );
                String line;
                if ((line = successResult.readLine()) != null) {
                    successMsg.append(line);
                    while ((line = successResult.readLine()) != null) {
                        successMsg.append(LINE_SEP).append(line);
                    }
                }
                if ((line = errorResult.readLine()) != null) {
                    errorMsg.append(line);
                    while ((line = errorResult.readLine()) != null) {
                        errorMsg.append(LINE_SEP).append(line);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (successResult != null) {
                    successResult.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (errorResult != null) {
                    errorResult.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (process != null) {
                process.destroy();
            }
        }
        return new CommandResult(
                result,
                successMsg == null ? "" : successMsg.toString(),
                errorMsg == null ? "" : errorMsg.toString()
        );
    }

    /**
     * The result of command.
     */
    public static class CommandResult {
        public int    result;
        public String successMsg;
        public String errorMsg;

        public CommandResult(final int result, final String successMsg, final String errorMsg) {
            this.result = result;
            this.successMsg = successMsg;
            this.errorMsg = errorMsg;
        }

        @Override
        public String toString() {
            return "result: " + result + "\n" +
                    "successMsg: " + successMsg + "\n" +
                    "errorMsg: " + errorMsg;
        }
    }

}

你可能感兴趣的:(车机魔改,车机,SharedPreferen)