首页 文章 精选 留言 我的

精选列表

搜索[桌面应用程序],共10000篇文章
优秀的个人博客,低调大师

Android应用程序安装过程源代码分析(2)

Step 4. AndroidRuntime.callStatic 这个函数定义在frameworks/base/core/jni/AndroidRuntime.cpp文件中: [cpp] view plain copy /* *CallastaticJavaProgrammingLanguagefunctionthattakesnoargumentsandreturnsvoid. */ status_tAndroidRuntime::callStatic(constchar*className,constchar*methodName) { JNIEnv*env; jclassclazz; jmethodIDmethodId; env=getJNIEnv(); if(env==NULL) returnUNKNOWN_ERROR; clazz=findClass(env,className); if(clazz==NULL){ LOGE("ERROR:couldnotfindclass'%s'\n",className); returnUNKNOWN_ERROR; } methodId=env->GetStaticMethodID(clazz,methodName,"()V"); if(methodId==NULL){ LOGE("ERROR:couldnotfindmethod%s.%s\n",className,methodName); returnUNKNOWN_ERROR; } env->CallStaticVoidMethod(clazz,methodId); returnNO_ERROR; } 这个函数调用由参数className指定的java类的静态成员函数,这个静态成员函数是由参数methodName指定的。上面传进来的参数className的值为"com/android/server/SystemServer",而参数methodName的值为"init2",因此,接下来就会调用SystemServer类的init2函数了。 Step 5.SystemServer.init2 这个函数定义在frameworks/base/services/java/com/android/server/SystemServer.java文件中: [java] view plain copy publicclassSystemServer { ...... publicstaticfinalvoidinit2(){ Slog.i(TAG,"EnteredtheAndroidsystemserver!"); Threadthr=newServerThread(); thr.setName("android.server.ServerThread"); thr.start(); } } 这个函数创建了一个ServerThread线程,PackageManagerService服务就是这个线程中启动的了。这里调用了ServerThread实例thr的start函数之后,下面就会执行这个实例的run函数了。 Step 6.ServerThread.run 这个函数定义在frameworks/base/services/java/com/android/server/SystemServer.java文件中: [java] view plain copy classServerThreadextendsThread{ ...... @Override publicvoidrun(){ ...... IPackageManagerpm=null; ...... //Criticalservices... try{ ...... Slog.i(TAG,"PackageManager"); pm=PackageManagerService.main(context, factoryTest!=SystemServer.FACTORY_TEST_OFF); ...... }catch(RuntimeExceptione){ Slog.e("System","Failurestartingcoreservice",e); } ...... } ...... } 这个函数除了启动PackageManagerService服务之外,还启动了其它很多的服务,例如在前面学习Activity和Service的几篇文章中经常看到的ActivityManagerService服务,有兴趣的读者可以自己研究一下。 本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966521,如需转载请自行联系原作者

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

Android应用程序启动过程源代码分析(4)

Step 28. ActivityStack.realStartActivityLocked 这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityStack.java文件中: publicclassActivityStack{ ...... finalbooleanrealStartActivityLocked(ActivityRecordr, ProcessRecordapp,booleanandResume,booleancheckConfig) throwsRemoteException{ ...... r.app=app; ...... intidx=app.activities.indexOf(r); if(idx<0){ app.activities.add(r); } ...... try{ ...... List<ResultInfo>results=null; List<Intent>newIntents=null; if(andResume){ results=r.results; newIntents=r.newIntents; } ...... app.thread.scheduleLaunchActivity(newIntent(r.intent),r, System.identityHashCode(r), r.info,r.icicle,results,newIntents,!andResume, mService.isNextTransitionForward()); ...... }catch(RemoteExceptione){ ...... } ...... returntrue; } ...... } 这里最终通过app.thread进入到ApplicationThreadProxy的scheduleLaunchActivity函数中,注意,这里的第二个参数r,是一个ActivityRecord类型的Binder对象,用来作来这个Activity的token值。 Step 29.ApplicationThreadProxy.scheduleLaunchActivity 这个函数定义在frameworks/base/core/java/android/app/ApplicationThreadNative.java文件中: classApplicationThreadProxyimplementsIApplicationThread{ ...... publicfinalvoidscheduleLaunchActivity(Intentintent,IBindertoken,intident, ActivityInfoinfo,Bundlestate,List<ResultInfo>pendingResults, List<Intent>pendingNewIntents,booleannotResumed,booleanisForward) throwsRemoteException{ Parceldata=Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); intent.writeToParcel(data,0); data.writeStrongBinder(token); data.writeInt(ident); info.writeToParcel(data,0); data.writeBundle(state); data.writeTypedList(pendingResults); data.writeTypedList(pendingNewIntents); data.writeInt(notResumed?1:0); data.writeInt(isForward?1:0); mRemote.transact(SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION,data,null, IBinder.FLAG_ONEWAY); data.recycle(); } ...... } 这个函数最终通过Binder驱动程序进入到ApplicationThread的scheduleLaunchActivity函数中。 Step 30.ApplicationThread.scheduleLaunchActivity 这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中: publicfinalclassActivityThread{ ...... privatefinalclassApplicationThreadextendsApplicationThreadNative{ ...... //weusetokentoidentifythisactivitywithouthavingtosendthe //activityitselfbacktotheactivitymanager.(mattersmorewithipc) publicfinalvoidscheduleLaunchActivity(Intentintent,IBindertoken,intident, ActivityInfoinfo,Bundlestate,List<ResultInfo>pendingResults, List<Intent>pendingNewIntents,booleannotResumed,booleanisForward){ ActivityClientRecordr=newActivityClientRecord(); r.token=token; r.ident=ident; r.intent=intent; r.activityInfo=info; r.state=state; r.pendingResults=pendingResults; r.pendingIntents=pendingNewIntents; r.startsNotResumed=notResumed; r.isForward=isForward; queueOrSendMessage(H.LAUNCH_ACTIVITY,r); } ...... } ...... } 函数首先创建一个ActivityClientRecord实例,并且初始化它的成员变量,然后调用ActivityThread类的queueOrSendMessage函数进一步处理。 Step 31.ActivityThread.queueOrSendMessage 这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中: publicfinalclassActivityThread{ ...... privatefinalclassApplicationThreadextendsApplicationThreadNative{ ...... //ifthethreadhasn'tstartedyet,wedon'thavethehandler,sojust //savethemessagesuntilwe'reready. privatefinalvoidqueueOrSendMessage(intwhat,Objectobj){ queueOrSendMessage(what,obj,0,0); } ...... privatefinalvoidqueueOrSendMessage(intwhat,Objectobj,intarg1,intarg2){ synchronized(this){ ...... Messagemsg=Message.obtain(); msg.what=what; msg.obj=obj; msg.arg1=arg1; msg.arg2=arg2; mH.sendMessage(msg); } } ...... } ...... } 函数把消息内容放在msg中,然后通过mH把消息分发出去,这里的成员变量mH我们在前面已经见过,消息分发出去后,最后会调用H类的handleMessage函数。 Step 32. H.handleMessage 这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中: publicfinalclassActivityThread{ ...... privatefinalclassHextendsHandler{ ...... publicvoidhandleMessage(Messagemsg){ ...... switch(msg.what){ caseLAUNCH_ACTIVITY:{ ActivityClientRecordr=(ActivityClientRecord)msg.obj; r.packageInfo=getPackageInfoNoCheck( r.activityInfo.applicationInfo); handleLaunchActivity(r,null); }break; ...... } ...... } ...... } 这里最后调用ActivityThread类的handleLaunchActivity函数进一步处理。 Step 33.ActivityThread.handleLaunchActivity 这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中: publicfinalclassActivityThread{ ...... privatefinalvoidhandleLaunchActivity(ActivityClientRecordr,IntentcustomIntent){ ...... Activitya=performLaunchActivity(r,customIntent); if(a!=null){ r.createdConfig=newConfiguration(mConfiguration); BundleoldState=r.state; handleResumeActivity(r.token,false,r.isForward); ...... }else{ ...... } } ...... } 这里首先调用performLaunchActivity函数来加载这个Activity类,即shy.luo.activity.MainActivity,然后调用它的onCreate函数,最后回到handleLaunchActivity函数时,再调用handleResumeActivity函数来使这个Activity进入Resumed状态,即会调用这个Activity的onResume函数,这是遵循Activity的生命周期的。 Step 34.ActivityThread.performLaunchActivity 这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中: publicfinalclassActivityThread{ ...... privatefinalActivityperformLaunchActivity(ActivityClientRecordr,IntentcustomIntent){ ActivityInfoaInfo=r.activityInfo; if(r.packageInfo==null){ r.packageInfo=getPackageInfo(aInfo.applicationInfo, Context.CONTEXT_INCLUDE_CODE); } ComponentNamecomponent=r.intent.getComponent(); if(component==null){ component=r.intent.resolveActivity( mInitialApplication.getPackageManager()); r.intent.setComponent(component); } if(r.activityInfo.targetActivity!=null){ component=newComponentName(r.activityInfo.packageName, r.activityInfo.targetActivity); } Activityactivity=null; try{ java.lang.ClassLoadercl=r.packageInfo.getClassLoader(); activity=mInstrumentation.newActivity( cl,component.getClassName(),r.intent); r.intent.setExtrasClassLoader(cl); if(r.state!=null){ r.state.setClassLoader(cl); } }catch(Exceptione){ ...... } try{ Applicationapp=r.packageInfo.makeApplication(false,mInstrumentation); ...... if(activity!=null){ ContextImplappContext=newContextImpl(); appContext.init(r.packageInfo,r.token,this); appContext.setOuterContext(activity); CharSequencetitle=r.activityInfo.loadLabel(appContext.getPackageManager()); Configurationconfig=newConfiguration(mConfiguration); ...... activity.attach(appContext,this,getInstrumentation(),r.token, r.ident,app,r.intent,r.activityInfo,title,r.parent, r.embeddedID,r.lastNonConfigurationInstance, r.lastNonConfigurationChildInstances,config); if(customIntent!=null){ activity.mIntent=customIntent; } r.lastNonConfigurationInstance=null; r.lastNonConfigurationChildInstances=null; activity.mStartedActivity=false; inttheme=r.activityInfo.getThemeResource(); if(theme!=0){ activity.setTheme(theme); } activity.mCalled=false; mInstrumentation.callActivityOnCreate(activity,r.state); ...... r.activity=activity; r.stopped=true; if(!r.activity.mFinished){ activity.performStart(); r.stopped=false; } if(!r.activity.mFinished){ if(r.state!=null){ mInstrumentation.callActivityOnRestoreInstanceState(activity,r.state); } } if(!r.activity.mFinished){ activity.mCalled=false; mInstrumentation.callActivityOnPostCreate(activity,r.state); if(!activity.mCalled){ thrownewSuperNotCalledException( "Activity"+r.intent.getComponent().toShortString()+ "didnotcallthroughtosuper.onPostCreate()"); } } } r.paused=true; mActivities.put(r.token,r); }catch(SuperNotCalledExceptione){ ...... }catch(Exceptione){ ...... } returnactivity; } ...... } 函数前面是收集要启动的Activity的相关信息,主要package和component信息: ActivityInfoaInfo=r.activityInfo; if(r.packageInfo==null){ r.packageInfo=getPackageInfo(aInfo.applicationInfo, Context.CONTEXT_INCLUDE_CODE); } ComponentNamecomponent=r.intent.getComponent(); if(component==null){ component=r.intent.resolveActivity( mInitialApplication.getPackageManager()); r.intent.setComponent(component); } if(r.activityInfo.targetActivity!=null){ component=newComponentName(r.activityInfo.packageName, r.activityInfo.targetActivity); } 然后通过ClassLoader将shy.luo.activity.MainActivity类加载进来: Activityactivity=null; try{ java.lang.ClassLoadercl=r.packageInfo.getClassLoader(); activity=mInstrumentation.newActivity( cl,component.getClassName(),r.intent); r.intent.setExtrasClassLoader(cl); if(r.state!=null){ r.state.setClassLoader(cl); } }catch(Exceptione){ ...... } 接下来是创建Application对象,这是根据AndroidManifest.xml配置文件中的Application标签的信息来创建的: Applicationapp=r.packageInfo.makeApplication(false,mInstrumentation); 后面的代码主要创建Activity的上下文信息,并通过attach方法将这些上下文信息设置到MainActivity中去: activity.attach(appContext,this,getInstrumentation(),r.token, r.ident,app,r.intent,r.activityInfo,title,r.parent, r.embeddedID,r.lastNonConfigurationInstance, r.lastNonConfigurationChildInstances,config); 最后还要调用MainActivity的onCreate函数: mInstrumentation.callActivityOnCreate(activity,r.state); 这里不是直接调用MainActivity的onCreate函数,而是通过mInstrumentation的callActivityOnCreate函数来间接调用,前面我们说过,mInstrumentation在这里的作用是监控Activity与系统的交互操作,相当于是系统运行日志。 本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/965992,如需转载请自行联系原作者

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

【Andrioid】在Gradle编译时生成一个不同的版本号,动态设置应用程序标题,应用程序图标,更换常数

写项目的时候常常会遇到下面的情况: 1.须要生成測试版本号和正式版本号的apk 2.測试版本号和正式版本号的URL是不一样的 3.測试版本号和正式版本号的包名须要不一致,这样才干安装到同一部手机上面。 4.不同apk须要应用名不同,图标不同,某些常量不同.... 假设你有以上的需求。看这篇文章就对了 When developing an app, you usually have many slightly different versions of this app. The most common example is probably the backend you want to use:productionorstaging. 当我们做开发的时候。常常会须要生成多个版本号的app。 最常见的就是測试版和正式版。 You usually define the base URLs with the other constants of the app. Switching from one environment to the other is done by (un)commenting the right lines: 我们经常须要在应用中定义一些常量,当应用正式公布的时候,经常是凝视掉測试用的部分,放开正式的部分,就像以下一样: public static String BASE_URL = "http://staging.tamere.be" //public static String BASE_URL = "http://production.tamere.be" The process is manual, boring and error prone but hey, changing one line is not that bad, is it? Then you add more and more features that depends on the environment. You maybe want a different icon and then different input validation rules and then ... That's where your build tool can help. Let's see how we can automate the process of generating different APKs for different environment with Gradle. 上面的步骤是烦躁。无味的,改动一个地方还好。代码写多了以后正过来整过去就egg_pain了,这个时候我们Gragle就闪亮登场了 Build variants Gradle has the concepts ofBuild TypesandBuild Flavors. When combining the two, you get aBuild Variant. There two default build types:releaseanddebug. We won't change them in our example but we will create two new flavors:productionandstaging. Gradle默认有release和debug两个版本号。 我们这里添加了production和staging.两两组合就是以下4个版本号了。 As a result, we'll have four different variants: ProductionDebug ProductionRelease StagingDebug StagingRelease Sample project 演示样例项目 The project is pretty simple but shows how you can define for each build variant: an app name an icon constants (in our case aBASE_URLvariable) You can download the project onGithub. Here are two screenshots of the generated apps. Nothing really fancy: 演示样例项目非常easy。在不同的版本号中我们须要改动项目名称。项目图标,一些常量:url...,项目能够从Github下载,效果图例如以下: build.gradle file buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:0.5.+' } } apply plugin: 'android' repositories { mavenCentral() } android { compileSdkVersion 18 buildToolsVersion "18.0.1" defaultConfig { minSdkVersion 15 targetSdkVersion 18 } productFlavors { production { packageName "be.tamere.gradlebuildtypesexample" } staging { packageName "be.tamere.gradlebuildtypesexample.staging" } } } dependencies { compile 'com.android.support:appcompat-v7:18.0.0' } The definition of the flavors is super simple, all the magic will happen in their folders. 改动非常easy:核心配置是productFlavors,同一时候须要注意production和staging。它们须要与后面的文件夹结构名字一致 File structure 改动后的文件结构 In thesrcfolder, we've created two directories whose names must match the flavors. We will define all the flavor-specific values. Only specific values are necessary. 改动也比較简单,在src以下(main同级的文件夹)新建和上面productFlavors中配置production和staging同样的文件夹,分别放入相应的Constants.java。这两个文件夹的属性和功能与系统默认创建的main是一样的。 总结一下就是: 1.production和staging两个文件夹,相应着各存放一份Constants.java 2.对于应用图标和应用名字信息配置在res文件夹以下的。这个地方针对staging又一次配置了一份ic_launcher.png和string.xml。production没配置的话就是用默认main以下的res。 这个比較easy理解哈。 The staging version defines new icons while both flavors defines aConstants.java. The app name is defined in thestring.xmlfiles. ├── main │ ├── AndroidManifest.xml │ ├── ic_launcher-web.png │ ├── java │ │ └── be │ │ └── tamere │ │ └── gradlebuildtypesexample │ │ └── MainActivity.java │ └── res │ ├── drawable-hdpi │ │ └── ic_launcher.png │ ├── drawable-mdpi │ │ └── ic_launcher.png │ ├── drawable-xhdpi │ │ └── ic_launcher.png │ ├── drawable-xxhdpi │ │ └── ic_launcher.png │ ├── layout │ │ └── activity_main.xml │ ├── menu │ │ └── main.xml │ ├── values │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ ├── values-v11 │ │ └── styles.xml │ └── values-v14 │ └── styles.xml ├── production │ └── java │ └── be │ └── tamere │ └── gradlebuildtypesexample │ └── Constants.java └── staging ├── java │ └── be │ └── tamere │ └── gradlebuildtypesexample │ └── Constants.java └── res ├── drawable-hdpi │ └── ic_launcher.png ├── drawable-mdpi │ └── ic_launcher.png ├── drawable-xhdpi │ └── ic_launcher.png ├── drawable-xxhdpi │ └── ic_launcher.png └── values └── string.xml Android Studio You can switch between the two flavors in theBuild variantstab of the IDE. Android Studio has some trouble identifying the resources for a non-active flavors. We are using theproductionflavor, Studio does not understand that thestagingfolder contains source code. Don't worry, it's normal, it will catch up when you switch to the staging variant. Launch the app with the different flavors to see the result. The app drawer shows the two icons: References http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Product-flavors Xav's answer on thisStack overflow topicis particularly helpful. 原文地址: http://tulipemoutarde.be/2013/10/06/gradle-build-variants-for-your-android-project.html 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4734552.html,如需转载请自行联系原作者

资源下载

更多资源
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应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

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

用户登录
用户注册