精华内容
下载资源
问答
  • Androidfby[编译apk资源文件]
  • 反编译APK资源文件乱码

    千次阅读 2017-06-22 10:34:13
    反编译APK资源文件乱码把APK后缀改为zip后发现res文件夹下的xml文件打开乱码解决方案: 1.下载AXMLPrinter2.jar的jar包,下载地址: http://download.csdn.net/detail/simbaba/8625893 2.下载完jar包后打开命令行...

    反编译APK资源文件乱码

    把APK后缀改为zip后发现res文件夹下的xml文件打开乱码

    解决方案:
    1.下载AXMLPrinter2.jar的jar包,下载地址:
    http://download.csdn.net/detail/simbaba/8625893
    2.下载完jar包后打开命令行,cd到该jar包路径下,或者直接在该路径下打开命令行窗口,运行:java -jar AXMLPrinter2.S.jar 文件所在路径\指定文件名.xml
    即可反编译出xml文件
    最后
    如果想得到文件可使用
    Java -jar AXMLPrinter2.S.jar 文件所在路径\指定文件名.xml > 指定路径\文件名.txt(或XML) 则会将该xml文件的数据全部写入该文件

    展开全文
  • 解压看apk资源

    2019-01-07 18:05:17
    unity包资源, 一键轻松解压。针对的是unity打的apk资源
  • android实现对apk资源文件整体替换

    千次阅读 2019-05-14 21:20:27
    上一篇文章中我们实现了对资源文件的替换,但是有一个问题,就是得创建一个resource对象并使用这个resource对象才能实现对资源的替换,很麻烦,需要每个类去重写getResource方法。通过阅读framwork层源码发现...

    上一篇文章中我们实现了对资源文件的替换,但是有一个问题,就是得创建一个resource对象并使用这个resource对象才能实现对资源的替换,很麻烦,需要每个类去重写getResource方法。通过阅读framework层源码发现ContextImpl类的构造方法中实现了对resource的赋值操作。

    	 private ContextImpl(ContextImpl container, ActivityThread mainThread,
                            LoadedApk packageInfo, IBinder activityToken, UserHandle user, int flags,
                            Display display, Configuration overrideConfiguration, int createDisplayWithId) {
            mPackageInfo = packageInfo;
            Resources resources = packageInfo.getResources(mainThread);
        }
        
    

    跟踪packageInfo的getResources方法。在LoadedApk 类中

      public Resources getResources(ActivityThread mainThread) {
            if (mResources == null) {
              mResources = mainThread.getTopLevelResources(mResDir, mSplitResDirs, mOverlayDirs,
                       mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, this);
            }
           return mResources;
    

    我们发现了一个很神奇的变量mResDir,它是加载资源apk的路劲。那么我们就可以通过反射对mResDir重新赋值放上我们自己的资源路径实现整体替换。

    首先我们要先拿到LoadedApk 对象mPackageInfo,通过反射可获取到。先拿到mPackageInfo变量域。

           Class<?> contextImpl = Class.forName("android.app.ContextImpl");
            Field mPackageInfo = contextImpl.getDeclaredField("mPackageInfo");
            mPackageInfo.setAccessible(true);
    

    再拿到contextImpl对象。通过反射getImpl可以拿到。

    源码:
     static ContextImpl getImpl(Context context) {
            Context nextContext;
            while ((context instanceof ContextWrapper) &&
                   (nextContext=((ContextWrapper)context).getBaseContext()) != null) {
                context = nextContext;
            }
            return (ContextImpl)context;
        }
    

    反射getImpl这个方法:

            Method methodGetImpl = contextImpl.getDeclaredMethod("getImpl",Context.class);
            methodGetImpl.setAccessible(true);
            Object objImpl = methodGetImpl.invoke(null,this);
    

    在LoadedApk类中拿到mResDir域并重新赋值。

            Class<?> loadedApkClass;
            try {
                loadedApkClass = Class.forName("android.app.LoadedApk");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
                loadedApkClass = Class.forName("android.app.ActivityThread$PackageInfo");
            }
            Object loadedApkObj = mPackageInfo.get(objImpl);
            Field resDir = loadedApkClass.getDeclaredField("mResDir");
            resDir.setAccessible(true);
            resDir.set(loadedApkObj,path);
    

    完整代码:

            Class<?> contextImpl = Class.forName("android.app.ContextImpl");
            Class<?> loadedApkClass;
            try {
                loadedApkClass = Class.forName("android.app.LoadedApk");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
                loadedApkClass = Class.forName("android.app.ActivityThread$PackageInfo");
            }
            Field mPackageInfo = contextImpl.getDeclaredField("mPackageInfo");
            mPackageInfo.setAccessible(true);
            Method methodGetImpl = contextImpl.getDeclaredMethod("getImpl",Context.class);
            methodGetImpl.setAccessible(true);
            Object objImpl = methodGetImpl.invoke(null,this);
            if(objImpl!=null){
                Toast.makeText(this,"objImpl不为空:", Toast.LENGTH_SHORT).show();
            }
            Object loadedApkObj = mPackageInfo.get(objImpl);
            Field resDir = loadedApkClass.getDeclaredField("mResDir");
            resDir.setAccessible(true);
           //String path=""; 资源apk路劲
            resDir.set(loadedApkObj,path);
    

    总结:对LoadedApk 类中mResDir属性重新赋值,实现了我们资源路径的整体替换。不用重写getResource方法了。

    展开全文
  • 可以反编译apk文件中的资源文件,得到正常查看layout下的xml文件
  • 加载未安装资源apk里面的资源文件

    热门讨论 2014-01-03 22:55:32
    获取未安装资源apk里面的资源文件,对于sdk插件功能的布局有很大的帮助作用。
  • 反编译apk文件查看源码,反编译apk获取资源-附件资源
  • apk反翻译生成资源文件
  • 可视化反编译资源文件,选择APK文件,选择导出资源路径。只需几秒钟搞定。
  • 目前最好的TA 反编译得到的“送给最好的TA.apk”源码,包括了apk中的资源文件
  • 获取另一个apk中的资源文件

    千次阅读 2016-12-23 17:26:50
    在聊这个问题前,先来看看我们在程序中调用getResources()方法,为何获取的是自己apk中的资源文件。追踪程序中getResources()方法,首先我们找到ContxtThemeWrapper.java中的如下代码:@Override public Resources ...

    如何获取另一个apk的资源?在聊这个问题前,先来看看我们在程序中调用getResources()方法,为何获取的是自己apk中的资源文件。

    追踪程序中getResources()方法,首先我们找到ContxtThemeWrapper.java中的如下代码:

    @Override
    public Resources getResources() {
        if (mResources != null) {
            return mResources;
        }
        if (mOverrideConfiguration == null) {
            mResources = super.getResources();
            return mResources;
        } else {
            Context resc = createConfigurationContext(mOverrideConfiguration);
            mResources = resc.getResources();
            return mResources;
        }
    }

    我们看到mResources是从resc对象中对象得到的,我们跟进createConfigurationContext方法,最终会发现这个方法是在ContextImpl.java这个类中实现的,ContextImpl.java继承自Context.java,当然我们从类名上就可以看出,下面是ContextImpl.java中对于createConfigurationContext方法的具体实现:

    @Override
    public Context createConfigurationContext(Configuration overrideConfiguration) {
        if (overrideConfiguration == null) {
            throw new IllegalArgumentException("overrideConfiguration must not be null");
        }
    
        ContextImpl c = new ContextImpl();
        c.init(mPackageInfo, null, mMainThread);
        c.mResources = mResourcesManager.getTopLevelResources(mPackageInfo.getResDir(),
                getDisplayId(), overrideConfiguration, mResources.getCompatibilityInfo(),
                mActivityToken);
        return c;
    }

    我们关注第8行c.init方法,这个方法调用的是下面重载的init方法。

    final void init(LoadedApk packageInfo, IBinder activityToken, ActivityThread mainThread,
                Resources container, String basePackageName, UserHandle user) {
    
            ...
    
            if (mResources != null &&
                    ((compatInfo != null && compatInfo.applicationScale !=
                            mResources.getCompatibilityInfo().applicationScale)
                    || activityToken != null)) {
                if (DEBUG) {
                    Log.d(TAG, "loaded context has different scaling. Using container's" +
                            " compatiblity info:" + container.getDisplayMetrics());
                }
                if (compatInfo == null) {
                    compatInfo = packageInfo.getCompatibilityInfo();
                }
                mDisplayAdjustments.setCompatibilityInfo(compatInfo);
                mDisplayAdjustments.setActivityToken(activityToken);
                mResources = mResourcesManager.getTopLevelResources(mPackageInfo.getResDir(),
                        Display.DEFAULT_DISPLAY, null, compatInfo, activityToken);
            } else {
                mDisplayAdjustments.setCompatibilityInfo(packageInfo.getCompatibilityInfo());
                mDisplayAdjustments.setActivityToken(activityToken);
            }
    
            ...
        }

    我们看到其中的mResource成员变量就是资源类的一个声明引用,它是由mResourcesManager的getTopLevelResources方法得到,并且我们回看createConfigurationContext方法c.init()方法后面一步仍是调用了getTopLevelResources, 继续跟进getTopLevelResources方法,注意,传个这个方法的第一个参数的值是mPackageInfo.getResDir(),这个值就是我们自己apk的的路径。

    public Resources getTopLevelResources(String resDir, int displayId,
            Configuration overrideConfiguration, CompatibilityInfo compatInfo, IBinder token) {
    
        ...
    
        Resources r;
        synchronized (this) {
            // Resources is app scale dependent.
            if (false) {
                Slog.w(TAG, "getTopLevelResources: " + resDir + " / " + scale);
            }
            WeakReference<Resources> wr = mActiveResources.get(key);
            r = wr != null ? wr.get() : null;
            //if (r != null) Slog.i(TAG, "isUpToDate " + resDir + ": " + r.getAssets().isUpToDate());
            if (r != null && r.getAssets().isUpToDate()) {
                if (false) {
                    Slog.w(TAG, "Returning cached resources " + r + " " + resDir
                            + ": appScale=" + r.getCompatibilityInfo().applicationScale);
                }
                return r;
            }
        }
    
        //if (r != null) {
        //    Slog.w(TAG, "Throwing away out-of-date resources!!!! "
        //            + r + " " + resDir);
        //}
    
        AssetManager assets = new AssetManager();
        if (assets.addAssetPath(resDir) == 0) {
            return null;
        }
    
        ...
    
        r = new Resources(assets, dm, config, compatInfo, token);
    
        ...
    }
    

    这里使用了弱引用的技术,如果r在缓存中存在就从wr(WeakReference)中获取然后直接返回,不存在就调用new Resources(assets, dm, config, compatInfo, token);方法新建一个Resouces对象,在构造方法中传入了一个资源对象,我们主要关注一下获取资源的方法 很明显就是assets.addAssetPath(resDir) 这个了。

    到这里就可以知道为什么用getResources()获取的是自己app的资源文件,因为这里传的是packageInfo.getResDir(),这是我们自己apk的的路径。 所以要获取别的apk的资源 ,我们可以在我们的app里面调用这个方法传入想要获取的apk路径,就可以获取别的apk资源。

    但是想法虽好,现实是残酷的,我们发现addAssetPath方法是被加了@hide的,也就是我们不能直接在程序中使用。这时我们又想到了万能的反射技术,下面是具体代码:

    String dexpath= "";
    try {
        //所需的资源的apk的APK路径
        dexpath = getPackageManager().getApplicationInfo("com.chm.main", 0).sourceDir;
        Toast.makeText(this, dexpath, Toast.LENGTH_SHORT).show();
    } catch (PackageManager.NameNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    loadRes(dexpath);

    loadRes方法:

    private void loadRes(String path) {
        try {
            am = AssetManager.class.newInstance();
            Method addAssPath = AssetManager.class.getMethod("addAssetPath", String.class);
            addAssPath.invoke(am, path);
        } catch (Exception e) {
            e.printStackTrace();
        }
        rs = new Resources(am, super.getResources().getDisplayMetrics(), super.getResources().getConfiguration());
    }

    然后可以像下面这样给一个ImageView设置背景图标

    iv.setImageDrawable(rs.getDrawable(R.drawable.message_pay));

    这里有一个问题,如果你是想获取另一个apk中的message_pay图片,而这个方法中这张message_pay图片肯定是本apk中的,那么它们分别在R类中随机生成的对应整数很可能是不一致的。所以大多数情况下,这并不能获取我们真正想要的资源文件。甚至会抛出异常,如果找不到图片。

    看到这里大家是不是很郁闷,那么我们再来看看另一种获取其他apk资源的方式。

    也是用到了反射,我们直接看代码:

    private void setImage(String dexpath){
        DexClassLoader loader = new DexClassLoader(dexpath, getApplicationInfo().dataDir, null, this.getClass().getClassLoader());
        try {
            Class<?> clazz = loader.loadClass("com.chm.main.HellogpsActivity");
            Method getImageId = clazz.getMethod("getImageId");
            //调用静态方法
    //            int ic_launcher = (Integer) getImageId.invoke(clazz);
            int ic_launcher = (int) getImageId.invoke(clazz.newInstance());
            iv.setImageDrawable(getResourcs().getDrawable(ic_launcher));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    这里我们通过DexClassLoader类加载器获取到了另一个apk的Activity类,然后调用了该Activity中的 getImageId方法。这种方式可以返回我们真正想要的另一个apk中的资源,但是那也必须让那个apk给我们提供相关的方法返回资源对应的随机数,我们通过这个随机数才能拿到这个资源。

    最后,总的来说我们想完全准确的拿到与你毫无关系的apk中资源是做不到的,要不然岂不是天下大乱,但是如果我们做插件这样的东西到是可以用用。

    欢迎关注公众号。
    这里写图片描述

    展开全文
  • APK瘦身之删除多余资源文件

    千次阅读 2017-04-17 13:29:15
    1. 前言移动端项目迭代很频繁,一般半年左右,app包就变得很大,并且包含很多废弃的图片,layout文件,本篇文章主要讲如何快速定位出废弃资源,并快速删除。这次瘦身使用的工作是Android Studio Lint工具 , 用瘦身前...
    1. 前言

    移动端项目迭代很频繁,一般半年左右,app包就变得很大,并且包含很多废弃的图片,layout文件,本篇文章主要讲如何快速定位出废弃资源,并快速删除。

    这次瘦身使用的工作是Android Studio Lint工具 , 用瘦身前APK为21.5M, 瘦身后为18.4M. 瘦身结果为APK大小减少了3.1M(14%)

    2.准备工作

    1.Android Studio Lint只能定位出废弃的资源文件(res),源文件(src)无法定位,我是根据类名变灰(说明未被引用),则删除该资源 文件。

    3.工具介绍

    1)选中要检查的项目,点击【Analyze】->【Run Inspection By Name】,如图所示:
    这里写图片描述

    2)在【Enter inspection name】中输入【unused resources】,然后回车,如图所示:
    这里写图片描述

    3)可以选择检查的模块,我这边用的默认的Whole project,如图所示:
    这里写图片描述

    4)点击OK,稍等几分钟就会列出冗余资源,如图所示:
    这里写图片描述

    5)当然,你可以一张一张图片的去删除,如果不嫌麻烦的话,当然studio提供了批量删除方法,如图所示:
    这里写图片描述
    点击【Remove All Unused Resources】,则成功删掉所有冗余资源。

    4.注意点

    当然通过上面的步骤,已经成功的删掉了多余的资源,包括string里面没有用到的字符常量。当然有些文件我们是没有必要删除的,比如dimens,colors文件中的某些变量,因为这些文件我们做的是一个公有库,暂时没有用的,也没有必要删除,后期迭代中会使用到。


    如有错误欢迎指出来,一起学习。
    在这里插入图片描述

    展开全文
  • 第一步、先制做一个有我们需要的图片资源APK 如下图,这里有个about_log.png,我们需要生成apk文件。 生成的apk文件如果你不到项目的文件夹里面去取apk,想通过命令放到手机里面去可以快速用下面命令 1)、在...
  • Android apk文件资源混淆原理及实现

    千次阅读 2015-09-09 14:04:05
    Android apk文件资源混淆的实现,将apk中res目录下文件名混淆为随机名称。
  • APK资源文件哪去了

    千次阅读 2014-03-12 21:52:30
    问题: 在切换系统语言的时候,发现有些语言显示为默认...1. 资源文件中 res/values-fr res/valuse-it 等等资源文件都在 没有缺失 2. Android.mk, LOCAL_AAPT_FLAGS := -c zz_ZZ 3. 使用 aapt d resources XXX.apk
  • 可以非常方便的反编译apk中xml文件,里面包里我也写了批处理文件。直接把apk放到当前文件夹中,点击run.bat运行即可获得到out文件夹中的东西了 哈哈
  • 安卓APK反编译改资源文件

    千次阅读 2018-01-25 16:26:02
    更新:2018.03.07 感谢http://blog.csdn.net/wxk105/article/details/62231068... ... 情景:替换icon、应用名、包名。 关键代码:反编译、编译、签名apk apktool.bat d -f test.apk -o test apktool.bat b test j...
  • apk 测试文件

    2019-03-25 13:38:40
    apk 测试程序,供开发者实验用
  • 使用apktool反编译apk获取资源文件

    千次阅读 多人点赞 2016-07-02 01:03:45
    apktool的主要作用是资源文件获取,可以提取出图片文件和布局文件进行使用查看 使用: 1. 下载新版apktool 这里是传送门 2. 解压得到3个文件:aapt.exe,apktool.bat,apktool.jar 3. 将需要反编译的APK文件放到...
  • android 查看apk资源文件

    千次阅读 2014-06-09 10:49:12
    aapt dump xmltree *.apk AndroidManifest.xml aapt dump xmltree *.apk res/layout/*.xml
  • APK文件名称

    2014-05-13 23:05:26
    APK安装文件安装前的资源,保证手机的正常安装
  • 折腾一天,终于搞定了(收1分,折腾一天不容易哈),之前一直对包含资源文件apk加壳运行不通过,这个demo实现了对包含资源文件apk进行加壳,demo里面包含了所有的工程和最后完整加壳的apk,参考博客:...
  • LZ-Says:天道好轮回,苍天饶过谁~! 前言 本文,乃是反编译(逆向)首战,在此,...将Apk解包并修改资源文件(包含:更换Apk名称、替换Icon以及更换文字内容) 将修改好的Apk包进行回包,运行查看效果。 ...
  • 解压apk文件

    2013-12-16 08:16:37
    解压apk文件: 1.跳转到aapt.exe文件所在的目录 2.aapt.exe d badgin xxxxx.apk

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 111,346
精华内容 44,538
关键字:

如何看apk的资源文件