V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
gramyang
V2EX  ›  Android

Android assets 的大坑!

  •  
  •   gramyang · May 16, 2019 · 15162 views
    This topic created in 2537 days ago, the information mentioned may be changed or developed.

    app 用 netty 进行网络请求,传输数据用 SSL 加密,nettysdk 初始化时需要读入 assets 里的 jks 文件。

    结果发现打开 assets 目录只能在 Activity 里!在 Application 里不行,我 tm。。。

    有什么别的解决方案吗?

    Supplement 1  ·  May 17, 2019
    留言说可以把 jks 文件持久化成字符串嵌入代码的方案行不通。用 base64 打出来的全是 A,用 String()打出来的是空白。
    Supplement 2  ·  May 17, 2019
    有人质疑我的代码问题,代码很多贴出来很麻烦,我口述一下吧。
    1,App 继承 Application 里获取单例:onCreate 里面 app = this。
    2,在工具类里面 App.getApp().getAssets()。就这个地方老是报空指针!无法获取 AssetManager。

    我之前设置过 multiDexEnabled true,因为方法数有 7 万多个,后来又把 multiDexEnabled true 给取消了,但是又没有报过方法数超 64k 了,很奇怪。

    是不是和这个有关呢?
    Supplement 3  ·  May 17, 2019
    又测试了一下,发现问题了:
    sslContext1 = SSLContext.getInstance("SSLv3");
    这行代码在 Android 里面报空。。。。。

    是我看错了,assets 可以在 application 里面读取。。。。

    抱歉耽误大家时间了,也感谢大家的热心解答!
    34 replies    2019-05-17 12:46:39 +08:00
    mouyase
        1
    mouyase  
       May 16, 2019 via Android
    初始化的时候创建一个没有 ui 的 activity
    pual
        2
    pual  
       May 16, 2019 via Android
    你直接内嵌到代码中啊
    xiangyuecn
        3
    xiangyuecn  
       May 16, 2019
    用 zip 读自身 apk 文件内容,不知道可不可行
    gramyang
        4
    gramyang  
    OP
       May 16, 2019
    @mouyase 研究了一下,activity 也是要执行完 onCreate 之后才能调用 getAssets()。看来也只能这样了。
    gramyang
        5
    gramyang  
    OP
       May 16, 2019
    @pual 还能把 byte[]内嵌到代码中??
    qianji201712
        6
    qianji201712  
       May 16, 2019
    简单粗暴点,吧 jks 文件都成的 byte,放到一个类里面,当作一个 byte[] ,哈哈哈,这样就可以了
    gramyang
        7
    gramyang  
    OP
       May 16, 2019
    @qianji201712 你的意思是,把 jks 文件读成 byte[],再用 utf8 编码成字符串,再放在类里面?
    stdnull
        8
    stdnull  
       May 16, 2019 via Android
    什么叫打开 assets 目录只能在 activity 里 ? 用 application 的 context 就能打开啊
    cxtrinityy
        9
    cxtrinityy  
       May 16, 2019
    context 直接 getAssets 就可以啊,我之前还做了后台从 assets 里解压数据库呢
    gramyang
        10
    gramyang  
    OP
       May 16, 2019
    @stdnull 不能,getAssets 的实现在 ContextThemeWrapper 里面,只能由 Activity 在 onCreate 之后可以打开。
    yippees
        11
    yippees  
       May 16, 2019
    cpAts2Sd
    yippees
        12
    yippees  
       May 16, 2019
    错了,快安全的应该还是内置代码··base64 吧
    nxforce
        13
    nxforce  
       May 16, 2019 via Android
    都转成 base64,硬编码到 java 代码里,也可以弄到 so 里,通过 jni 读取。
    qianji201712
        14
    qianji201712  
       May 16, 2019
    @gramyang 对的,他说白了就是一个二进制数据啊,放代码里面也一样的
    ztaober
        15
    ztaober  
       May 16, 2019
    为什么初始化一定要放在 application 里呢。。。
    MoHen9
        16
    MoHen9  
       May 16, 2019 via Android
    其实放在 res/raw/下面也可以,一般不是都有个 splash 页面吗?

    我都不知道 assets 目录不能在 application 中读取的问题,明天我去试试。
    pual
        17
    pual  
       May 16, 2019 via Android
    证书文件内嵌到代码很正常的操作
    james2013
        18
    james2013  
       May 17, 2019 via Android
    netty 代码包装成单例,延时初始化就可以实现,这样第一次网络请求才会初始化;
    也可以直接放到启动 activity 中
    gramyang
        19
    gramyang  
    OP
       May 17, 2019
    @MoHen9 这个可以有,我等会试试
    gramyang
        20
    gramyang  
    OP
       May 17, 2019
    @MoHen9 res/raw/和 asset 是一样的,都是通过 getResources 来读取的,所以都存在 application 里面不能读取的问题。
    kwanzaa
        21
    kwanzaa  
       May 17, 2019
    你们这么喜欢在 Application.onCreate 里面办事嘛。。。
    MoHen9
        22
    MoHen9  
       May 17, 2019 via Android
    @gramyang 可以读取,不管是 assets 还是 raw,使用 getAssets().open(“ xxx.jks ”)方法试试,还有,为什么用 Netty 呢?
    cysionliu
        23
    cysionliu  
       May 17, 2019
    ....怀疑了一下咋会不行呢,花点时间敲个例子,说明 context 直接 getAssets 就可以,难道还有版本问题??

    assets 里有个 hello.txt ,里面有行文字:hello asset

    代码:

    public class MyApp extends Application {

    @Override
    public void onCreate() {
    super.onCreate();
    test();
    }

    private void test() {
    Log.e("flag--", "run(MyApp.java)---->>" + Thread.currentThread().getName());
    try {
    InputStream open = getAssets().open("hello.txt");
    InputStreamReader reader = new InputStreamReader(open);
    BufferedReader bufferedReader = new BufferedReader(reader);
    Log.e("flag--", "run(MyApp.java)---->>" + bufferedReader.readLine());
    } catch (IOException aE) {
    aE.printStackTrace();
    }
    }
    }


    logcat:

    2019-05-17 09:19:54.497 30636-30636/com.haibin.calendarviewproject E/flag--: run(MyApp.java)---->>main
    2019-05-17 09:19:54.498 30636-30636/com.haibin.calendarviewproject E/flag--: run(MyApp.java)---->>hello asset
    olbb
        24
    olbb  
       May 17, 2019
    试了下可以读啊 不知道楼主为啥读不了
    kile
        25
    kile  
       May 17, 2019
    你为什么读不了??

    完全不符合多年经验...
    还跑去验证了下
    luwies
        26
    luwies  
       May 17, 2019
    完全是可以读的
    bkmi
        27
    bkmi  
       May 17, 2019 via Android
    别到处甩锅了,贴出你的代码来让大伙瞧瞧
    gramyang
        28
    gramyang  
    OP
       May 17, 2019
    @cysionliu 我也按照你的方法试了一下,在一个空白的 app 里面试了一下,确实可以读。但是我现在的 app 不能读。我这边有一个情况,我之前设定过 multiDexEnabled,最小版本是 21,然后又把 multiDexEnabled 取消了,但是又不提示方法是超过 64k 了。
    会不会是这个原因呢?
    laoyur
        29
    laoyur  
       May 17, 2019
    > 留言说可以把 jks 文件持久化成字符串嵌入代码的方案行不通。用 base64 打出来的全是 A,用 String()打出来的是空白。

    ???
    nicevar
        30
    nicevar  
       May 17, 2019
    楼主是个大坑,你们都听他瞎扯蛋。。。
    nicevar
        31
    nicevar  
       May 17, 2019
    我猜测一下可能性,楼主可能启动了一个 remote 的 service,跨进程了,由于知识不足找不到问题所在
    rb6221
        32
    rb6221  
       May 17, 2019
    用 raw 啊 别用 assets
    rigortek
        33
    rigortek  
       May 17, 2019
    show me you code
    别在这瞎聊,让大家猜来猜去
    hhhsuan
        34
    hhhsuan  
       May 17, 2019 via Android
    明明可以读,我一直都是这样做的。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   5650 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 103ms · UTC 08:22 · PVG 16:22 · LAX 01:22 · JFK 04:22
    ♥ Do have faith in what you're doing.