安卓面试基础知识总结_第1页
安卓面试基础知识总结_第2页
安卓面试基础知识总结_第3页
安卓面试基础知识总结_第4页
安卓面试基础知识总结_第5页
已阅读5页,还剩28页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、1 Activity1.1 Activity的概念是Android应用层开发的四大组件之一,主要负责和用户交互部分,有自己的生命周期,在其上可以布置按钮,文本框等各种控件,简单来说就是Android的UI部分。1.2 Activity与View的区别1) Activity是四大组件中唯一一个用来和用户进行交互的组件。可以说Activity就是android的视图层。2) 如果再细化,Activity相当于视图层中的控制层,是用来控制和管理View的,真正用来显示和处理事件的实际上是View。3) 每个Activity内部都有一个Window对象, Window对象包含了一个DecorView(

2、实际上就是FrameLayout),我们通过setContentView给Activity设置显示的View实际上都是加到了DecorView中。1.3 Activity生命周期1.3.1 生命周期主干方法描述可被杀死下一个onCreate()在Activity第一次被创建的时候被调用。这里是你做所有初始化设置的地方创建视图、绑定数据至列表等。如果曾经有状态记录(参阅后述SavingActivityState。),则调用此方法时会传入一个包含着此activity以前状态的包对象做为参数否onStart()onStart()在Activity正要变得为用户所见时被调用。数据刷新时候调用!当Act

3、ivity转向前台时接着调用onResume()在Activity变为隐藏时接着知行onStop()否onResume()onStop()onResume()在Activity开始与用户进行交互之前被调用。此时Activity位于堆栈顶部,并接收用户输入。否onPause()Activity runActivity开始运行onPasue()当系统将要启动另一个 Activity时调用。此方法主要用来将未保存的变化进行持久化,停止类似动画这样耗费CPU的动作等。这一切动作应该在短时间内完成,因为下一个Activity必须等到此方法返回后才会继续。当Activity重新回到前台会执行onResum

4、e()【弹出对话框】。当Activity变为用户不可见时会执行onStop()。是onResume()onStop()onStop()当Activity不再为用户可见时调用此方法。这可能发生在它被销毁或者另一个Activity(可能是现存的或者是新的)回到运行状态并覆盖了它。如果Activity再次回到前台跟用户交互则执行onRestart().如果关闭Activity则执行onDestroy()是onRestart()onDestroy()onDestroy()在Activity销毁前调用。这是Activity接收的最后一个调用。这可能发生在Activity结束(调用了它的finish()方

5、法)或因为系统需要空间所以临时的销毁了此Activity的实例时。可以用isFinishing()方法来区分这两种情况。是已经完蛋了,还调用毛线!1.3.2 其他中转方法onRestart()在Activity停止后,在再次启动之前被调用。之后执行onStart().否onStart()1.4 Activity启动模式1.4.1 四种启动模式standard默认模式,可以不用写配置。在这个模式下,都会默认创建一个新的实例。因此,在这种模式下,可以有多个相同的实例,也允许多个相同Activity叠加。singleTop可以有多个实例,但是不允许多个相同Activity叠加。即,如果Activit

6、y在栈顶的时候,启动相同的Activity,不会创建新的实例,而会调用其onNewIntent方法。singleTask只有一个实例。在同一个应用程序中启动它的时候,若Activity不存在,则会在当前task创建一个新的实例,若存在,则会把task中在其之上的其它Activity destory掉并调用它的onNewIntent方法。如果是在别的应用程序中启动它,则会新建一个task,并在该task中启动这个Activity,singleTask允许别的Activity与其在一个task中共存,也就是说,如果我在这个singleTask的实例中再打开新的Activity,这个新的Activi

7、ty还是会在singleTask的实例的task中。singleInstance只有一个实例,并且这个实例独立运行在一个task中,这个task只有这个实例,不允许有别的Activity存在。1.4.2 配置样例1.5 Activity启动方法1) 在一个Activity中调用startActivity()方法。直接启动Activity,不带请求码。2) 在一个Activity中调用startActivityForResult()方法。带请求码启动Activity。1.6 请求码与响应码请求码(RequestCode)在一个业务中可能在两个按钮被单击事件中打开同一个Activity,但我们在o

8、nActivityResult事件中如何判断是哪个按钮打开了新的Activity?请求码就是为解决这个问题的,那么我们打开新的Activity时应该使用startActivityForResult(intent, 1);。其中的第二个参数就是请求码。结果码(ResultCode)在一个业务中可能要打开多个不同的Activity,那关闭Activity时在onActivityResult事件中我们如何知道关闭的是哪一个Activity呢?结果码就是为解决这个问题的,那么我们打开新的Activity时应该使用setResult(2, intent);或在关闭Activity前调用ActivityO

9、bj.setResult(2);。其中的第一个参数就是结果码。在onActivityResult事件中,通过判断resultCode更可知道是哪个Activity被关闭了。2 BroadcastReceiver2.1 概念BroadcastReceiver也就是“广播接收者”的意思,顾名思义,它就是用来接收来自系统和应用中的广播。2.2 应用场景在Android系统中,广播体现在方方面面:eg:1. 当开机完成后系统会产生一条广播,接收到这条广播就能实现开机启动服务的功能;2. 当锁屏或者点亮屏幕时就会产生一条广播,接收这条广播就可以实现一些暂停或者开启一些耗电进程的功能。3. 当网络状态改变

10、时系统会产生一条广播,接收到这条广播就能及时地做出提示和保存数据等操作;4. 当电池电量改变时,系统会产生一条广播,接收到这条广播就能在电量低时告知用户及时保存进度;2.3 注册2.3.1 静态注册 概念静态注册是在AndroidManifest.xml文件中配置的。2.3.2 动态注册 概念动态注册需要在代码中动态的指定广播地址并注册。 需要注意的事项RegisterReceiver是android.content.ContextWrapper类中的方法,Activity和Service都继承了ContextWrapper,所以可以直接调用。在实际应

11、用中,我们在Activity或Service中注册了一个BroadcastReceiver,当这个Activity或Service被销毁时如果没有解除注册,系统会报一个异常,提示我们是否忘记解除注册了。所以,需要在特定的地方执行解除注册操作:生命周期的onDestroy()。有部分广播接受者,涉及到用户的敏感内容,需要在权限文件中声明。如开机完成的广播,用户电量变化的广播,用户网络状态发生改变的广播2.3.3 生命周期1. 广播接收者的生命周期是非常短暂的,在接收到广播的时候创建,onReceive()方法结束之后销毁2. 广播接收者中不要做一些耗时的工作,否则会弹出Application N

12、o Response错误对话框3. 最好也不要在广播接收者中创建子线程做耗时的工作,因为广播接收者被销毁后进程就成为了空进程,很容易被系统杀掉4. 耗时的较长的工作最好放在服务中完成3 Service3.1 概念服务是看不到界面的,,就是一个没有界面的Activity, 并且长期在后台运行的一个组件.。3.2 为什么用服务?进程优先级, 回收时是从51, 从低到高Foreground process 前台进程Visible process 可视进程Service process 服务进程Background process 后台进程Empty process 空进程回收的优先级: 先回收空进程

13、, 一个一个回收的, 当内存够用时, 不再回收空进程. 如果空进程回收完毕后, 内存还是不够用时, 继续向上一个一个的回收后台进程. 依次类推.当系统内存不够用时, 需要回收服务进程时, 当系统内存又够用时, 会重新启动服务. 当用户去手动的把服务关闭时, 服务不会再重启了3.3 作用由于ANR对Activity和BroadcastReceiver响应时间的限制(Activity对事件响应不超过5秒,BroadcastReceiver执行不超过10秒),使得在其中都不适合执行较耗时操作,这样像网络、数据库、复杂计算这类耗时操作的执行就需要一个组件来承担。Service作为Android四大组件

14、之一,其功能之一就是耗时操作的执行,主要功能如下:a. 执行需要长时间运行的操作,这个操作不与用户进行交互,如网络下载、大文件I/O、复杂计算、监听手机状态。b. 应用内或应用间数据通信,Android每个应用程序都在自己的dalvik虚拟机中运行,一个应用是不允许访问其他应用的内存信息的,为此Android引入了Content Provider在不同应用间共享数据,BroadcastReceiver广播信息给不同应用程序,但Content Provider更多用于数据的共享,BroadcastReceiver广播的信息会被所有应用接收较耗费系统资源,对于两个应用间动态的进行交互还需要通过Se

15、rvice来完成。3.4 启动方式3.4.1 直接启动Activity开启完服务后就不管服务了. Activity和服务没有关系. startService开启的服务,只有stopService可以关闭3.4.2 绑定启动绑定服务, 生命周期方法会执行: onUnbind - onDestory 服务销毁了.在activity中调用service中的方法.步骤:调用bindService方法绑定服务1. 在Activity中定义一个连接桥的内部类, 会在bindService方法传递给service.2. 在service服务中onBind方法中返回一个IBinder接口对象.3. 在serv

16、ice类中定义一个IBinder的内部实现类, 在onBind方法返回.4. 当onBinder方法返回完对象后, activity中连接桥里的onServiceConnected会被调用, 其中形参IBinder service就是service类中onBind返回的对象.5. activity得到了service中的内部类对象, 点击按钮是调用内部类中的forwardBuyTicket方法, 此方法会转调服务中buyTicket方法.3.5 生命周期Service的生命周期(适用于2.1及以上)1.被startService的无论是否有任何活动绑定到该Service,都在后台运行。onCr

17、eate(若需要) - onStart(int id, Bundle args).多次startService,则onStart调用多次,但不会创建多个Service实例,只需要一次stop。该Service一直后台运行,直到stopService或者自己的stopSelf()或者资源不足由平台结束。2.被bindService的调用bindService绑定,连接建立服务一直运行。未被startService只是BindService,则onCreate()执行,onStart(int,Bund,le)不被调用;这种情况下绑定被解除,平台就可以清除该Service(连接销毁后,会导致解除,解

18、除后就会销毁)。3.被启动又被绑定类似startService的生命周期,onCreate onStart都会调用。4.停止服务时stopService时显式onDestroy()。或不再有绑定(没有启动时)时隐式调用。有bind情况下stopService()不起作用。4 ContentProvider 4.1 ContentProvider 数据库在Android当中是私有的,当然这些数据包括文件数据和数据库数据以及一些其他类型的数据。 不能将数据库设为WORLD_READABLE,每个数据库都只能创建它的包访问, 这意味着只有由创建数据库的进程可访问它。如果需要在进程间传递数据, 则可以

19、使用AIDL/Binder或创建一个ContentProvider,但是不能跨越进程/包边界直接来使用数据库。 一个Content Provider类实现了一组标准的方法接口,从而能够让其他的应用保存或读取此Content Provider的各种数据类型。 也就是说,一个程序可以通过实现一个Content Provider的抽象接口将自己的数据暴露出去。 外界根本看不到,也不用看到这个应用暴露的数据在应用当中是如何存储的,或者是用数据库存储还是用文件存储,还是通过网上获得,这些一切都不重要, 重要的是外界可以通过这一套标准及统一的接口和程序里的数据打交道,可以读取程序的数据,也可以删除程序的数

20、据, 当然,中间也会涉及一些权限的问题。下边列举一些较常见的接口,这些接口如下所示。 query(Uri uri, String projection, String selection, String selectionArgs,String sortOrder):通过Uri进行查询,返回一个Cursor。 insert(Uri url, ContentValues values):将一组数据插入到Uri 指定的地方。 update(Uri uri, ContentValues values, String where, String selectionArgs):更新Uri指定位置的数据。

21、 delete(Uri url, String where, String selectionArgs):删除指定Uri并且符合一定条件的数据。4.2 ContentResolver外界的程序通过ContentResolver接口可以访问ContentProvider提供的数据,在Activity当中通过getContentResolver()可以得到当前应用的 ContentResolver实例。 ContentResolver提供的接口和ContentProvider中需要实现的接口对应,主要有以下几个。 query(Uri uri, String projection, String s

22、election, String selectionArgs,String sortOrder):通过Uri进行查询,返回一个Cursor。 insert(Uri url, ContentValues values):将一组数据插入到Uri 指定的地方。 update(Uri uri, ContentValues values, String where, String selectionArgs):更新Uri指定位置的数据。 delete(Uri url, String where, String selectionArgs):删除指定Uri并且符合一定条件的数据。4.3 ContentOb

23、server在注册,翻译成中文就是内容观察者,目的是观察(捕捉)特定Uri引起的数据库的变化,继而做一些相应的处理。ContentObserver一般和系统或第三方程序提供的Provider一起使用,这些Provider一般情况下会有一个Uri,然后ContentObserver就去监听这些Uri数据的变化,然后做出相应的处理。4.4 ContentProvider和ContentResolver中用到的Uri在ContentProvider和 ContentResolver当中用到了Uri的形式通常有两种,一种是指定全部数据,另一种是指定某个ID的数据。我们看下面的例子。 content:/

24、contacts/people/ 这个Uri指定的就是全部的联系人数据。 content:/contacts/people/1 这个Uri指定的是ID为1的联系人的数据。 在上边两个类中用到的Uri一般由3部分组成。 第一部分是方案:content:/ 这部分永远不变 第二部分是授权:contacts 第二部分是路径:people/,people/1(如果没有指定ID,那么表示返回全部)。由于URI通常比较长,而且有时候容易出错,且难以理解。所以,在Android当中定义了一些辅助类,并且定义了一些常量来代替这些长字符串的使用,例如下边的代码:Contacts.People.CONTENT_U

25、RI (联系人的URI)。在我们的实例MyProvider中是如下定义的:public static final String AUTHORITY=com.teleca.PeopleProvider;public static final String PATH_SINGLE=people/#;public static final String PATH_MULTIPLE=people;public static final Uri content_URI=Uri.parse(content:/+AUTHORITY+/+PATH_MULTIPLE);5 Service如何向Activity传

26、递数据一个Android程序可以由多个Activity和Servier组成,在这些程序组件之间传递数据的方法有以下几种,每种方法都有其特定的使用途径。5.1 原始数据类型在Activity/Servier之间传递临时性的原始数据,可以使用Intent的putExtras方法来传递数据。若传递的数据需要长久保存,则使用SharedPreference类来完成。5.2 传递对象当在Activity/Servier之间传递不需要长久保存的对象时,可以使用以下几种途径:(1)通过Application类,每个Android应用程序都有一个Application类。当你在程序的AndroidManife

27、st.xml中给Application设定一个名字时,你的程序中就必须有一个Application的子类。这个Application子类会被Android自动实例化,并且是一个全局性的类,它的生命周期和程序的生命周期相同,你可以把一些全局性的对象保存在Application类中。Application类可以通过getApplication()获得。(2)通过HashMap of WeakReferences传递对象。当一个Activity需要向另外一个Activity传递对象时,可以使用一个关键字把对象存在一个HashMap中,并把这个关键字通过Internt的Extras发给目标Activi

28、ty,目标Activity接到该关键字后使用该关键字把对象从HashMap中取出。5.3 在Activity/Service之间传递需要长久保存的对象时,可以使用以下的方式1. Application Preferences2. Files3. contentProviders4. SQLite DB6 AsyncTask 6.1 底层处理底层使用本地线程池机制:1. 核心线程数:线程池中保存的线程数,包括空闲线程,默认为5个2. 线程池中允许的最大线程数,固定为128个+10个阻塞线程3. 当线程数大于核心线程数时,如果线程池中中线程数大于核心线程数5超过一秒事,终止多余的线程,保留五个核心

29、线程数。4. 执行前用于保持任务的队列,此队列仅保持execute方法提交的Runnable任务,固定容量为105. 执行程序创建新线程时使用的工厂6.2 AsyncTask介绍Android的AsyncTask比Handler更轻量级一些(只是代码上轻量一些,而实际上要比handler更耗资源),适用于简单的异步处理。首先明确Android之所以有Handler和AsyncTask,都是为了不阻塞主线程(UI线程),且UI的更新只能在主线程中完成,因此异步处理是不可避免的。 Android为了降低这个开发难度,提供了AsyncTask。AsyncTask就是一个封装过的后台任务类,顾名思义就

30、是异步任务。AsyncTask直接继承于Object类,位置为android.os.AsyncTask。要使用AsyncTask工作我们要提供三个泛型参数,并重载几个方法(至少重载一个)。 AsyncTask定义了三种泛型类型 Params,Progress和Result。Params 启动任务执行的输入参数,比如HTTP请求的URL。Progress 后台任务执行的百分比。Result 后台执行任务最终返回的结果,比如String。使用过AsyncTask 的同学都知道一个异步加载数据最少要重写以下这两个方法:doInBackground(Params) 后台执行,比较耗时的操作都可以放在这

31、里。注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress)来更新任务的进度。onPostExecute(Result) 相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回有必要的话你还得重写以下这三个方法,但不是必须的:onProgressUpdate(Progress) 可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。onPreExecute()这里

32、是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。onCancelled() 用户调用取消时,要做的操作使用AsyncTask类,以下是几条必须遵守的准则:Task的实例必须在UI thread中创建;execute方法必须在UI thread中调用;不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params.), onProgressUpdate(Progress.)这几个方法;该task只能被执行一次,否则多次调用时将会出现异常;6.3 AsyncTask实现的原理和适用的优

33、缺点AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程.使用的优点:简单,快捷过程可控 使用的缺点:在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来.7 Handler7.1 Handler异步实现的原理和适用的优缺点1. Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的MessageQueue(消息队列)。 2. Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Me

34、ssageQueue里;或者接收Looper从Message Queue取出)所送来的消息。3. Message Queue(消息队列):用来存放线程放入的消息。4. 线程:UIthread 通常就是main thread,而Android启动程序时会替它建立一个MessageQueue。在Handler 异步实现时,涉及到 Handler, Looper, Message, MessageQueue四个对象,实现异步的流程是主线程启动Thread(子线程)运行并生成Message放到MessageQueue,Looper从MessageQueue中获取Message并传递给Handler,H

35、andler逐个获取Looper中的Message,并进行UI变更。使用的优点:结构清晰,功能定义明确对于多个后台任务时,简单,清晰使用的缺点:在单个后台异步处理时,显得代码过多,结构过于复杂(相对性)7.2 Handler介绍Handler主要接受子线程发送的数据, 并用此数据配合主线程更新UI.当应用程序启动时,Android首先会开启一个主线程, 主线程为管理界面中的UI控件,进行事件分发,更新UI只能在主线程中更新,子线程中操作是危险的。这个时候,Handler就需要出来解决这个复杂的问题。由于Handler运行在主线程中(UI线程中),它与子线程可以通过Message对象来传递数据,

36、 这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传递)Message对象(里面包含数据), 把这些消息放入主线程队列中,配合主线程进行更新UI。7.3 Handler的特点Handler可以分发Message对象和Runnable对象到主线程中, 每个Handler实例,都会绑定到创建他的线程中,它有两个作用: (1)安排消息或Runnable 在某个主线程中某个地方执行 (2)安排一个动作在不同的线程中执行Handler中分发消息的一些方法post(Runnable)postAtTime(Runnable,long)postDelayed(Runna

37、ble long)sendEmptyMessage(int)sendMessage(Message)sendMessageAtTime(Message,long)sendMessageDelayed(Message,long)以上post类方法允许你排列一个Runnable对象到主线程队列中,sendMessage类方法, 允许你安排一个带数据的Message对象到队列中,等待更新.7.4 综上所述数据简单使用AsyncTask:实现代码简单,数据量多且复杂使用handler+thread :相比较AsyncTask来说能更好的利用系统资源且高效8 ListView8.1 ListView优化

38、8.1.1 简介在android开发中Listview是一个很重要的组件,它以列表的形式根据数据的长自适应展示具体内容,用户可以自由的定义listview每一列的布局,但当listview有大量的数据需要加载的时候,会占据大量内存,影响性能,这时候就需要按需填充并重新使用view来减少对象的创建。ListView加载数据都是在public View getView(int position, View convertView, ViewGroup parent) 方法中进行的(要自定义listview都需要重写listadapter:如BaseAdapter,SimpleAdapter,Cur

39、sorAdapter的等的getvView方法),优化listview的加载速度就要让convertView匹配列表类型,并最大程度上的重新使用convertView。8.1.2 getview的加载方法一般有以下三种种方式:1. 最慢的加载方式是每一次都重新定义一个View载入布局,再加载数据2. 正确的加载方式是当convertView不为空的时候直接重新使用convertView从而减少了很多不必要的View的创建,然后加载数据3. 最快的方式是定义一个ViewHolder,将convetView的tag设置为ViewHolder,不为空时重新使用即可8.1.3 补充当处理一些耗时的资源

40、加载的时候需要做到以下几点,以使你的加载更快更平滑:1. 适配器在界面主线程中进行修改2. 可以在任何地方获取数据但应该在另外一个地方请求数据3. 在主界面的线程中提交适配器的变化并调用notifyDataSetChanged()方法8.2 ListView的图文混合显示8.2.1 异步加载图片基本思想: 1.先从内存缓存中获取图片显示(内存缓冲) 2.获取不到的话从SD卡里获取(SD卡缓冲) 3.都获取不到的话从网络下载图片并保存到SD卡同时加入内存并显示(视情况看是否要显示) 8.2.2 具体优化优化一:先从内存中加载,没有则开启线程从SD卡或网络中获取,这里注意从SD卡获取图片是放在子线

41、程里执行的,否则快速滑屏的话会不够流畅。优化二:在adapter里新建一个busy变量,表示listview是否处于滑动状态,如果是滑动状态则仅从内存中获取图片,没有的话无需再开启线程去外存或网络获取图片。优化三:利用线程池在从网络获取图片时,先是将其保存到sd卡,然后再加载到内存,这么做的好处是在加载到内存时可以做个压缩处理,以减少图片所占内存资料与源码实现(见附件)8.2.3 关于图片错位的处理图片错位问题的本质源于我们的listview使用了缓存convertView,假设一种场景,一个listview一屏显示九个item,那么在拉出第十个item的时候,事实上该item是重复使用了第一

42、个item,也就是说在第一个item从网络中下载图片并最终要显示的时候其实该item已经不在当前显示区域内了,此时显示的后果将是在可能在第十个item上输出图像,这就导致了图片错位的问题。所以解决之道在于可见则显示,不可见则不显示。在ImageLoader里有个imageViews的map对象,就是用于保存当前显示区域图像对应的url集,在显示前判断处理一下即可。9 JNI9.1 快速智能开发步骤1. 配置NDK目录结构(只需一次)2. 添加本地支持:右键选中工程,Android ToolsAdd native support3. 将cpp代码改成c代码,注意Android.mk文件也要修改,

43、刷新工程,删除obj目录4. 声明本地方法,实现对应c代码实现:Javah+全类名 生成本地方法标头文件,把头文件剪切到jni目录下,c代码引用头文件,实现头文件里的方法。5. 实现对应的c代码6. 交叉编译,一锤子敲下去7. 使用静态代码块,引用库函数,调用方法9.2 开发中常见的JNI问题9.2.1 错误一10-31 06:42:33.645: E/AndroidRuntime(805): java.lang.UnsatisfiedLinkError: Native method not found: com.example.ndk2.MainActivity.hello_From_C:(

44、)Ljava/lang/String;1. 引入的函数库名字不对,或者没有引入2. java方法和c方法不对应3. 部署的平台有问题9.2.2 错误二当前工程报错,但是没有任何文件有错误,有可能Android.mk有问题在Android.mk文件中不要用到全角空格或者回车9.2.3 错误3在C代码中有编译时异常,在控制台上会提示9.2.4 错误410-31 06:53:23.165: A/libc(2075): Fatal signal 11 (SIGSEGV) at 0x476a415c (code=2), thread 2075 (om.example.ndk2)下面打印一大堆debug信

45、息C代码中有运行时异常9.3 应用场景1. 输出日志2. 收集用户反馈信息3. 用户登录4. 加密算法5. 电商数据加密10 静默安装10.1 方式一:定制ROMGoogle的安全策略要求任何应用应该提示APK安装包的权限,对于一些内置特定厂商应用,可以跳过安装过程的信息加快安装,或者运营商强制安装。10.2 方式二:查看系统源码10.2.1 基本原理在窗口中点击一个APK时,触发单击事件,PackageInstaller接收系统服务PackageManagerService传来的intent信息,传来的Intent信息中有APK的一些参数。实现的关键是区分一般APK和特定APK。通过传给Pa

46、ckageManagerService的intent中添加特别的参数,PackageInstaller接收后进行判断,进行特别的隐藏安装流程。这个实现只能通过程序调用的方式安装。 安装过程的信息窗口在PackageInstallActivity.java中实现的。安装过程的信息窗口有4个:需要实现一个PakkageInstallActivityHide.JAVA的文件,去掉下面的dialog和窗口安装权限确认窗口:installPermissionConfirm安装进度条:installProgress安装结果窗口:installResult安装错误提示对话框10.2.2 具体实现(方法一)1

47、. 在Androidmainfest.xml声明一个特定的intent:ent.action.VIEW.HIDE,由PackageInstallActivityHide.java来接受注意:2. 实现PakkageInstallActivityHide.java,UninstallerActivityHide.java。 只需把PakkageInstallActivity.java修改去掉dialog和对话框。3. 安装程序调用者发一个上面定义的intent即可。如下例子,静默安装/sdcard/hello.apk4. 卸载的方法类似。5. 注意,这个方法需要Packag

48、eInstall这个apk必须与系统一起编译。这个apk在/system/app/目录下面;ent.action.VIEW.HIDE 这个静默安装的接口需要开放给第三方。10.2.3 具体实现(方法二)1. 从模拟器Systemframework目录下提取framework.jar2. 将framework.jar后缀名改为zip,解压后提取其中的classes.dex文件3. 用dex2jar工具将classes.dex转成classes.dex.dex2jar.jar(注意新版本的dex2jar工具无法转换Android2.2的framework,建议使用dex2ja

49、r--SNAPSHOT,该工具可以从google官方站上下载到)4. 将classes.dex.dex2jar.jar改名为classes.dex.dex2jar.zip解压取出android/content/pm/目录下的PackageManager.class,IPackageInstallObserver.class,IPackageDeleteObserver.class及相关的几个class文件备用5. 找到android-sdk目录下的android.jar,改名为android.zip(注意改名前先备份一下),解压后将步骤4中取得的class文件覆盖到android

50、对应的目录下,6. 这个时候你的android.jar已经是一个更新过的SDK了,重新打开eclipse工程,你已经可以调用方法:void android.content.pm.PackageManager.installPackage(Uri packageURI, IPackageInstallObserver observer, int flags, String installerPackageName)11 Android中数据的存储方式11.1 方式1. Shared Preferences:主要用于保存程序的系统配置信息。用来存储“key-values paires”。一般用于保

51、存程序启动时设定的信息,以便在程序下一次启动时继续保留前一次设定的信息。2. xml3. Files:用文件的形式保存信息。可以通过对文件的读写来获取或保存相关信息。4. SQLite:用数据库的形式保存信息。SQLite是一个开源的数据库 系统。5. NetWork:将数据保存于网络。11.2 区别1. Shared Preferences:Android提供用来存储一些简单的配置信息的一种机制,例如,一些默认欢迎语、登录的用户名和密码等。其以键值对的方式存储,SharedPreferences是以XML的格式以文件的方式自动保存的,在DDMS中的File Explorer中展开到/data

52、/data/shared_prefs下,以上面这个为例,可以看到一个叫做SETTING_Infos.xml的文件2. Files在Android中,其提供了openFileInput 和 openFileOuput 方法读取设备上的文件,下面看个例子代码,具体如下所示:String FILE_NAME = tempfile.tmp; /确定要操作文件的文件名FileOutputStream fos = openFileOutput(FILE_NAME, Context.MODE_PRIVATE); /初始化FileInputStream fis = openFileInput(FILE_NAM

53、E); /创建写入流上述代码中两个方法只支持读取该应用目录下的文件,读取非其自身目录下的文件将会抛出异常。需要提醒的是,如果调用FileOutputStream 时指定的文件不存在,Android 会自动创建它。另外,在默认情况下,写入的时候会覆盖原文件内容,如果想把新写入的内容附加到原文件内容后,则可以指定其模式为Context.MODE_APPEND3. SQLiteSQLite是Android所带的一个标准的数据库,它支持SQL语句,它是一个轻量级的嵌入式数据库4. NetWork:将数据上传到网络补充: 1. Shared Preferences底层使用xml,xml也可以保存数据,但

54、是Shared Preferences只能保存键值对方式,xml能保存复杂数据2. Content provider底部还是使用了Sqlite数据库,也是算一种方式。12 什么是异步,什么是同步?分别在什么情况下使用? 比如:在子线程中执行数据加载,主线程中实现界面显示就是异步,这样界面可以先显示出来,在后台加载完数据再填充界面,而同步则是在一个线程中,如果数据没有加载完,那么界面就不会展示,两个任务必须按顺序执行. 异步适合加载网络数据,或者大量数据 同步适合多线程访问或修改同一个数据,要保证数据修改前后的一致性的时候使用.13 开发中遇到过哪些异常?是如何处理的?1. java.lang.

55、NullPointerException 异常的解释是程序遇上了空指针,简单地说就是调用了未经初始化的对象或者是不存在的对象,即把数组的初始化和数组元素的初始化混淆起来了。数组的初始化是对数组分配需要的空间,而初始化后的数组,其中的元素并没有实例化,依然是空的,所以还需要对每个元素都进行初始化(如果要调用的话)2. java.lang.OutOfMemoryError: bitmap size exceeds VM budget 自动把眼睛跳动到OOM异常看去3. java.lang.ClassNotFoundException异常的解释是指定的类不存在。4. java.lang.ArrayI

56、ndexOutOfBoundsException算法异常,一般是被0除,logcat中一般有提示;5. SQLException:操作数据库异常类,日志中一般会写出来执行什么语句有问题,直接从代码中查找即可;6. java.lang.IllegalArgumentException这个异常的解释是方法的参数错误,比如g.setColor(int red,int green,int blue)这个方法中的三个值,如果有超过的也会出现这个异常,因此一旦发现这个异常,我们要做的,就是赶紧去检查一下方法调用中的参数传递是不是出现了错误。7. java.lang.IllegalAccessException这个异常的解释是没有访问权限,当应用程序要调用一个类,但当前的方法即没有对

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论