首页 文章 精选 留言 我的

精选列表

搜索[orm框架],共10000篇文章
优秀的个人博客,低调大师

Android--项目框架介绍

公司最近要开发一款Android平台下的应用,通讯软件,所以年后上班一直在研究Android方面的内容。 使用Eclipse开发的Android,对于一个新建的Android项目,自动生成的项目结构如下图: 自动生成的目录介绍: src目录:主要是存放编写的Java代码。 assets目录:资源目录。 res目录:存放图片、布局文件、字符串、菜单等文件。 bin目录:输出文件夹,如生成的APK文件。 project.properties:工程属性文件配置。 gen目录:系统自动生成的代码目录,存放R.java. 这个R.java文件是系统自动生成的文件,非常的重要。这个R.java默认有attr、drawable、layout、string等4个静态内部类,每个类对应一种资源。例如在工程中添加一幅图片,那么工程就会在此类的drawable内部类中添加一条数据,如果删除了此图片,工程则会自动删除此条数据。 在res资源文件夹下包含有以下的文件: Drawable存放工程图片的信息,默认png格式的图片。 Layout存放工程的布局文件以.xml结束。 Values文件夹下存放一个很重要的string.xml,此文件夹存放的是自定义的字符串和数值。 除了这个文件之外,还可以定义arrays.xml(用来定义数组)、color.xml(用来定义颜色和颜色字符串数值)、dimens.xml(用来定义尺寸数值)、styles.xml(用来定义样式)。这些文件只是为了区分资源的类型,一种开发规范,便于开发人员识别修改,其实可以全部定义在string.xml文件中,均可以自动生成到R.java,便于使用。 资源文件分别的格式: 数组: <string-array name="city"> <item >北京</item> <item >上海</item> </string-array> 颜色,使用二进制的RGB值表示: <color name="bgcolor">#FFCCFF</color> 尺寸: <dimen name="width">20dp</dimen> 样式: <sytle name="customText"> <item name="android:textSize">20sp</item> </sytle> 在安卓的activity中,均有一个全局的方法,getResource()来获取资源,具体资源的获取方法如下: 文件 取值方式 String.xml getResource().getString(resourceId)、getResource().getText(resourceId) Arrays.xml getResource().getStringArray(resourceId) colors.xml getResource().getDarwable(resourceId)、getResource().getColor(resourceId) Dimens.xml getResource().getDimension(resourceId) Styles.xml 不需要取值 AndroidManifest.xml文件介绍 AndroidManifest.xml是每个android程序中必须的文件。它位于整个项目的根目录,描述了package中暴露的组件(activities、services等等),他们各自的实现类,各种能被处理的数据和启动位置。能声明程序中的Activity、ContentProviders、ServersIntent Receivers、permissions和instrumentation(安全控制和测试)。 示例: <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="bgxt.demo" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:label="@string/app_name" android:name=".SimpleActivity" > <intent-filter > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> 其中manifest节点中的一些属性,介绍: Packgae:包,表示整个java应用程序的主要包名,而且是一个默认的程序名称。 Android:versionCode:表示该工程说生产的apk的版本号,1开始,逐渐递增。 Android:versionName:表示版本的一个名称。类似于:1.0、2.0. Android:installLoacation:自动寻找安装的地方,ROM或者SDCard,默认属性为自动。可选属性有auto:系统默认、internalOnly:仅仅只能安装在ROM上、preferExternal:会直接安装在sdcard上。 Application节点的一些属性介绍: Android:icon:表示应用程序的图标,Logo图片。 Android:label:表示应用的工程文字说明。 Activity节点的属性介绍: Android:name:表示整个应用程序的主程序的名称。 Intent-filter :意图过滤器,用来过滤用户的一些动作和操作。 本文转自承香墨影博客园博客,原文链接:http://www.cnblogs.com/plokmju/archive/2013/03/07/2949041.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Docker基础概念与框架

什么是容器? 一种虚拟化方案 操作系统级别的虚拟化 只能运行相同或相似内核的操作系统 依赖于Linux内核特性:NameSpace和CGroups(Control Group) Docker的目标: 提供简单轻量的建模方式 职责的逻辑分离 快速高效的开发生命周期 鼓励使用面向服务的架构 Docker的使用场景: 使用Docker容器开发、测试、部署服务 创建隔离的运行环境 搭建测试环境 构建多用户的平台即服务(PaaS)基础设施 提供软件即服务(SaaS)应用程序 高性能、超大规模的宿主机部署 Docker的基本组成: Docker Client客户端 Docker Daemon守护进程 Docker Image镜像 Docker Container容器 Docker Registry仓库 Docker是C/S的架构,Docker的客户端向Docker的守护进程发出请求,守护进程处理完所有的工作并返回结果。Docker容器的创建运行基于Docker的镜像。Docker镜像是一个层叠的只读文件系统,最底层是一个引导系统bootfs,当一个容器启动后,这个容器将会被移动到内存中,而引导文件系统会被卸载。Docker镜像的第二层是rootfs,位于bootfs之上。rootfs可以是一种或多种文件系统,在传统的Linux中,rootfs将会以只读文件系统进行加载,当引导结束并且完成了完整性检查后,才会被切换为读写模式,但是Docker中rootfs永远是只读文件系统的状态,并且Docker使用联合加载技术在rootfs之上加载更多的只读文件系统,在外部称为一个完整的系统。Docker将这样的文件系统称为镜像。Docker的容器启动的时候将会在镜像的最顶层加载一个可读写的文件系统,在Docker中执行的程序就是在这个可写层执行的。当Docker容器启动后,这个可写层是空的,当需要修改文件系统的文件的时候,Docker将会把这个文件复制到可写层,这个可写层的文件副本将会隐藏只读层的对应的文件,这就叫做Docker写时复制。Docker使用仓库来保存用户构建的镜像,仓库分为公有仓库和私有仓库两种,Docker自己提供的Docker公有仓库叫做Docker Hub。 Docker容器的相关技术: Docker依赖的Linux内核特性 (1)Namespaces命名空间: 编程语言中的命名空间是为了实现更好的封装,也就是代码隔离。 操作系统的命名空间是实现了系统资源的隔离,例如:进程、网络、文件系统。Linux内核实现命名空间的最主要的原因之一就是为了实现轻量级的虚拟化功能。 Docker使用了五种命名空间: PID(Process ID) 进程隔离 NET(Network) 网络接口管理 IPC(InterProcess Communication) 跨进程通信访问管理 MNT(Mount) 管理挂载点 UTS(Unix Timesharing System) 隔离内核和版本标识 这些隔离的资源使用CGroups进行管理。 (2)Controlgroups控制组: CGroups是Linux内核提供的可以限制、记录、隔离进程组所使用的物理资源的机制。由Google的工程师提出。在2004年整合进入Linux kernel 2.6.24。 CGroups提供的功能: 资源限制 优先级设定 资源计量 资源控制 CGroups赋予Docker的能力: 文件系统的隔离:每个Docker容器都有自己的rootfs 进程隔离:每个容器都运行在自己的进程环境中 网络隔离:容器间的虚拟接口和IP地址都是分开的 资源隔离和分组:使用CGroups将CPU和内存之类的资源独立分配给每个Docker容器。 本文转自 棋帅小七 51CTO博客,原文链接:http://blog.51cto.com/xvjunjie/1982394

优秀的个人博客,低调大师

android 基础框架依赖库

AndroidBaseModule android base module project 基础的Android开发依赖包,独立出来主要是为了持续更新,方便多个项目同时使用,同步更新;同时使工程结构更加简洁。 使用方式 1) 新工程建议直接下载AndroidMouldProject,修改包名后在此基础上开发; or 2) Add Library module as a dependency in your build.gradle file. Add the dependency dependencies { compile 'com.github.BrillantZhao:AndroidBaseModule:1.1.2.48' } 项目结构 用到的第三方库 //=== butterKnife (https://github.com/JakeWharton/butterknife) "butterknife" : "com.jakewharton:butterknife:${butterKnifeVersion}", "butterknife-compiler" : "com.jakewharton:butterknife-compiler:${butterKnifeVersion}", //=== rxjava(https://github.com/ReactiveX/RxJava) "rxjava" : "io.reactivex:rxjava:${rxjavaVersion}", //=== rxandroid(https://github.com/ReactiveX/RxAndroid) "rxandroid" : "io.reactivex:rxandroid:${rxandroidVersion}", //=== AndroidUtilCode (https://github.com/Blankj/AndroidUtilCode) "utilcode" : "com.blankj:utilcode:${utilcodeVersion}", //=== RxLifecycle (https://github.com/trello/RxLifecycle) "rxlifecycle" : "com.trello:rxlifecycle:${rxlifecycleVersion}", "rxlifecycle-android" : "com.trello:rxlifecycle-android:${rxlifecycleVersion}", "rxlifecycle-components": "com.trello:rxlifecycle-components:${rxlifecycleVersion}", "rxlifecycle-navi" : "com.trello:rxlifecycle-navi:${rxlifecycleVersion}", "rxlifecycle-kotlin" : "com.trello:rxlifecycle-kotlin:${rxlifecycleVersion}", //=== glide (https://github.com/bumptech/glide) "glide" : "com.github.bumptech.glide:glide:${glideVersion}", //=== hawk (https://github.com/orhanobut/hawk) "hawk" : "com.orhanobut:hawk:${hawkVersion}", //=== fastjson (https://github.com/alibaba/fastjson) "fastjson" : "com.alibaba:fastjson:${fastjsonVersion}" API ### base相关→最底层的继承 IBaseActivity : "", IBaseApplication : "", IBaseFragment : "", IBaseFragmentAdapter : "", IBaseFragmentStateAdapter: "", IBaseModel : "", IBasePresenter : "", IBaseView : "", ### baseapp相关→应用的一些基本工具类 AppException: "异常记录与处理", AppManager : "activity管理工具", BaseRespose : "网络请求基础返回", ### baserx相关→rx底层处理 RxBus : "", RxCache : "", RxHelper : "", RxManager : "", RxSchedulers : "", RxSubscriber : "", ServerException: "", ### local相关→数据存储 SharedPrefUtils: "sharedPreference数据存储", ### notes相关→说明文档 Android 代码混淆在AS的实践 Android 使用gradle打包的各种配置 Android 自动化打包实践 gradle打包并推送到git远程库 Android开发之版本统一规范 GitSubmodule 神注释大全 ### utils相关→自定义的工具类 ACache : "", CollectionUtils : "", DialogPermissionUtil : "", DisplayUtil : "", FormatUtil : "", GlideCircleTransfromUtil: "", GlideRoundTransformUtil : "", ImageLoaderUtils : "", IpUtils : "", JsonConvertHelper : "", MeasureUtils : "", NetWorkUtils : "", RxCountDown : "", SDCardUtils : "", TimeUtil : "", TUtil : "", ### widget相关→自定义的控件 NoScrollGridView : "", NoScrollListview : "", OnDoubleClickListener : "", OnNoDoubleClickListener: "", 详细介绍 参见 AndroidBaseModule,工程地址为:https://github.com/BrillantZhao/AndroidBaseModule 参见 AndroidMouldProject(常规的MVP结构),工程地址为:https://github.com/BrillantZhao/AndroidMouldProject 参见 AndroidMouldProject(组件化的MVP结构,建议使用),工程地址为:https://github.com/BrillantZhao/AndroidMouldProject2

优秀的个人博客,低调大师

Apache Kylin的框架介绍

Apache kylin能提供低延迟(sub-second latency)的秘诀就是预计算,即针对一个星型拓扑结构的数据立方体,预计算多个维度组合的度量,然后将结果保存在hbase中,对外暴露JDBC、ODBC、Rest API的查询接口,即可实现实时查询。 如上图所示,Kylin从Hadoop Hive中获取数据,然后经过Cube Build Engine,将Hive中的数据Build成一个OLAP Cube保存在HBase中。用户执行SQL查询时,通过Query引擎,将SQL语句解析成OLAP Cube查询,然后将结果返回给用户。 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/7404400.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android应用框架之PackageManagerService

系统在启动的时候会启动一个叫做PackageManagerService的服务,顾名思义,这个服务主要管理安装在设备上的应用程序,其中最为重要的工作就是在在系统启动之后,PackageManagerService会扫描特定目录下地以apk为后缀的文件,然后将对应的应用安装到系统中。注意,这里的安装并不是我们平时所说的安装,它指的的是将存放在磁盘之上的静态应用程序文件进行解析,并将相关信息注册到系统中。而具体的解析工作实际就是读取应用的配置文件manifest.xml,并将文件中配置的组件 (Activity,Service,BroadcastRecevier,ContentProvider),权限等信息注册到PackageManagerService中。 本篇博客主要介绍PackageManagerService的启动过程,以及PackageManagerService如何安装各个应用程序。 1.PackageManagerService启动过程 和ActivityManagerService,WindowManagerService一样,PackageManagerService是一个系统级的服务,运行在独立的进程中,而所有的系统级服务都是由SystemServer启动的。所以首先来看看SystemServer的启动过程。 1) SystemServer启动: SystemServer组件是由Zygote进程负责启动的,启动的时候就会调用它的main函数,这个函数主要调用了JNI方法init1来做一些系统初始化的工作。 public class SystemServer { ...... native public static void init1(String[] args); ...... public static void main(String[] args) { ...... init1(args); ...... } ...... } 2)SystemServer.system_init 经过一系列调用后转到system_init方法,这是一个JNI方法 extern "C" status_t system_init() { LOGI("Entered system_init()"); sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager(); LOGI("ServiceManager: %p\n", sm.get()); sp<GrimReaper> grim = new GrimReaper(); sm->asBinder()->linkToDeath(grim, grim.get(), 0); char propBuf[PROPERTY_VALUE_MAX]; property_get("system_init.startsurfaceflinger", propBuf, "1"); if (strcmp(propBuf, "1") == 0) { // Start the SurfaceFlinger SurfaceFlinger::instantiate(); } // Start the sensor service SensorService::instantiate(); // On the simulator, audioflinger et al don't get started the // same way as on the device, and we need to start them here if (!proc->supportsProcesses()) { // Start the AudioFlinger AudioFlinger::instantiate(); // Start the media playback service MediaPlayerService::instantiate(); // Start the camera service CameraService::instantiate(); // Start the audio policy service AudioPolicyService::instantiate(); } // And now start the Android runtime. We have to do this bit // of nastiness because the Android runtime initialization requires // some of the core system services to already be started. // All other servers should just start the Android runtime at // the beginning of their processes's main(), before calling // the init function. LOGI("System server: starting Android runtime.\n"); AndroidRuntime* runtime = AndroidRuntime::getRuntime(); LOGI("System server: starting Android services.\n"); runtime->callStatic("com/android/server/SystemServer", "init2"); // If running in our own process, just go into the thread // pool. Otherwise, call the initialization finished // func to let this process continue its initilization. if (proc->supportsProcesses()) { LOGI("System server: entering thread pool.\n"); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); LOGI("System server: exiting thread pool.\n"); } return NO_ERROR; } 在这个方法中,创建了SurfaceFlinger、SensorService、AudioFlinger、MediaPlayerService、CameraService和AudioPolicyService这几个服务,然后就通过系统全局唯一的AndroidRuntime实例变量runtime的callStatic来调用SystemServer的init2函数了。init2函数很简单,创建一个线程,而PackageManagerService就是在这个线程中创建的。 public class SystemServer { ...... public static final void init2() { Slog.i(TAG, "Entered the Android system server!"); Thread thr = new ServerThread(); thr.setName("android.server.ServerThread"); thr.start(); } } 3)ServerThread.run class ServerThread extends Thread { ...... @Override public void run() { ...... IPackageManager pm = null; ...... // Critical services... try { ...... Slog.i(TAG, "Package Manager"); pm = PackageManagerService.main(context, factoryTest != SystemServer.FACTORY_TEST_OFF); ...... } catch (RuntimeException e) { Slog.e("System", "Failure starting core service", e); } ...... } ...... } 在这个线程中创建了PackageManagerService,并同时启动了其main函数。另外在这个线程中还启动了ActivityManagerService等其他Service 2.应用安装 接下来再来看看PackageManagerService启动之后如何进行应用程序的安装。 1)PackageManagerService.main class PackageManagerService extends IPackageManager.Stub { ...... public static final IPackageManager main(Context context, boolean factoryTest) { PackageManagerService m = new PackageManagerService(context, factoryTest); ServiceManager.addService("package", m); return m; } ...... } 可以看到,创建完成后,就加载到ServiceManager中。接下来看看PackageManagerService的构造函数: class PackageManagerService extends IPackageManager.Stub { ...... public PackageManagerService(Context context, boolean factoryTest) { ...... synchronized (mInstallLock) { synchronized (mPackages) { ...... File dataDir = Environment.getDataDirectory(); mAppDataDir = new File(dataDir, "data"); mSecureAppDataDir = new File(dataDir, "secure/data"); mDrmAppPrivateInstallDir = new File(dataDir, "app-private"); ...... mFrameworkDir = new File(Environment.getRootDirectory(), "framework"); mDalvikCacheDir = new File(dataDir, "dalvik-cache"); ...... // Find base frameworks (resource packages without code). mFrameworkInstallObserver = new AppDirObserver( mFrameworkDir.getPath(), OBSERVER_EVENTS, true); mFrameworkInstallObserver.startWatching(); scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode | SCAN_NO_DEX, 0); // Collect all system packages. mSystemAppDir = new File(Environment.getRootDirectory(), "app"); mSystemInstallObserver = new AppDirObserver( mSystemAppDir.getPath(), OBSERVER_EVENTS, true); mSystemInstallObserver.startWatching(); scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0); // Collect all vendor packages. mVendorAppDir = new File("/vendor/app"); mVendorInstallObserver = new AppDirObserver( mVendorAppDir.getPath(), OBSERVER_EVENTS, true); mVendorInstallObserver.startWatching(); scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0); mAppInstallObserver = new AppDirObserver( mAppInstallDir.getPath(), OBSERVER_EVENTS, false); mAppInstallObserver.startWatching(); scanDirLI(mAppInstallDir, 0, scanMode, 0); mDrmAppInstallObserver = new AppDirObserver( mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false); mDrmAppInstallObserver.startWatching(); scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK, scanMode, 0); ...... } } } ...... } 可以看到,在构造函数中,PackageManagerService(PMS)会扫描特定目录下的APK文件,然后进行相关的加载工作,这些目录包括: /system/framework /system/app /vendor/app /data/app /data/app-private 在每个路径下,都调用了scanDirLI函数,接下来看看对应的函数做了些什么。 2)PackageParser.parsePackage scanDirLI中又经过多次调用,具体就是扫描对应目录的文件,如果是apk文件,就找到apk文件中的manifest文件,最后再为每一个apk创建一个PackageParser对象,并将manifest文件传递给PackageParser.parsePackage。 public class PackageParser { ...... private Package parsePackage( Resources res, XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException, IOException { ...... String pkgName = parsePackageName(parser, attrs, flags, outError); ...... final Package pkg = new Package(pkgName); ...... int type; ...... TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifest); ...... while ((type=parser.next()) != parser.END_DOCUMENT && (type != parser.END_TAG || parser.getDepth() > outerDepth)) { if (type == parser.END_TAG || type == parser.TEXT) { continue; } String tagName = parser.getName(); if (tagName.equals("application")) { ...... if (!parseApplication(pkg, res, parser, attrs, flags, outError)) { return null; } } else if (tagName.equals("permission-group")) { ...... } else if (tagName.equals("permission")) { ...... } else if (tagName.equals("permission-tree")) { ...... } else if (tagName.equals("uses-permission")) { ...... } else if (tagName.equals("uses-configuration")) { ...... } else if (tagName.equals("uses-feature")) { ...... } else if (tagName.equals("uses-sdk")) { ...... } else if (tagName.equals("supports-screens")) { ...... } else if (tagName.equals("protected-broadcast")) { ...... } else if (tagName.equals("instrumentation")) { ...... } else if (tagName.equals("original-package")) { ...... } else if (tagName.equals("adopt-permissions")) { ...... } else if (tagName.equals("uses-gl-texture")) { ...... } else if (tagName.equals("compatible-screens")) { ...... } else if (tagName.equals("eat-comment")) { ...... } else if (RIGID_PARSER) { ...... } else { ...... } } ...... return pkg; } ...... private Package parsePackage( Resources res, XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException, IOException { ...... String pkgName = parsePackageName(parser, attrs, flags, outError); ...... final Package pkg = new Package(pkgName); ...... int type; ...... TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifest); ...... while ((type=parser.next()) != parser.END_DOCUMENT && (type != parser.END_TAG || parser.getDepth() > outerDepth)) { if (type == parser.END_TAG || type == parser.TEXT) { continue; } String tagName = parser.getName(); if (tagName.equals("application")) { ...... if (!parseApplication(pkg, res, parser, attrs, flags, outError)) { return null; } } else if (tagName.equals("permission-group")) { ...... } else if (tagName.equals("permission")) { ...... } else if (tagName.equals("permission-tree")) { ...... } else if (tagName.equals("uses-permission")) { ...... } else if (tagName.equals("uses-configuration")) { ...... } else if (tagName.equals("uses-feature")) { ...... } else if (tagName.equals("uses-sdk")) { ...... } else if (tagName.equals("supports-screens")) { ...... } else if (tagName.equals("protected-broadcast")) { ...... } else if (tagName.equals("instrumentation")) { ...... } else if (tagName.equals("original-package")) { ...... } else if (tagName.equals("adopt-permissions")) { ...... } else if (tagName.equals("uses-gl-texture")) { ...... } else if (tagName.equals("compatible-screens")) { ...... } else if (tagName.equals("eat-comment")) { ...... } else if (RIGID_PARSER) { ...... } else { ...... } } ...... return pkg; } ...... } 这里就是对AndroidManifest.xml文件中的application标签进行解析了,我们常用到的标签就有activity、service、receiver和provider,这里解析完成后,一层层返回,调用另一个版本的scanPackageLI函数把来解析后得到的应用程序信息保存下来。 class PackageManagerService extends IPackageManager.Stub { ...... // Keys are String (package name), values are Package. This also serves // as the lock for the global state. Methods that must be called with // this lock held have the prefix "LP". final HashMap<String, PackageParser.Package> mPackages = new HashMap<String, PackageParser.Package>(); ...... // All available activities, for your resolving pleasure. final ActivityIntentResolver mActivities = new ActivityIntentResolver(); // All available receivers, for your resolving pleasure. final ActivityIntentResolver mReceivers = new ActivityIntentResolver(); // All available services, for your resolving pleasure. final ServiceIntentResolver mServices = new ServiceIntentResolver(); // Keys are String (provider class name), values are Provider. final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent = new HashMap<ComponentName, PackageParser.Provider>(); ...... private PackageParser.Package scanPackageLI(PackageParser.Package pkg, int parseFlags, int scanMode, long currentTime) { ...... synchronized (mPackages) { ...... // Add the new setting to mPackages mPackages.put(pkg.applicationInfo.packageName, pkg); ...... int N = pkg.providers.size(); int i; for (i=0; i<N; i++) { PackageParser.Provider p = pkg.providers.get(i); p.info.processName = fixProcessName(pkg.applicationInfo.processName, p.info.processName, pkg.applicationInfo.uid); mProvidersByComponent.put(new ComponentName(p.info.packageName, p.info.name), p); ...... } N = pkg.services.size(); for (i=0; i<N; i++) { PackageParser.Service s = pkg.services.get(i); s.info.processName = fixProcessName(pkg.applicationInfo.processName, s.info.processName, pkg.applicationInfo.uid); mServices.addService(s); ...... } N = pkg.receivers.size(); r = null; for (i=0; i<N; i++) { PackageParser.Activity a = pkg.receivers.get(i); a.info.processName = fixProcessName(pkg.applicationInfo.processName, a.info.processName, pkg.applicationInfo.uid); mReceivers.addActivity(a, "receiver"); ...... } N = pkg.activities.size(); for (i=0; i<N; i++) { PackageParser.Activity a = pkg.activities.get(i); a.info.processName = fixProcessName(pkg.applicationInfo.processName, a.info.processName, pkg.applicationInfo.uid); mActivities.addActivity(a, "activity"); ...... } ...... } ...... return pkg; } ...... } 到这里整个应用的安装过程就介绍完了。其实整个过程还是很明确,清晰的。 接下来再来总结一下整个启动过程: Zygote—>启动SystemServer—>启动ServerThread—>启动PackageManagerService—>扫描特定目录下的apk文件,进行加载—>解析APK的manifest文件,将配置信息加载到PackageManagerService中

优秀的个人博客,低调大师

Android应用框架之BroadcastReceiver

广播机制是Android系统中的一种消息传播机制,通过观察者模式实现了消息发送者与消息接收者之间的解耦。BroadcastReceiver的使用方式有两种,一种是静态注册,即在Manifest文件中注册,然后在需要发送广播时调用context.sendBroadcast(intent);;第二种是动态注册。BroadcastReceiver的使用不是本文的重点,本文将着重讲解广播的注册过程和消息发送及接收过程。 1 广播注册过程 广播的静态注册是通过PMS(PackageManagerService)来完成的,其余三大组件也是通过PMS来完成注册的。这里重点讲一下BroadcastReceiver的动态启动方法。和Activity以及Service一样,其启动过程也是通过ContextWrapper-->ContextImpl来完成的。其主要的启动函数是ContextImpl.registerReceiver: private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId, IntentFilter filter, String broadcastPermission, Handler scheduler, Context context) { IIntentReceiver rd = null; ...... rd = mPackageInfo.getReceiverDispatcher(receiver, context, scheduler, mMainThread.getInstrumentation, true); ...... return ActivityManagerNatvice.getDefault().registerReceiver(mMainThread.getApplicationThread(), mBasePackageName, rd, filter, boradcastPermission, userId); ...... } 从上面的代码可以看出主要做了两件事: 从mPackageInfo获取IIntentReceiver对象,之所以这样和bindService是一样的,因为上述的注册过程是一个跨进程的通信方式,而BroadcastReceiver作为Android的一个组件是不能直接跨进程传递的,所以需要使用IIntentReceiver来中转。其具体是由LoadedApk.ReceiverDispatcher.InnerReceiver,ReceiverDispatcher内部同时保存了BroadcastReceiver和InnerReceiver,所以当接收到广播时,ReceiverDispatcher可以很方便地调用BroadcastReceiver.onReceive()方法。 通过ActivityManagerNative.getDefault()获取ActivityManagerService,然后通过AMS来完成广播的注册过程。 接下来具体看一下AMS的registerReceiver具体的实现: public Intent registerReceiver(IApplicationThread caller, String callerPackage, IIntentReceiver receiver, IntentFilter filter, String permission, int userId) { ...... mRegisterReceivers.put(receiver.asBinder(), rl); BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission, callingUid, userId); rl.add(bf); mReceiverResolver.addFilter(bf); } 2 广播的发送和接收过程 广播的发送通过ContextImpl.sendBroadcast方法: public void sendBroadcast(Intent intent) { ...... ActivityManagerNative.getDefault().broadcastIntent(mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, false, false, getUserId()); ...... } 不出意料,任务又转到了AMS中,AMS在接收到这个指令会调用内部的broadcastIntentLocked方法,在该方法中,AMS会根据intent-filter查找出匹配的广播接收者,并通过一系列的条件过滤,并将最终满足条件的广播接收者添加到BroadcastQueue中,然后BroadcastQueue会将广播发送到相应的广播接收者,核心代码如下: BroadcastQueue queue = broadcastQueueForIntent(intent); BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callingPid, callingUid, resolvedType, requiredPermission, appOp, receivers, resultTo, resultCode, resultData, map, ordered, sticky, false, userId); ...... queue.enqueOrderedBroadcastLocked(r); queue.scheduleBroadcastsLocked(); 下面再看一下在BroadcastQueue中发送广播scheduleBroadcastsLocked的实现: public void scheduleBroadcastsLocked(){ ...... mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this)); ...... } 实际上BroadcastQueue的scheduleBroadcastsLocked方法没有立即发送广播,而是发送了一个BROADCAST_INTENT_MSG类型的消息,BroadcastQueue收到该消息后会调用processNestBroadcast方法: while(mParallelBroadcasts.size() > 0) { r = mParallelBroadcasts.remove(0); r.dispatchTime = SystemClock.uptimeMillis(); r.dispatchClockTime = System.currentTimeMillis(); final int N = r.recivers.size(); for(int i = 0; i < N; i++) { Object target = r.receivers.get(i); deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false); } addBroadcastToHistoryLocked(r); } 可以看到无序广播存储在mParallelBroadcasts中,系统遍历该队列,并将广播发送给它所有的接收者。具体的发送工作通过deliverToRegisteredReceiverLocked完成,在该函数内部通过performReceivedLocked来完成: private static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver, Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws RemoteException { ...... app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode, data, extras, ordered, sticky, sendingUser, app.repProcState); ...... } ApplicationThread的scheduleRegisteredReceiver会调用InnerReceiver.performReceive来实现广播的接收。而在这个方法中会调用LoadedApk.ReceiverDispatcher.performReceive方法: public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { ...... Args args = new Args(intent, resultCode, data, extras, ordered, sticky, sendingUser); if(!mActivityThread.post(args)) { if(mRistered && ordered) { IActivityManager mgr = ActivityManagerNative.getDefault(); args.sendFinished(mgr); } } } 在上面的代码中,会创建一个Args对象,并通过mActivityThread的post方法来执行Args的逻辑,Args实际上是一个Runnable接口。mActivityThread是一个Handler,其实就是ActivityThread中的mH,类型是H。Args中的run方法有如下几行代码: final BroadcastReceiver receiver = mReceiver; receiver.setPendingResult(this); receiver.onReceive(mContext, intent); 这个时候BroadcastReceiver的onReceive方法才被执行,也就接收到广播了。

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册