• 反射修改其它 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();
            }
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    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;
            }
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
  • 相关阅读:
    (进阶)004 - AWS DeepRacer重要资料合集
    力扣题(5)—— 最长回文子串
    Java 的 String、StringBuffer 和 StringBuilder(一文讲透)
    Java的日期与时间之java.time.Instant简介说明
    【Linux】进程概念与进程状态
    ue5读取自定义文件夹中内容
    GoldenGate中使用 exp/imp 进行初始化
    《数据结构》复试问答题总结
    达梦数据库 视图 错误 [22003]: 数据溢出
    Unity IL2CPP 游戏分析入门
  • 原文地址:https://blog.csdn.net/u012932409/article/details/132872603