首页
社区
课程
招聘
1
[原创]Android Storage Access Framework(SAF)框架实现外置SD卡的写入(JAVA层与JNI层HOOK)
发表于: 2020-1-14 20:48 6970

[原创]Android Storage Access Framework(SAF)框架实现外置SD卡的写入(JAVA层与JNI层HOOK)

2020-1-14 20:48
6970

1. 前言

之前折腾了了一下MINE模拟器,发现SDL全是在JNI层fopen操作的,而安卓的SAF则是JAVA层通过DocumentFile和docUri来实现写入的。一种方法是通过去的File Descriptor然后传给JNI层,通过fdopen实现写入[1]。于是成功在MINE模拟器添加外置sd卡写入功能,详见我在贴吧布的 mine模拟器外置SD卡写入修复版。完整版源码我已经封装好了发布到github上,理论上通用。
MINE模拟器外置sd卡修复版

2. JAVA层SAF核心代码

通过DocumentFile来实现写入,Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)发送请求docUri,然后onActivityResult来得到并储存docUri,通过SharedPreference来实现共享。已经封装在静态类SafFile.java中。

获取外置sd卡根目录DocumentFile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static DocumentFile getBaseDocumentFile(final Context context, final SharedPreferences share) {
        if(context==null) {
            Log.e(LOGTAG, "SafFile.getBaseDocumentFile context is null!");
            return null;
        }
        if(share==null){
            Log.e(LOGTAG, "SafFile.getBaseDocumentFile share is null!");
            return null;
        }      
        DocumentFile base = null;
        Uri docUri = null;
        final String p = share.getString("docUri", null);
        if (p != null)
            docUri = Uri.parse(p);
        base = DocumentFile.fromTreeUri(context, docUri);
        return base;
    }

注意DocumentFile CreateFile好像不只能在本目录下创建,要一层一层往里面走

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
public static DocumentFile getTargetDirDocumentFile(final DocumentFile base, String path) {
        DocumentFile target = null;
        if (base == null) {
            Log.e(LOGTAG, "SafFile.getTargetDirDocumentFile base is null!");
            return null;
        }
        if(path==null) path="";
 
        path = path.replace("\\", "/");
        final String paths[] = path.split("/");
        int i;
        final int end = paths[paths.length - 1].length() > 0 ? paths.length - 1 : paths.length - 2;
        for (i = 0; i < end; i++) {
            // Log.i(LOGTAG, "getTar... path["+String.valueOf(i)+"], "+paths[i]);
            if (paths[i].equals(base.getName())) {
                if (i >= end - 1) {
                    // Log.i(LOGTAG, "getTar... "+path+" end="+paths[paths.length-1]+" "+ paths[end]);
                    return base;
                }
                i++;
                break;
            }
        }
        // Log.i(LOGTAG, "getTarget... "+base.getName()+" "+path);
        target = base.findFile(paths[i++]);
        // Log.i(LOGTAG, "target, "+ target.getName());
        for (; i < end; i++) {
            if (target == null)
                break;
            // Log.i(LOGTAG, "getTar..., "+path+" "+ target.getName());
            target = target.findFile(paths[i]);
        }
        return target;
    }

获得OutputStream

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
public static OutputStream getOutputStreamSaf(final Context context, final DocumentFile base, final String path,
            final boolean append) {
        if(context==null) {
            Log.e(LOGTAG, "SafFile.getOutputStreamSaf context is null!");
            return null;
        }
        if(base==null){
            Log.e(LOGTAG, "SafFile.getOutputStreamSaf base is null!");
            return null;
        }
 
        OutputStream out = null;
        final String mode = append ? "wa" : "w";
        // Log.i(LOGTAG, "getOut.. "+ path +" "+mode);
        final DocumentFile df2 = createFileSaf(base, path, append);
        if (df2 == null) {
            return null;
        }
        try {
            out = context.getContentResolver().openOutputStream(df2.getUri(), mode);
        } catch (final Exception e) {
            Log.e(LOGTAG, "SafFile.getOutputStreamSaf " + e.getClass().getName());
        }
        return out;
    }

获取文件描述符


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2020-1-14 22:12 被devseed编辑 ,原因:
收藏
免费 1
支持
分享
赞赏记录
参与人
雪币
留言
时间
PLEBFE
为你点赞~
2023-1-19 03:38
最新回复 (2)
雪    币: 6296
活跃值: (4972)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
2
没注意是桌面平台,发错区了,请管理员把此贴移到安卓区吧。
2020-1-14 20:51
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
2020-2-28 01:52
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册