精华内容
下载资源
问答
  • android 资源管理器

    2011-01-18 18:50:05
    android 资源管理器 源码 android 资源管理器 源码 android 资源管理器 源码 android 资源管理器 源码 android 资源管理器 源码 android 资源管理器 源码 android 资源管理器 源码 android 资源管理器 源码 android ...
  • Android 文件资源管理器源码

    热门讨论 2010-08-07 15:50:56
    Android文件资源管理器2.0的源码,包括程序有两个模块:文件管理部分和任务管理部分。
  • 外汇资源管理器 安卓文件资源管理器
  • 基于android平台的资源管理器设计
  • 程序说明 -----------------------------... 小安任务助手是一款简单易用的任务管理软件,它可以使用户更方便的关闭正在运行的程序,显示手机CPU、内存、SD卡和电池状态等系统信息,还可用来卸载用户已安装的应用软件。
  • 安卓2.2 ES资源管理器

    2011-06-27 22:34:17
    资源管理器资源管理器资源管理器资源管理器资源管理器
  • 安卓文件资源管理器 我从 2011 年 10 月开始编写 Android 文件资源管理器。这个应用程序背后的设计目标是(现在是) 可用性 严格遵守 Android UI 设计指南 速度 然而,不可否认,自 2012 年 4 月以来我没有推送任何...
  • 安卓免费文件资源管理器 MiXplorer Silver 中文版安卓免费文件资源管理器 MiXplorer Silver 中文版 MiXPlorer 特色: 可通过自定义选项轻松进行更改,该选项可让您选择所需的任何颜色。 排序,禁用和启用所有菜单...
  • 这是一个关于Android 带图标的文件资源管理器的简单源码,供学习使用。
  • Android应用程序在运行的过程中,是通过一个称为AssetManager的资源管理器来读取打包在APK文件里面的资源文件的。在本文中,我们就将详细分析Android应用程序资源管理器的创建以及初始化过程,为接下来的一篇文章...

            在前面一篇文章中,我们分析了Android应用程序资源的编译和打包过程,最终得到的应用程序资源就与应用程序代码一起打包在一个APK文件中。Android应用程序在运行的过程中,是通过一个称为AssetManager的资源管理器来读取打包在APK文件里面的资源文件的。在本文中,我们就将详细分析Android应用程序资源管理器的创建以及初始化过程,为接下来的一篇文章分析应用程序资源的读取过程打下基础。

    《Android系统源代码情景分析》一书正在进击的程序员网(http://0xcc0xcd.com)中连载,点击进入!

            从前面Android应用程序窗口(Activity)的运行上下文环境(Context)的创建过程分析一文可以知道,应用程序的每一个Activity组件都关联有一个ContextImpl对象,这个ContextImpl对象就是用来描述Activity组件的运行上下文环境的。Activity组件是从Context类继承下来的,而ContextImpl同样是从Context类继承下来的。我们在Activity组件调用的大部分成员函数都是转发给与它所关联的一个ContextImpl对象的对应的成员函数来处理的,其中就包括用来访问应用程序资源的两个成员函数getResources和getAssets。

            ContextImpl类的成员函数getResources返回的是一个Resources对象,有了这个Resources对象之后,我们就可以通过资源ID来访问那些被编译过的应用程序资源了。ContextImpl类的成员函数getAssets返回的是一个AssetManager对象,有了这个AssetManager对象之后,我们就可以通过文件名来访问那些被编译过或者没有被编译过的应用程序资源文件了。事实上,Resources类也是通过AssetManager类来访问那些被编译过的应用程序资源文件的,不过在访问之前,它会先根据资源ID查找得到对应的资源文件名。

            我们知道,在Android系统中,一个进程是可以同时加载多个应用程序的,也就是可以同时加载多个APK文件。每一个APK文件在进程中都对应有一个全局的Resourses对象以及一个全局的AssetManager对象。其中,这个全局的Resourses对象保存在一个对应的ContextImpl对象的成员变量mResources中,而这个全局的AssetManager对象保存在这个全局的Resourses对象的成员变量mAssets中。上述ContextImpl、Resourses和AssetManager的关系如图1所示:


    图1 ContextImpl、Resources和AssetManager的关系图

            Resources类有一个成员函数getAssets,通过它就可以获得保存在Resources类的成员变量mAssets中的AssetManager,例如,ContextImpl类的成员函数getAssets就是通过调用其成员变量mResources所指向的一个Resources对象的成员函数getAssets来获得一个可以用来访问应用程序的非编译资源文件的AssetManager。

            我们知道,Android应用程序除了要访问自己的资源之外,还需要访问系统的资源。系统的资源打包在/system/framework/framework-res.apk文件中,它在应用程序进程中是通过一个单独的Resources对象和一个单独的AssetManager对象来管理的。这个单独的Resources对象就保存在Resources类的静态成员变量mSystem中,我们可以通过Resources类的静态成员函数getSystem就可以获得这个Resources对象,而这个单独的AssetManager对象就保存在AssetManager类的静态成员变量sSystem中,我们可以通过AssetManager类的静态成员函数getSystem同样可以获得这个AssetManager对象。

            AssetManager类除了在Java层有一个实现之外,在 C++层也有一个对应的实现,而Java层的AssetManager类的功能就是通过C++层的AssetManager类来实现的。Java层的每一个AssetManager对象都有一个类型为int的成员变量mObject,它保存的便是在C++层对应的AssetManager对象的地址,因此,通过这个成员变量就可以将Java层的AssetManager对象与C++层的AssetManager对象关联起来。

            C++层的AssetManager类有三个重要的成员变量mAssetPaths、mResources和mConfig。其中,mAssetPaths保存的是资源存放目录,mResources指向的是一个资源索引表,而mConfig保存的是设备的本地配置信息,例如屏幕密度和大小、国家地区和语言等等配置信息。有了这三个成员变量之后,C++层的AssetManager类就可以访问应用程序的资源了。

            从前面Android应用程序启动过程源代码分析一文可以知道,每一个Activity组件在进程的加载过程中,都会创建一个对应的ContextImpl,并且调用这个ContextImpl对象的成员函数init来执行初始化Activity组件运行上下文环境的工作,其中就包括创建用来访问应用程序资源的Resources对象和AssetManager对象的工作,接下来,我们就从ContextImpl类的成员函数init开始分析Resources对象和AssetManager对象的创建以及初始化过程,如图2所示:

    图2 应用程序资源管理器的创建和初始化过程

            这个过程可以分为14个步骤,接下来我们就详细分析每一个步骤。

            Step 1. ContextImpl.init

    class ContextImpl extends Context {
        ......
    
        /*package*/ LoadedApk mPackageInfo;
        private Resources mResources;
        ......
    
        final void init(LoadedApk packageInfo,
                IBinder activityToken, ActivityThread mainThread) {
            init(packageInfo, activityToken, mainThread, null);
        }
    
        final void init(LoadedApk packageInfo,
                    IBinder activityToken, ActivityThread mainThread,
                    Resources container) {
            mPackageInfo = packageInfo;
            mResources = mPackageInfo.getResources(mainThread);
    
            ......
        }
    
        ......
    }

            这个函数定义在文件frameworks/base/core/java/android/app/ContextImpl.java中。

            参数packageInfo指向的是一个LoadedApk对象,这个LoadedApk对象描述的是当前正在启动的Activity组所属的Apk。三个参数版本的成员函数init调用了四个参数版本的成员函数init来初始化当前正在启动的Activity组件的运行上下文环境。其中,用来访问应用程序资源的Resources对象是通过调用参数packageInfo所指向的是一个LoadedApk对象的成员函数getResources来创建的。这个Resources对象创建完成之后,就会保存在ContextImpl类的成员变量mResources中。

            接下来,我们就继续分析LoadedApk类的成员函数getResources的实现。

            Step 2. LoadedApk.getResources

    final class LoadedApk {
        ......
    
        private final String mResDir;
        ......
    
        Resources mResources;
        ......
    
        public Resources getResources(ActivityThread mainThread) {
            if (mResources == null) {
                mResources = mainThread.getTopLevelResources(mResDir, this);
            }
            return mResources;
        }
     
        ......
    }
            这个函数定义在文件frameworks/base/core/java/android/app/LoadedApk.java中。

            参数mainThread指向了一个ActivityThread对象,这个ActivityThread对象描述的是当前正在运行的应用程序进程。

            LoadedApk类的成员函数getResources首先检查其成员变量mResources的值是否等于null。如果不等于的话,那么就会将它所指向的是一个Resources对象返回给调用者,否则的话,就会调用参数mainThread所指向的一个ActivityThread对象的成员函数getTopLevelResources来获得这个Resources对象,然后再返回给调用者。

            在调用ActivityThread类的成员函数getTopLevelResources来获得一个Resources对象的时候,需要指定要获取的Resources对象所对应的Apk文件路径,这个Apk文件路径就保存在LoadedApk类的成员变量mResDir中。例如,假设我们要获取的Resources对象是用来访问系统自带的音乐播放器的资源的,那么对应的Apk文件路径就为/system/app/Music.apk。

            接下来,我们就继续分析ActivityThread类的成员函数getTopLevelResources的实现。

            Step 3. ActivityThread.getTopLevelResources

    public final class ActivityThread {
        ......
    
        final HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
                = new HashMap<ResourcesKey, WeakReference<Resources> >();
        ......
    
        Resources getTopLevelResources(String resDir, CompatibilityInfo compInfo) {
            ResourcesKey key = new ResourcesKey(resDir, compInfo.applicationScale);
            Resources r;
            synchronized (mPackages) {
                ......
    
                WeakReference<Resources> wr = mActiveResources.get(key);
                r = wr != null ? wr.get() : null;
                ......
    
                if (r != null && r.getAssets().isUpToDate()) {
                    ......
                    return r;
                }
            }
    
            ......
    
            AssetManager assets = new AssetManager();
            if (assets.addAssetPath(resDir) == 0) {
                return null;
            }
            ......
    
            r = new Resources(assets, metrics, getConfiguration(), compInfo);
            ......
    
            synchronized (mPackages) {
                WeakReference<Resources> wr = mActiveResources.get(key);
                Resources existing = wr != null ? wr.get() : null;
                if (existing != null && existing.getAssets().isUpToDate()) {
                    // Someone else already created the resources while we were
                    // unlocked; go ahead and use theirs.
                    r.getAssets().close();
                    return existing;
                }
    
                // XXX need to remove entries when weak references go away
                mActiveResources.put(key, new WeakReference<Resources>(r));
                return r;
            }
        }
    
        ......
    }
            这个函数定义在文件frameworks/base/core/java/android/app/ActivityThread.java中。

            ActivityThread类的成员变量mActiveResources指向的是一个HashMap。这个HashMap用来维护在当前应用程序进程中加载的每一个Apk文件及其对应的Resources对象的对应关系。也就是说,给定一个Apk文件路径,ActivityThread类的成员函数getTopLevelResources可以在成员变量mActiveResources中检查是否存在一个对应的Resources对象。如果不存在,那么就会新建一个,并且保存在ActivityThread类的成员变量mActiveResources中。

            参数resDir即为要获取其对应的Resources对象的Apk文件路径,ActivityThread类的成员函数getTopLevelResources首先根据它来创建一个ResourcesKey对象,然后再以这个ResourcesKey对象在ActivityThread类的成员变量mActiveResources中检查是否存在一个Resources对象。如果存在,并且这个Resources对象里面包含的资源文件没有过时,即调用这个Resources对象的成员函数getAssets所获得一个AssetManager对象的成员函数isUpToDate的返回值等于true,那么ActivityThread类的成员函数getTopLevelResources就可以将该Resources对象返回给调用者了。

            如果不存在与参数resDir对应的Resources对象,或者存在这个Resources对象,但是存在的这个Resources对象是过时的,那么ActivityThread类的成员函数getTopLevelResources就会新创建一个AssetManager对象,并且调用这个新创建的AssetManager对象的成员函数addAssetPath来将参数resDir所描述的Apk文件路径作为它的资源目录。

            创建了一个新的AssetManager对象,ActivityThread类的成员函数getTopLevelResources还需要这个AssetManager对象来创建一个新的Resources对象。这个新创建的Resources对象需要以前面所创建的ResourcesKey对象为键值缓存在ActivityThread类的成员变量mActiveResources所描述的一个HashMap中,以便以后可以获取回来使用。不过,这个新创建的Resources对象在缓存到ActivityThread类的成员变量mActiveResources所描述的一个HashMap去之前,需要再次检查该HashMap是否已经存在一个对应的Resources对象了,这是因为当前线程在创建新的AssetManager对象和Resources对象的过程中,可能有其它线程抢先一步创建了与参数resDir对应的Resources对象,并且将该Resources对象保存到该HashMap中去了。

            如果没有其它线程抢先创建一个与参数resDir对应的Resources对象,或者其它线程抢先创建出来的Resources对象是过时的,那么ActivityThread类的成员函数getTopLevelResources就会将前面创建的Resources对象缓存到成员变量mActiveResources所描述的一个HashMap中去,并且将前面创建的Resources对象返回给调用者,否则扩知,就会将其它线程抢先创建的Resources对象返回给调用者。

            接下来,我们首先分析AssetManager类的构造函数和成员函数addAssetPath的实现,接着再分析Resources类的构造函数的实现,以便可以了解用来访问应用程序资源的AssetManager对象和Resources对象的创建以及初始化过程。

            Step 4. new AssetManager

    public final class AssetManager {
        ......
    
        private static AssetManager sSystem = null;
        ......
    
        public AssetManager() {
            synchronized (this) {
                ......
                init();
                ......
                ensureSystemAssets();
            }
        }
    
        private static void ensureSystemAssets() {
            synchronized (sSync) {
                if (sSystem == null) {
                    AssetManager system = new AssetManager(true);
                    system.makeStringBlocks(false);
                    sSystem = system;
                }
            }
        }
    
        ......
    }
            这个函数定义在文件frameworks/base/core/java/android/content/res/AssetManager.java中。

            AssetManager类的构造函数是通过调用另外一个成员函数init来执行初始化工作的。在初始化完成当前正在创建的AssetManager对象之后,AssetManager类的构造函数还会调用另外一个成员函数ensureSystemAssets来检查当前进程是否已经创建了一个用来访问系统资源的AssetManager对象。

            如果用来访问系统资源的AssetManager对象还没有创建的话,那么AssetManager类的成员函数ensureSystemAssets就会创建并且初始化它,并且将它保存在AssetManager类的静态成员变量sSystem中。注意,创建用来访问系统资源和应用程序资源的AssetManager对象的过程是一样的,区别只在于它们所要访问的Apk文件不一样,因此,接下来我们就只分析用来访问应用资源的AssetManager对象的创建过程以及初始化过程。

           Step 5. AssetManager.init

    public final class AssetManager {
        ......
     
        private int mObject;
        ......
    
        private native final void init();
    
        ......
    }

           这个函数定义在文件frameworks/base/core/java/android/content/res/AssetManager.java中。

           AssetManager类的成员函数init是一个JNI函数,它是由C++层的函数android_content_AssetManager_init来实现的:

    static void android_content_AssetManager_init(JNIEnv* env, jobject clazz)
    {
        AssetManager* am = new AssetManager();
        .....
    
        am->addDefaultAssets();
    
        ......
        env->SetIntField(clazz, gAssetManagerOffsets.mObject, (jint)am);
    }
             这个函数定义在文件frameworks/base/core/jni/android_util_AssetManager.cpp中。

             函数android_content_AssetManager_init首先创建一个C++层的AssetManager对象,接着调用这个C++层的AssetManager对象的成员函数addDefaultAssets来添加默认的资源路径,最后将这个这个C++层的AssetManager对象的地址保存在参数clazz所描述的一个Java层的AssetManager对象的成员变量mObject中。

            Step 6. AssetManager.addDefaultAssets

    static const char* kSystemAssets = "framework/framework-res.apk";
    ......
    
    bool AssetManager::addDefaultAssets()
    {
        const char* root = getenv("ANDROID_ROOT");
        ......
    
        String8 path(root);
        path.appendPath(kSystemAssets);
    
        return addAssetPath(path, NULL);
    }
           这个函数定义在文件frameworks/base/libs/utils/AssetManager.cpp中。

           AssetManager类的成员函数addDefaultAssets首先通过环境变量ANDROID_ROOT来获得Android的系统路径,接着再将全局变量kSystemAssets所指向的字符串“framework/framework-res.apk”附加到这个系统路径的后面去,这样就可以得到系统资源文件framework-res.apk的绝对路径了。一般来说,环境变量ANDROID_ROOT所设置的Android系统路径就是“/system”,因此,最终得到的系统资源文件的绝对路径就为“/system/framework/framework-res.apk”。

           得到了系统资源文件framework-res.apk的绝对路径之后,就调用AssetManager类的成员函数addAssetPath来将它添加到当前正在初始化的AssetManager对象中去。

           Step 7. AssetManager.addAssetPath

    static const char* kAppZipName = NULL; //"classes.jar";
    ......
    
    bool AssetManager::addAssetPath(const String8& path, void** cookie)
    {
        AutoMutex _l(mLock);
    
        asset_path ap;
    
        String8 realPath(path);
        if (kAppZipName) {
            realPath.appendPath(kAppZipName);
        }
        ap.type = ::getFileType(realPath.string());
        if (ap.type == kFileTypeRegular) {
            ap.path = realPath;
        } else {
            ap.path = path;
            ap.type = ::getFileType(path.string());
            if (ap.type != kFileTypeDirectory && ap.type != kFileTypeRegular) {
                ......
                return false;
            }
        }
    
        // Skip if we have it already.
        for (size_t i=0; i<mAssetPaths.size(); i++) {
            if (mAssetPaths[i].path == ap.path) {
                if (cookie) {
                    *cookie = (void*)(i+1);
                }
                return true;
            }
        }
    
        ......
    
        mAssetPaths.add(ap);
    
        // new paths are always added at the end
        if (cookie) {
            *cookie = (void*)mAssetPaths.size();
        }
    
        // add overlay packages for /system/framework; apps are handled by the
        // (Java) package manager
        if (strncmp(path.string(), "/system/framework/", 18) == 0) {
            // When there is an environment variable for /vendor, this
            // should be changed to something similar to how ANDROID_ROOT
            // and ANDROID_DATA are used in this file.
            String8 overlayPath("/vendor/overlay/framework/");
            overlayPath.append(path.getPathLeaf());
            if (TEMP_FAILURE_RETRY(access(overlayPath.string(), R_OK)) == 0) {
                asset_path oap;
                oap.path = overlayPath;
                oap.type = ::getFileType(overlayPath.string());
                bool addOverlay = (oap.type == kFileTypeRegular); // only .apks supported as overlay
                if (addOverlay) {
                    oap.idmap = idmapPathForPackagePath(overlayPath);
    
                    if (isIdmapStaleLocked(ap.path, oap.path, oap.idmap)) {
                        addOverlay = createIdmapFileLocked(ap.path, oap.path, oap.idmap);
                    }
                }
                if (addOverlay) {
                    mAssetPaths.add(oap);
                } 
                ......
            }
        }
    
        return true;
    }
            这个函数定义在文件frameworks/base/libs/utils/AssetManager.cpp中。

            如果全局变量kAppZipName的值不等于NULL的话,那么它的值一般就是被设置为“classes.jar”,这时候就表示应用程序的资源文件是保存在参数path所描述的一个目录下的一个classes.jar文件中。全局变量kAppZipName的值一般被设置为NULL,并且参数path指向的是一个Apk文件,因此,接下来我们只考虑应用程序资源不是保存在一个classes.jar文件的情况。

            AssetManager类的成员函数addAssetPath首先是要检查参数path指向的是一个文件或者目录,并且该文件或者目录存在,否则的话,它就会直接返回一个false值,而不会再继续往下处理了。

            AssetManager类的成员函数addAssetPath接着再检查在其成员变量mAssetPaths所描述的一个类型为asset_path的Vector中是否已经添加过参数path所描述的一个Apk文件路径了。如果已经添加过了,那么AssetManager类的成员函数addAssetPath就不会再继续往下处理了,而是将与参数path所描述的一个Apk文件路径所对应的一个Cookie返回给调用者,即保存在输出参数cookie中,前提是参数cookie的值不等于NULL。一个Apk文件路径所对应的Cookie实际上只是一个整数,这个整数表示该Apk文件路径所对应的一个asset_path对象在成员变量mAssetPaths所描述的一个Vector中的索引再加上1。

            经过上面的检查之后,AssetManager类的成员函数addAssetPath确保参数path所描述的一个Apk文件路径之前没有被添加过,于是接下来就会将与该Apk文件路径所对应的一个asset_path对象保存在成员变量mAssetPaths所描述的一个Vector的最末尾位置上,并且将这时候得到的Vector的大小作为一个Cookie值保存在输出参数cookie中返回给调用者。

            AssetManager类的成员函数addAssetPath的最后一个工作是检查刚刚添加的Apk文件路径是否是保存在/system/framework/目录下面的。如果是的话,那么就会在/vendor/overlay/framework/目录下找到一个同名的Apk文件,并且也会将该Apk文件添加到成员变量mAssetPaths所描述的一个Vector中去。这是一种资源覆盖机制,手机厂商可以利用它来自定义的系统资源,即用自定义的系统资源来覆盖系统默认的系统资源,以达到个性化系统界面的目的。

            如果手机厂商要利用上述的资源覆盖机制来自定义自己的系统资源,那么还需要提供一个idmap文件,用来说明它在/vendor/overlay/framework/目录提供的Apk文件要覆盖系统的哪些默认资源,使用资源ID来描述,因此,这个idmap文件实际上就是一个资源ID映射文件。这个idmap文件最终保存在/data/resource-cache/目录下,并且按照一定的格式来命令,例如,假设手机厂商提供的覆盖资源文件为/vendor/overlay/framework/framework-res.apk,那么对应的idmap文件就会以名称为@vendor@overlay@framework@framework-res.apk@idmap的形式保存在目录/data/resource-cache/下。

            关于Android系统的资源覆盖(Overlay)机制,可以参考frameworks/base/libs/utils目录下的READ文件。

            这一步执行完成之后,回到前面的Step 3中,即ActivityThread类的成员函数getTopLevelResources中,接下来它就会调用前面所创建的Java层的AssetManager对象的成员函数addAssetPath来添加指定的应用程序资源文件路径。

            Step 8. AssetManager.addAssetPath

    public final class AssetManager {
        ......
    
        /**
         * Add an additional set of assets to the asset manager.  This can be
         * either a directory or ZIP file.  Not for use by applications.  Returns
         * the cookie of the added asset, or 0 on failure.
         * {@hide}
         */
        public native final int addAssetPath(String path);
    
        ......
    }

            这个函数定义在文件frameworks/base/core/java/android/content/res/AssetManager.java中。

            AssetManager类的成员函数addAssetPath是一个JNI方法,它是由C++层的函数android_content_AssetManager_addAssetPath来实现的,如下所示:

    static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz,
                                                           jstring path)
    {
        ......
    
        AssetManager* am = assetManagerForJavaObject(env, clazz);
        ......
    
        const char* path8 = env->GetStringUTFChars(path, NULL);
    
        void* cookie;
        bool res = am->addAssetPath(String8(path8), &cookie);
    
        env->ReleaseStringUTFChars(path, path8);
    
        return (res) ? (jint)cookie : 0;
    }
            这个函数定义在文件frameworks/base/core/jni/android_util_AssetManager.cpp中。

            参数clazz指向的是Java层的一个AssetManager对象,函数android_content_AssetManager_addAssetPath首先调用另外一个函数assetManagerForJavaObject来将它的成员函数mObject转换为一个C++层的AssetManager对象。有了这个C++层的AssetManager对象之后,就可以调用它的成员函数addAssetPath来将参数path所描述的一个Apk文件路径添加到它里面去了,这个过程可以参考前面的Step 7。

            这一步执行完成之后,回到前面的Step 3中,即ActivityThread类的成员函数getTopLevelResources中,接下来就会根据前面所创建的Java层的AssetManager对象来创建一个Resources对象。

            Step 9. new Resources

    public class Resources {
        ......
    
        /*package*/ final AssetManager mAssets;
        ......
    
        public Resources(AssetManager assets, DisplayMetrics metrics,
                Configuration config, CompatibilityInfo compInfo) {
            mAssets = assets;
            ......
    
            updateConfiguration(config, metrics);
            assets.ensureStringBlocks();
        }
     
        ......
    }
            这个函数定义在文件frameworks/base/core/java/android/content/res/Resources.java中。

            Resources类的构造函数首先将参数assets所指向的一个AssetManager对象保存在成员变量mAssets中,以便以后可以通过它来访问应用程序的资源,接下来调用另外一个成员函数updateConfiguration来设置设备配置信息,最后调用参数assets所指向的一个AssetManager对象的成员函数ensureStringBlocks来创建字符串资源池。

            接下来,我们就首先分析Resources类的成员函数updateConfiguration的实现,接着再分析AssetManager类的成员函数ensureStringBlocks的实现。

            Step 10. Resources.updateConfiguration

    public class Resources {
        ......
    
        private final Configuration mConfiguration = new Configuration();
        ......
    
        public void updateConfiguration(Configuration config,
                DisplayMetrics metrics) {
            synchronized (mTmpValue) {
                int configChanges = 0xfffffff;
                if (config != null) {
                    configChanges = mConfiguration.updateFrom(config);
                }
                if (mConfiguration.locale == null) {
                    mConfiguration.locale = Locale.getDefault();
                }
                if (metrics != null) {
                    mMetrics.setTo(metrics);
                    mMetrics.updateMetrics(mCompatibilityInfo,
                            mConfiguration.orientation, mConfiguration.screenLayout);
                }
                mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
    
                String locale = null;
                if (mConfiguration.locale != null) {
                    locale = mConfiguration.locale.getLanguage();
                    if (mConfiguration.locale.getCountry() != null) {
                        locale += "-" + mConfiguration.locale.getCountry();
                    }
                }
                int width, height;
                if (mMetrics.widthPixels >= mMetrics.heightPixels) {
                    width = mMetrics.widthPixels;
                    height = mMetrics.heightPixels;
                } else {
                    //noinspection SuspiciousNameCombination
                    width = mMetrics.heightPixels;
                    //noinspection SuspiciousNameCombination
                    height = mMetrics.widthPixels;
                }
                int keyboardHidden = mConfiguration.keyboardHidden;
                if (keyboardHidden == Configuration.KEYBOARDHIDDEN_NO
                        && mConfiguration.hardKeyboardHidden
                                == Configuration.HARDKEYBOARDHIDDEN_YES) {
                    keyboardHidden = Configuration.KEYBOARDHIDDEN_SOFT;
                }
                mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc,
                        locale, mConfiguration.orientation,
                        mConfiguration.touchscreen,
                        (int)(mMetrics.density*160), mConfiguration.keyboard,
                        keyboardHidden, mConfiguration.navigation, width, height,
                        mConfiguration.screenLayout, mConfiguration.uiMode, sSdkVersion);
    
                ......
            }
           
            ...... 
        }
    
        ......
    }
            这个函数定义在文件frameworks/base/core/java/android/content/res/Resources.java中。

            Resources类的成员变量mConfiguration指向的是一个Configuration对象,用来描述设备当前的配置信息,这些配置信息对应的就是在前面Android资源管理框架(Asset Manager)简要介绍和学习计划一文中提到18个资源维度。

            Resources类的成员函数updateConfiguration首先是根据参数config和metrics来更新设备的当前配置信息,例如,屏幕大小和密码、国家地区和语言、键盘配置情况等等,接着再调用成员变量mAssets所指向的一个Java层的AssetManager对象的成员函数setConfiguration来将这些配置信息设置到与之关联的C++层的AssetManager对象中去。

            接下来,我们就继续分析AssetManager类的成员函数setConfiguration的实现,以便可以了解设备配置信息的设置过程。

            Step 11. AssetManager.setConfiguration

    public final class AssetManager {
        ......
    
        /**
         * Change the configuation used when retrieving resources.  Not for use by
         * applications.
         * {@hide}
         */
        public native final void setConfiguration(int mcc, int mnc, String locale,
                int orientation, int touchscreen, int density, int keyboard,
                int keyboardHidden, int navigation, int screenWidth, int screenHeight,
                int screenLayout, int uiMode, int majorVersion);
    
        ......
    }
            这个函数定义在文件frameworks/base/core/java/android/content/res/AssetManager.java中。

            AssetManager类的成员函数setConfiguration是一个JNI方法,它是由C++层的函数android_content_AssetManager_setConfiguration来实现的,如下所示:

    static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject clazz,
                                                              jint mcc, jint mnc,
                                                              jstring locale, jint orientation,
                                                              jint touchscreen, jint density,
                                                              jint keyboard, jint keyboardHidden,
                                                              jint navigation,
                                                              jint screenWidth, jint screenHeight,
                                                              jint screenLayout, jint uiMode,
                                                              jint sdkVersion)
    {
        AssetManager* am = assetManagerForJavaObject(env, clazz);
        if (am == NULL) {
            return;
        }
    
        ResTable_config config;
        memset(&config, 0, sizeof(config));
    
        const char* locale8 = locale != NULL ? env->GetStringUTFChars(locale, NULL) : NULL;
    
        config.mcc = (uint16_t)mcc;
        config.mnc = (uint16_t)mnc;
        config.orientation = (uint8_t)orientation;
        config.touchscreen = (uint8_t)touchscreen;
        config.density = (uint16_t)density;
        config.keyboard = (uint8_t)keyboard;
        config.inputFlags = (uint8_t)keyboardHidden;
        config.navigation = (uint8_t)navigation;
        config.screenWidth = (uint16_t)screenWidth;
        config.screenHeight = (uint16_t)screenHeight;
        config.screenLayout = (uint8_t)screenLayout;
        config.uiMode = (uint8_t)uiMode;
        config.sdkVersion = (uint16_t)sdkVersion;
        config.minorVersion = 0;
        am->setConfiguration(config, locale8);
    
        if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
    }
            这个函数定义在文件frameworks/base/core/jni/android_util_AssetManager.cpp中。

            参数clazz指向的是一个Java层的AssetManager对象,函数android_content_AssetManager_setConfiguration首先调用另外一个函数assetManagerForJavaObject将它的成员变量mObject转换为一个C++层的AssetManager对象。

            函数android_content_AssetManager_setConfiguration接下来再根据其它参数来创建一个ResTable_config对象,这个ResTable_config对象就用来描述设备的当前配置信息。

            函数android_content_AssetManager_setConfiguration最后调用前面获得C++层的AssetManager对象的成员函数setConfiguration来将前面创建的ResTable_config对象设置到它内部去,以便C++层的AssetManager对象可以根据设备的当前配置信息来找到最合适的资源。

            Step 12. AssetManager.setConfiguration

    void AssetManager::setConfiguration(const ResTable_config& config, const char* locale)
    {
        AutoMutex _l(mLock);
        *mConfig = config;
        if (locale) {
            setLocaleLocked(locale);
        } else if (config.language[0] != 0) {
            char spec[9];
            spec[0] = config.language[0];
            spec[1] = config.language[1];
            if (config.country[0] != 0) {
                spec[2] = '_';
                spec[3] = config.country[0];
                spec[4] = config.country[1];
                spec[5] = 0;
            } else {
                spec[3] = 0;
            }
            setLocaleLocked(spec);
        } else {
            updateResourceParamsLocked();
        }
    }
            这个函数定义在文件frameworks/base/libs/utils/AssetManager.cpp中。

            AssetManager类的成员变量mConfig指向的是一个ResTable_config对象,用来描述设备的当前配置信息,AssetManager类的成员函数setConfiguration首先将参数config所描述的设备配置信息拷贝到它里面去。

            如果参数local的值不等于NULL,那么它指向的字符串就是用来描述设备的国家、地区和语言信息的,这时候AssetManager类的成员函数setConfiguration就会调用另外一个成员函数setLocalLocked来将它们设置到AssetManager类的另外一个成员变量mLocale中去。

            如果参数local的值等于NULL,并且参数config指向的一个ResTable_config对象包含了设备的国家、地区和语言信息,那么AssetManager类的成员函数setConfiguration同样会调用另外一个成员函数setLocalLocked来将它们设置到AssetManager类的另外一个成员变量mLocale中去。

            如果参数local的值等于NULL,并且参数config指向的一个ResTable_config对象没有包含设备的国家、地区和语言信息,那么就说明设备的国家、地区和语言等信息不需要更新,这时候AssetManager类的成员函数setConfiguration就会直接调用另外一个成员函数updateResourceParamsLocked来更新资源表中的设备配置信息。

            注意,AssetManager类的成员函数setLocalLocked来更新了成员变量mLocale的内容之后,同样会调用另外一个成员函数updateResourceParamsLocked来更新资源表中的设备配置信息。

            AssetManager类的成员函数updateResourceParamsLocked的实现如下所示:

    void AssetManager::updateResourceParamsLocked() const
    {
        ResTable* res = mResources;
        if (!res) {
            return;
        }
    
        size_t llen = mLocale ? strlen(mLocale) : 0;
        mConfig->language[0] = 0;
        mConfig->language[1] = 0;
        mConfig->country[0] = 0;
        mConfig->country[1] = 0;
        if (llen >= 2) {
            mConfig->language[0] = mLocale[0];
            mConfig->language[1] = mLocale[1];
        }
        if (llen >= 5) {
            mConfig->country[0] = mLocale[3];
            mConfig->country[1] = mLocale[4];
        }
        mConfig->size = sizeof(*mConfig);
    
        res->setParameters(mConfig);
    }
            这个函数定义在文件frameworks/base/libs/utils/AssetManager.cpp中。

            AssetManager类的成员变量mResources指向的是一个ResTable对象,这个ResTable对象描述的就是一个资源索引表。Android应用程序的资源索引表的格式以及生成过程可以参考前面Android应用程序资源的编译和打包过程分析一文。

            AssetManager类的成员函数updateResourceParamsLocked首先是将成员变量mLocale所描述的国家、地区和语言信息更新到另外一个成员变量mConfig中去,接着再将成员变量mConfig所包含的设备配置信息设置到成员变量mResources所描述的一个资源索引表中去,这是通过调用成员变量mResources所指向的一个ResTable对象的成员函数setParameters来实现的。

            这一步执行完成之后,返回到前面的Step 9中,即Resources类的构造函数,接下来它就会调用AssetManager类的成员函数ensureStringBlocks来创建字符串资源池。

            Step 13. AssetManager.ensureStringBlocks

    public final class AssetManager {
        ......
    
        private StringBlock mStringBlocks[] = null;
        ......
    
        /*package*/ final void ensureStringBlocks() {
            if (mStringBlocks == null) {
                synchronized (this) {
                    if (mStringBlocks == null) {
                        makeStringBlocks(true);
                    }
                }
            }
        }
    
        ......
    }
            这个函数定义在文件frameworks/base/core/java/android/content/res/AssetManager.java中。

            AssetManager类的成员变量mStringBlocks指向的是一个StringBlock数组,其中,每一个StringBlock对象都是用来描述一个字符串资源池。从前面Android应用程序资源的编译和打包过程分析一文可以知道,每一个资源表都包含有一个资源项值字符串资源池,AssetManager类的成员变量mStringBlocks就是用来保存所有的资源表中的资源项值字符串资源池的。

            AssetManager类的成员函数ensureStringBlocks首先检查成员变量mStringBlocks的值是否等于null。如果等于null的话,那么就说明当前应用程序使用的资源表中的资源项值字符串资源池还没有读取出来,这时候就会调用另外一个成员函数makeStringBlocks来进行读取。

           Step 14. AssetManager.makeStringBlocks

    public final class AssetManager {
        ......
    
        private final void makeStringBlocks(boolean copyFromSystem) {
            final int sysNum = copyFromSystem ? sSystem.mStringBlocks.length : 0;
            final int num = getStringBlockCount();
            mStringBlocks = new StringBlock[num];
            ......
            for (int i=0; i<num; i++) {
                if (i < sysNum) {
                    mStringBlocks[i] = sSystem.mStringBlocks[i];
                } else {
                    mStringBlocks[i] = new StringBlock(getNativeStringBlock(i), true);
                }
            }
        }
    
        ......
    
        private native final int getStringBlockCount();
        private native final int getNativeStringBlock(int block);
    
        ......
    }

            这个函数定义在文件frameworks/base/core/java/android/content/res/AssetManager.java中。

            参数copyFromSystem表示是否要将系统资源表里面的资源项值字符串资源池也一起拷贝到成员变量mStringBlokcs所描述的一个数组中去。如果它的值等于true的时候,那么AssetManager就会首先获得makeStringBlocks首先获得系统资源表的个数sysNum,接着再获得总的资源表个数num,这是通过调用JNI方法getStringBlockCount来实现的。注意,总的资源表个数num是包含了系统资源表的个数sysNum的。

            从前面的Step 4可以知道,用来访问系统资源包的AssetManager对象就保存在AssetManager类的静态成员变量sSystem中,并且这个AssetManager对象是最先被创建以及初始化的。也就是说,当执行到这一步的时候,所有系统资源表的资源项值字符串资源池已经读取出来,它们就保存在AssetManager类的静态成员变量sSystem所描述的一个AssetManager对象的成员变量mStringBlocks中,因此,只将它们拷贝到当前正在处理的AssetManager对象的成员变量mStringBlokcs的前sysNum个位置上去就可以了。

            最后,AssetManager类的成员函数makeStringBlocks就调用另外一个JNI方法getNativeStringBlock来读取剩余的其它资源表的资源项值字符串资源池,并且分别将它们封装在一个StringBlock对象保存在成员变量mStringBlokcs所描述的一个数组中。

            AssetManager类的JNI方法getNativeStringBlock实际上就是将每一个资源包里面的resources.arsc文件的资源项值字符串资源池数据块读取出来,并且封装在一个C++层的StringPool对象中,然后AssetManager类的成员函数makeStringBlocks再将该StringPool对象封装成一个Java层的StringBlock中。关于资源表中的资源项值字符串资源池的更多信息,可以参考前面Android应用程序资源的编译和打包过程分析一文。

            至此,我们就分析完成Android应用程序资源管理器的创建的初始化过程了,主要就是创建和初始化用来访问应用程序资源的AssetManager对象和Resources对象,其中,初始化操作包括设置AssetManager对象的资源文件路径以及设备配置信息等。有了这两个初始化的AssetManager对象和Resources对象之后,在接下来的一篇文章中,我们就可以继续分析应用程序资源的查找过程了,敬请关注!

    老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注!

    展开全文
  • Android 实现windows文件资源管理器

    千次阅读 2013-05-10 17:56:42
    1)效果图如下 2)关键代码如下 package com.example.filedemo; import java.io.File; import java.util.ArrayList; import java.util.List;...import android.os.Bundle; import android.app.Activity; impo

    1)效果图如下


    2)关键代码如下

    package com.example.filedemo;
    
    
    import java.io.File;
    import java.util.ArrayList;
    import java.util.List;
    
    
    import android.os.Bundle;
    import android.app.Activity;
    import android.view.Menu;
    import android.widget.AdapterView;
    import android.widget.ArrayAdapter;
    import android.widget.Button;
    import android.widget.ListView;
    import android.widget.TextView;
    import android.view.View;
    
    
    public class MainActivity extends Activity {
    
    
    private ListView listView1=null;
    private Button homeButton=null;
    private Button previousButton=null;
    private TextView pathTextView=null;
    /*
    * rootPathString 根目录 
    * itemsList 存储文件名
    * pathsList 存储文件路径
    * */
    private String rootPathString="/";
    private List<String> itemsList=null;
    private List<String> pathsList=null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    listView1=(ListView)findViewById(R.id.listView1);
    /*进入单击目录*/
    listView1.setOnItemClickListener(new ListView.OnItemClickListener(){
    public void onItemClick(AdapterView<?> parent,View view,int position,long arg3){
    /*获取单击文件*/
    File file=new File(pathsList.get(position));
    if(file.isDirectory()){
    getFiles(pathsList.get(position));
    }
    }
    });
    /*进入根目录*/
    homeButton=(Button)findViewById(R.id.homeButton);
    homeButton.setOnClickListener(new Button.OnClickListener() {
    @Override
    public void onClick(View arg0) {
    getFiles(rootPathString);
    }
    });
    /*进入上一级目录*/
    previousButton=(Button)findViewById(R.id.PreviousButton);
    previousButton.setOnClickListener(new Button.OnClickListener() {
    @Override
    public void onClick(View v) {
    String currentPathString=pathTextView.getText().toString();
    if(!currentPathString.equals(rootPathString)){
    File currentFile=new File(currentPathString);
    getFiles(currentFile.getParent());
    }
    }
    });
    pathTextView=(TextView)findViewById(R.id.pathTextView);
    getFiles(rootPathString);
    }
    /*
    * 获取当前目录文件
    * */
    private void getFiles(String filePathString){
    /*显示当前路径*/
    pathTextView.setText(filePathString);
    /*显示当前目录文件*/
    itemsList=new ArrayList<String>();
    pathsList=new ArrayList<String>();
    File currentFile=new File(filePathString);
    File[] files=currentFile.listFiles();
    if(files!=null&&files.length>0){
    for(int i=0;i<files.length;i++){
    File file=files[i];
    if(file.isDirectory()){
    itemsList.add(file.getName()+"(dir)");
    }else {
    itemsList.add(file.getName()+"(file)");
    }
    pathsList.add(file.getPath());
    }
    }
    ArrayAdapter<String> adapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, itemsList);
    listView1.setAdapter(adapter);
    }
    
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
    }
    
    
    }


    展开全文
  • ES文件浏览器是一个能管理手机本地、局域网共享、FTP和蓝牙文件的管理器。通过ES 文件浏览器用户可以在本地、局域网共享、FTP和蓝牙设备中浏览、传输、复制、剪切、删除、重命名文件和文件夹等等,还可以备份系统的...

    ES文件浏览器是一个能管理手机本地、局域网共享、FTP和蓝牙文件的管理器。通过ES 文件浏览器用户可以在本地、局域网共享、FTP和蓝牙设备中浏览、传输、复制、剪切、删除、重命名文件和文件夹等等,还可以备份系统的已装软件。

    注:默认模式下,用户可以浏览手机存储卡和部分手机系统文件,想要访问所有文件并对其进行操作,请启动超级用户管理选项(在设置菜单中)。

    1.SD卡文件管理器,进行各种文件操作、多种文件视图选项 多选和功能更强的剪贴板功能,搜索功能

    2.应用程序管理器,安装、备份、卸载、快捷方式

    3.进程管理器

    4.访问局域网计算机、FTP和蓝牙上的文件,可以在计算机和手机进行无缝的文件操作

    5.本地、共享、FTP、蓝牙查看、打开多媒体文件,内置文本编辑器

    展开全文
  • UltraExplorer, Android的开源文件资源管理器 UltraExplorerAndroid的开源 root 文件浏览器这个项目仍处于发展阶段。 如果其他开发人员改进代码并使之成为更好的资源管理器,我愿意这样做。 有关编码和问题的帮助,...
  • 这是一个关于Android 带图标的文件资源管理器的简单源码,供学习使用。  
  • AnExplorer文件管理(文件资源管理器)是一种多合一的文件管理工具。 它是简单,小型,快速和高效的文件资源管理器,并且是Google Play商店中最好的文件管理应用程序之一。 唯一的文件管理支持RTL并显示整个...
  • Android资源管理器 只是一个简单的项目,它显示了如何在android中使用资源管理。 通常对于我的项目,不是使用getString(R.string.STRING_ID),而是使用资源管理来访问android资源。 这样做是为了确保我可以...
  • android文件管理器源码

    千次下载 热门讨论 2011-07-06 19:35:32
    android系统并不自带文件管理,但是很多情况下,我们有诸如从SD中打开... 下面介绍在代码中实现资源管理器,只需要一百行左右的一个类即可以最常用的文件选择功能。本代码为简单的文件管理的实现,可独立编译执行.
  • android 制作有图标的文件资源管理器 自定义Adapter
  • 安卓下载任务管理 > 前言:上年开发了一个壁纸,音乐,应用,视频等资源浏览和下载安卓应用,准备分解功能模块做下笔记。下载页面UI设计参照 网易云音乐 下载功能 多任务并行下载 断点续传(需服务器支持) 项目...
  • iconFile带图标的文件资源管理器.zip
  • Android应用由 代码 和 资源 两部分组成 代码写在src目录,自定义的包里, 那么其他的文件夹都是干什么的呢? 字符串、菜单、图像、声音、视频等统一称为资源 用来定义和显示用户界面的一些静态信息 资源...

    Android应用由 代码 资源 两部分组成

    代码写在src目录,自定义的包里,

    那么其他的文件夹都是干什么的呢?




    字符串、菜单、图像、声音、视频等统一称为资源

    用来定义和显示用户界面的一些静态信息
    资源文件划分为XML、图像和其他

    (本人初学者,别喷啊!哭


    这次用Eclipse讲解吧,不用Studio了,反正2个软件都差不多


    一、图片的设定

    二、自定义颜色的设定

    三、设定样式或主题

    四、存在,但是不能识别的ID

    五、AndroidManifest.xml的作用

    六、边框样式

    七、插入文本与播放音乐




    一、图片的设定

    之前也讲过插入图片,不过是studio的...


        

    如下:设定了字体颜色 和 背景颜色,但是你不知道这个是什么颜色...

    因为是在 别的 xml 设定好,然后直接调用的!










    二、自定义颜色的设定

    1、eclipse中res 资源文件夹中,是没有color 文件夹的,要手动创建的(你们看到的是我已经创建好的了!)

    2、drawable 是存放图片的,但是不同于studio,有多个,把图片放进去,会转换不同的大小像素

    要手动创建一个正常像素的 文件夹,drawable

    3、drawable 也是可以存放 xml 文件的





    注意:studio 和 h5 中,颜色都是6位的rgb,

    但是eclipse中,颜色是8位的!






    建好之后,alt+/  提示,能显示你的样式



    效果:




    、设定样式或主题


    每次设定按钮或者 文本都要:

    宽,高,文字大小,颜色,背景色,对齐方式,外边距,内边距....

    (心好累,就不能想css3中 有样式一键设定,然后调用吗?有!当然有!)









    mystyle.xml样式中设定:








    四、识别不了ID

    (频繁修改文件名字的时候,R 文件 可能识别错误,或者没有反应过来,这时需要手动设定)

    TestOneActivity.java 方法中,ID是存在的,就是报错 ,无法识别!


    明明 id 是有的 !


    去R文件修改吧!

    根据提示,写个 0x7f0a0002 吧,

    (虽然知道R 是保存各个ID 参数的,不能轻易修改....




    五、不能识别子页面异常

    (家常便饭吧!eclipse经常运行,跳转页面中,闪退 或 apk未响应

    这里只是说 相对路径有时候无法识别 而 未响应,把它改为绝对路径 即可,

    其他语法,逻辑报错 就不是了!)


    把包名 加上去 即是绝对路径,

    studio中不用绝对路径也能识别所有的子页面!



    六、边框样式

    普通 xml页面是没有border 这些样式的,只好在drawable页面新建一个

    xml,自己写边框样式


    普通的与样式的

      




    编辑样式


    引用样式



    七、插入文本与播放音乐

    我们再写一点有意思的:插入txt文本,xml文本,音乐


    activity_test_three.xml


    设定边框样式:


    看效果:读取xml



    读取txt文本:


    音乐也是正常播放的,停止也是可以的!

    代码:

    TestThreeActivity.java

    package com.example.androidch04_2;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    import org.xmlpull.v1.XmlPullParser;
    
    import android.app.Activity;
    import android.media.MediaPlayer;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.EditText;
    
    public class TestThreeActivity extends Activity {
    
    	private EditText showText;
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_test_three);
    		showText=(EditText)findViewById(R.id.showText);
    	}
    	
    	//读取多媒体文件
    	MediaPlayer mp=null;
    	public void doStart(View view) throws Exception{
    		if(mp==null){
    			mp=MediaPlayer.create(this, R.raw.nobody);
    			mp.stop();
    		}
    		//mp多媒体对象不为空
    		if(mp.isPlaying()){
    			mp.seekTo(0);//重新开始
    		}else{
    			mp.prepare();
    		}                                      
    		mp.start();//开始播放
    		
    	}
    	public void doStop(View view){
    		if(mp!=null&&mp.isPlaying())
    			mp.stop();
    	}
    	
    	
    	//读取Txt文件
    	public void doReadTwo(View view) throws Exception{
    		//打开raw中文件,生产一个文件输入流
    		InputStream input=getResources().openRawResource(R.raw.hello);
    		byte[] bytes=new byte[input.available()];
    		input.read(bytes);
    		input.close();
    		
    		showText.setText(new String(bytes));
    	}
    
    	//读取XML
    	public void doRead(View view) throws Exception{
    		XmlPullParser xp=getResources().getXml(R.xml.books);
    		if(xp!=null){
    			StringBuffer sb=new StringBuffer();
    	//开始读取XML文件直到文档结束
    			while(xp.getEventType()!=XmlPullParser.END_DOCUMENT){
    				if(xp.getName()!=null){
    					sb.append(xp.getName()+"\n");
    				}
    				int attr=xp.getAttributeCount();
    //获取当前节点的属性个数
    				for (int i = 0; i < attr; i++) {
    					String name=xp.getAttributeName(i);
    					String value=xp.getAttributeValue(i);
    					sb.append(name+"="+value+"\n");
    				}
    				if(xp.getEventType()==XmlPullParser.TEXT)
    					sb.append(xp.getText());
    	//开始读取下一个节点
    				xp.next();
    			}
    			showText.setText(sb.toString());
    		}
    	}
    }
    
    
    


    activity_test_xml


    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
    <EditText 
        android:id="@+id/showText"
        android:lines="3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/test_border"
        />   
    
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="开始读取XML"
        android:onClick="doRead"/>
    
    <Button 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="开始读取txt"
        android:onClick="doReadTwo"/>
    
    <LinearLayout 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        
    <Button 
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content"
        android:text="开始音乐"
        android:onClick="doStart"/>
        
    <Button 
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content"
        android:text="停止音乐"
        android:onClick="doStop"/>
    
    </LinearLayout>
    
    </LinearLayout>
    



    资源管理器先到这里,后面还会完善!


    展开全文
  • Android应用程序资源管理框架 PPT

    千次下载 热门讨论 2013-10-23 01:25:11
    Android应用程序在运行的时候,资源管理器AssetManager和Resources会根据当前的机器设置,即屏幕大小、密度、方向,以及国家、地区语言的信息,查找正确的资源,并且进行解析,最后将它们渲染在UI上。这个PPT讲...
  • Android资源下载

    千次阅读 2013-03-27 11:22:56
    首先 介绍几本书籍(下载包中)吧。 01_Android系统概述 02_Android系统的开发综述 03_Android的Linux内核与驱动程序 04_Android的底层库和程序 05_Android的JAVA虚拟机和JAVA环境 06_Android的GUI...
  • Unity 调用Android文件资源管理器,可以选择Android手机上的图片,视频等一些列文件,并且获得相关的文件路径。直接导入Unity即可运行。测试已经通过
  • 人力资源管理系统(Android实现)

    千次阅读 2019-02-08 13:43:02
    人力资源管理系统(Android实现) 基于网上的北大青鸟人力资源管理系统需求文档写出的一份课程设计,基于Android studio和sql server数据库。 一、连接sql server数据库 本文采用的是jtds直连 下载支持Android的SQL...
  • 用java实现的资源管理器

    千次阅读 2015-03-14 22:32:41
    资源管理器树形结构的显示。 菜单的显示和操作。 文件夹的操作,新建、删除、拷贝、移动等。 文件的操作,新建、删除、拷贝、移动等。 参考Linux和windows下的资源管理器。 实现思路 用JTree实现资源管理器树形结构...
  • android 下载管理器简介

    千次阅读 2014-03-11 21:05:02
    package com.example.downloadmanager; import org.apache.commons.lang3.StringUtils; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.app.Activity;
  • Android如何加载第三方的资源,Resources与AssetManager获取资源的机制,本文教你如何快速了解
  • Android文件管理器源码

    2014-08-31 14:26:12
    Android文件管理器(增加了文件夹复制移动,下载资源暂停删除等,以及复制过程中的可视化进程)是一个基于Android开发的应用,包含常用文件操作以及文件下载功能,文件操作包括打开文件夹和打开各类的文件(apk、avi...
  • Android资源管理及引用

    千次阅读 2020-04-21 16:02:18
    Android资源管理及引用 资源目录 res/ 目录在各种子目录中包含了所有的资源。下表详细的给出了在项目中 res/ 目录里面支持的资源。 参考自:https://www.runoob.com/android/android-resources.html 目录 资源...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 171,329
精华内容 68,531
关键字:

安卓资源管理器下载