您的位置:首页 > 职场人生

Android面试题(五) --重要

2016-03-15 11:35 405 查看
46. 注册广播有几种方式,这些方式有何优缺点?请谈谈 Android 引入广播机制的用意。
 Android 广播机制(两种注册方法) 在 android 下,要想接受广播信息,那么这个广播接收器就得我们自己来实现了,我们可以 继承 BroadcastReceiver,就可以有一个广播接受器了。有个接受器还不够,我们还得重写 BroadcastReceiver 里面的 onReceiver 方法,当来广播的时候我们要干什么,这就要我们自己 来实现,不过我们可以搞一个信息防火墙。具体的代码: public class SmsBroadCastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Bundle bundle = intent.getExtras(); Object[] object = (Object[])bundle.get("pdus"); SmsMessage sms[]=new SmsMessage[object.length]; for(int i=0;i<object.length;i++) { sms[0] = SmsMessage.createFromPdu((byte[])object[i]); Toast.makeText(context, "来自"+sms[i].getDisplayOriginatingAddress()+" 的消 息是:"+sms[i].getDisplayMessageBody(), Toast.LENGTH_SHORT).show(); } //终止广播, 在这里我们可以稍微处理, 根据用户输入的号码可以实现短信防火墙。 abortBroadcast(); } } 当实现了广播接收器,还要设置广播接收器接收广播信息的类型,这里是信息: android.provider.Telephony.SMS_RECEIVED 我们就可以把广播接收器注册到系统里面, 可以让系统知道我们有个广播接收器。 这里有 两种,一种是代码动态注册: //生成广播处理 smsBroadCastReceiver = new SmsBroadCastReceiver(); //实例化过滤器并设置要过滤的广播 IntentFilter intentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED"); //注册广播 BroadCastReceiverActivity.this.registerReceiver(smsBroadCastReceiver, intentFilter); 一种是在 AndroidManifest.xml 中配置广播 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="spl.broadCastReceiver" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".BroadCastReceiverActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!--广播注册--> <receiver android:name=".SmsBroadCastReceiver"> <intent-filter android:priority="20"> <action android:name="android.provider.Telephony.SMS_RECEIVED"/> </intent-filter> </receiver> </application> <uses-sdk android:minSdkVersion="7" /> <!-- 权限申请 --> <uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission> </manifest> 两种注册类型的区别是: 1)第一种不是常驻型广播,也就是说广播跟随程序的生命周期。 2)第二种是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系 统调用自动运行。

 

47. 请解释下在单线程模型中 Message、Handler、Message Queue、Looper 之间的关系。 Handler 简介: 一个 Handler 允许你发送和处理 Message 和 Runable 对象,这些对象和一个线程的 MessageQueue 相关联。 每一个线程实例和一个单独的线程以及该线程的 MessageQueue 相关 联。当你创建一个新的 Handler 时,它就和创建它的线程绑定在一起了。这里,线程我们也 可以理解为线程的 MessageQueue。从这一点上来看,Handler 把 Message 和 Runable 对象传 递给 MessageQueue,而且在这些对象离开 MessageQueue 时,Handler 负责执行他们。 Handler 有两个主要的用途: (1)确定在将来的某个时间点执行一个或者一些 Message 和 Runnable 对象。 (2)在其他线程(不是 Handler 绑定线程)中排入一些要执行的动作。 Scheduling Message,即(1) ,可以通过以下方法完成: post(Runnable):Runnable 在 handler 绑定的线程上执行,也就是说不创建新线程。 postAtTime(Runnable,long): postDelayed(Runnable,long): sendEmptyMessage(int): sendMessage(Message): sendMessageAtTime(Message,long): sendMessageDelayed(Message,long): post 这个动作让你把 Runnable 对象排入 MessageQueue,MessageQueue 受到这些消息的时候 执行他们,当然以一定的排序。sendMessage 这个动作允许你把 Message 对象排成队列,这 些 Message 对象包含一些信息, Handler 的 hanlerMessage(Message)会处理这些 Message.当然, handlerMessage(Message)必须由 Handler 的子类来重写。这是编程人员需要作的事。 当 posting 或者 sending 到一个 Hanler 时,你可以有三种行为:当 MessageQueue 准备好就处 理,定义一个延迟时间,定义一个精确的时间去处理。后两者允许你实现 timeout,tick,和基 于时间的行为。 当你的应用创建一个新的进程时,主线程(也就是 UI 线程)自带一个 MessageQueue,这个 MessageQueue 管理顶层的应用对象(像 activities,broadcast receivers 等)和主线程创建的窗 体。你可以创建自己的线程,并通过一个 Handler 和主线程进行通信。这和之前一样,通过 post 和 sendmessage 来完成,差别在于在哪一个线程中执行这么方法。在恰当的时候,给定 的 Runnable 和 Message 将在 Handler 的 MessageQueue 中被 Scheduled。 Message 简介: Message 类就是定义了一个信息,这个信息中包含一个描述符和任意的数据对象,这个信息 被用来传递给 Handler.Message 对象提供额外的两个 int 域和一个 Object 域,这可以让你在 大多数情况下不用作分配的动作。 尽管 Message 的构造函数是 public 的,但是获取 Message 实例的最好方法是调用 Message.obtain(),或者 Handler.obtainMessage()方法,这些方法会从回收对象池中获取一个。 MessageQueue 简介: 这是一个包含 message 列表的底层类。Looper 负责分发这些 message。Messages 并不是直接 加到一个 MessageQueue 中,而是通过 MessageQueue.IdleHandler 关联到 Looper。 你可以通过 Looper.myQueue()从当前线程中获取 MessageQueue。 Looper 简介: Looper 类被用来执行一个线程中的 message 循环。 默认情况, 没有一个消息循环关联到线程。 在线程中调用 prepare()创建一个 Looper,然后用 loop()来处理 messages,直到循环终止。 大多数和 message loop 的交互是通过 Handler。 下面是一个典型的带有 Looper 的线程实现。 class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); } }

 

48. AIDL 的全称是什么?如何工作?能处理哪些类型的数据? AIDL 的英文全称是 Android Interface Define Language 当 A 进程要去调用 B 进程中的 service 时,并实现通信,我们通常都是通过 AIDL 来操作的 A 工程: 首先我们在 net.blogjava.mobile.aidlservice 包中创建一个 RemoteService.aidl 文件,在里面我 们自定义一个接口, 含有方法 get。 ADT 插件会在 gen 目录下自动生成一个 RemoteService.java 文件,该类中含有一个名为 RemoteService.stub 的内部类,该内部类中含有 aidl 文件接口的 get 方法。 说明一:aidl 文件的位置不固定,可以任意 然后定义自己的 MyService 类,在 MyService 类中自定义一个内部类去继承 RemoteService.stub 这个内部类,实现 get 方法。在 onBind 方法中返回这个内部类的对象, 系统会自动将这个对象封装成 IBinder 对象,传递给他的调用者。 其次需要在 AndroidManifest.xml 文件中配置 MyService 类,代码如下: <!-- 注册服务 --> <service android:name=".MyService"> <intent-filter> <!-- 指定调用 AIDL 服务的 ID --> <action android:name="net.blogjava.mobile.aidlservice.RemoteService" /> </intent-filter> </service> 为什么要指定调用 AIDL 服务的 ID,就是要告诉外界 MyService 这个类能够被别的进程访问, 只要别的进程知道这个 ID,正是有了这个 ID,B 工程才能找到 A 工程实现通信。 说明:AIDL 并不需要权限 B 工程: 首先我们要将 A 工程中生成的 RemoteService.java 文件拷贝到 B 工程中,在 bindService 方法中绑定 aidl 服务 绑定 AIDL 服务就是将 RemoteService 的 ID 作为 intent 的 action 参数。 说明:如果我们单独将 RemoteService.aidl 文件放在一个包里,那个在我们将 gen 目 录下的该包拷贝到 B 工程中。如果我们将 RemoteService.aidl 文件和我们的其他类存放在一 起,那么我们在 B 工程中就要建立相应的包,以保证 RmoteService.java 文件的报名正确, 我们不能修改 RemoteService.java 文件 bindService(new Inten("net.blogjava.mobile.aidlservice.RemoteService"), serviceConnection, Context.BIND_AUTO_CREATE); ServiceConnection 的 onServiceConnected(ComponentName name, IBinder service)方法 中的 service 参数就是 A 工程中 MyService 类中继承了 RemoteService.stub 类的内部类的对象。

 

49. 请解释下 Android 程序运行时权限与文件系统权限的区别。 运行时权限 Dalvik( android 授权) 文件系统 linux 内核授权

 

50. 系统上安装了多种浏览器,能否指定某浏览器访问指定页面?请说明原由。 通过直接发送 Uri 把参数带过去,或者通过 manifest 里的 intentfilter 里的 data 属性 51. 你如何评价 Android 系统?优缺点。

 答:Android 平台手机 5 大优势:

 一、开放性 在优势方面,Android 平台首先就是其开发性,开发的平台允许任何移动终端厂商加入到 Android 联盟中来。 显著的开放性可以使其拥有更多的开发者, 随着用户和应用的日益丰富, 一个崭新的平台也将很快走向成熟。开放性对于 Android 的发展而言,有利于积累人气,这 里的人气包括消费者和厂商,而对于消费者来讲,随大的受益正是丰富的软件资源。开放的 平台也会带来更大竞争,如此一来,消费者将可以用更低的价位购得心仪的手机。

 二、挣脱运营商的束缚 在过去很长的一段时间,特别是在欧美地区,手机应用往往受到运营商制约,使用什么功能 接入什么网络,几乎都受到运营商的控制。从去年 iPhone 上市 ,用户可以更加方便地连接 网络, 运营商的制约减少。 随着 EDGE、 HSDPA 这些 2G 至 3G 移动网络的逐步过渡和提升, 手机随意接入网络已不是运营商口中的笑谈,当你可以通过手机 IM 软件方便地进行即时聊 天时,再回想不久前天价的彩信和图铃下载业务,是不是像噩梦一样?互联网巨头 Google 推动的 Android 终端天生就有网络特色,将让用户离互联网更近。

 三、丰富的硬件选择 这一点还是与 Android 平台的开放性相关,由于 Android 的开放性,众多的厂商会推出千奇 百怪,功能特色各具的多种产品。功能上的差异和特色,却不会影响到数据同步、甚至软件 的兼容,好比你从诺基亚 Symbian 风格手机 一下改用苹果 iPhone ,同时还可将 Symbian 中优秀的软件带到 iPhone 上使用、 联系人等资料更是可以方便地转移, 是不是非常方便呢?

 四、不受任何限制的开发商 Android 平台提供给第三方开发商一个十分宽泛、自由的环境,不会受到各种条条框框的阻 扰,可想而知,会有多少新颖别致的软件会诞生。但也有其两面性,血腥、暴力、情色方面 的程序和游戏如可控制正是留给 Android 难题之一。

 

 五、无缝结合的 Google 应用 如今叱诧互联网的 Google 已经走过 10 年度历史,从搜索巨人到全面的互联网渗透,Google 服务如地图、邮件、搜索等已经成为连接用户和互联网的重要纽带,而 Android 平台手机将 无缝结合这些优秀的 Google 服务。

 再说 Android 的 5 大不足:

 一、安全和隐私 由于手机 与互联网的紧密联系,个人隐私很难得到保守。除了上网过程中经意或不经意留 下的个人足迹,Google 这个巨人也时时站在你的身后,洞穿一切,因此,互联网的深入将 会带来新一轮的隐私危机。

 二、首先开卖 Android 手机的不是最大运营商 众所周知,T-Mobile 在 23 日,于美国纽约发布 了 Android 首款手机 G1。但是在北美市场, 最大的两家运营商乃 AT&T 和 Verizon, 而目前所知取得 Android 手机销售权的仅有 T-Mobile 和 Sprint,其中 T-Mobile 的 3G 网络相对于其他三家也要逊色不少,因此,用户可以买账购 买 G1,能否体验到最佳的 3G 网络服务则要另当别论了!

 三、运营商仍然能够影响到 Android 手机 在国内市场,不少用户对购得移动定制机不满,感觉所购的手机被人涂画了广告一般。这样 的情况在国外市场同样出现。Android 手机的另一发售运营商 Sprint 就将在其机型中内置其 手机商店程序。

 四、同类机型用户减少 在不少手机论坛都会有针对某一型号的子论坛, 对一款手机的使用心得交流, 并分享软件资 源。而对于 Android 平台手机,由于厂商丰富,产品类型多样,这样使用同一款机型的用户 越来越少,缺少统一机型的程序强化。举个稍显不当的例子,现在山寨机泛滥,品种各异, 就很少有专门针对某个型号山寨机的讨论和群组, 除了哪些功能异常抢眼、 颇受追捧的机型 以外。

五、过分依赖开发商缺少标准配置 在使用 PC 端的 Windows Xp 系统的时候,都会内置微软 Windows Media Player 这样一个浏 览器程序,用户可以选择更多样的播放器,如 Realplay 或暴风影音等。但入手开始使用默 认的程序同样可以应付多样的需要。在 Android 平台中,由于其开放性,软件更多依赖第 三方厂商,比如 Android 系统的 SDK 中就没有内置音乐 播放器,全部依赖第三方开发,缺 少了产品的统一性。

 

52. 什么是 ANR 如何避免它?

答:ANR:Application Not Responding,五秒 在 Android 中,活动管理器和窗口管理器这两个系统服务负责监视应用程序的响应。当出现 下列情况时,Android 就会显示 ANR 对话框了: 对输入事件(如按键、触摸屏事件)的响应超过 5 秒 意向接受器(intentReceiver)超过 10 秒钟仍未执行完毕 Android 应用程序完全运行在一个独立的线程中(例如 main)。这就意味着,任何在主线 程中运行的,需要消耗大量时间的操作都会引发 ANR。因为此时,你的应用程序已经没有 机会去响应输入事件和意向广播(Intent broadcast)。

 因此,任何运行在主线程中的方法,都要尽可能的只做少量的工作。特别是活动生命周 期中的重要方法如 onCreate()和 onResume()等更应如此。潜在的比较耗时的操作,

如访问 网络和数据库;或者是开销很大的计算,比如改变位图的大小,需要在一个单独的子线程中 完成(或者是使用异步请求,如数据库操作)。但这并不意味着你的主线程需要进入阻塞状态 已等待子线程结束 -- 也不需要调用 Therad.wait()或者 Thread.sleep()方法。 取而代之的是, 主线程为子线程提供一个句柄(Handler), 让子线程在即将结束的时候调用它(xing:可以参看 Snake 的例子,这种方法与以前我们所接触的有所不同)。使用这种方法涉及你的应用程序, 能够保证你的程序对输入保持良好的响应, 从而避免因为输入事件超过 5 秒钟不被处理而产 生的 ANR。这种实践需要应用到所有显示用户界面的线程,因为他们都面临着同样的超时 问题。

 

53. 什么情况会导致 Force Close ?如何避免?能否捕获导致其的异常?

 答:一般像空指针啊,可以看起 logcat,然后对应到程序中 来解决错误

 

 55. 简要解释一下 activity、 intent 、intent filter、service、Broadcase、BroadcaseReceiver

 答:一个 activity 呈现了一个用户可以操作的可视化用户界面 一个 service 不包含可见的用户界面,而是在后台无限地运行 可以连接到一个正在运行的服务中, 连接后, 可以通过服务中暴露出来的借口与其进行 通信 一个 broadcast receiver 是一个接收广播消息并作出回应的 component,broadcast receiver 没有界面 intent:content provider 在接收到 ContentResolver 的请求时被激活。 activity, service 和 broadcast receiver 是被称为 intents 的异步消息激活的。 一个 intent 是一个 Intent 对象,它保存了消息的内容。对于 activity 和 service 来说,它指 定了请求的操作名称和待操作数据的 URI Intent 对象可以显式的指定一个目标 component。如果这样的话,android 会找到这个 component(基于 manifest 文件中的声明)并激活它。但如果一个目标不是显式指定的, android 必须找到响应 intent 的最佳 component。 它是通过将 Intent 对象和目标的 intent filter 相比较来完成这一工作的。一个 component 的 intent filter 告诉 android 该 component 能处理的 intent。intent filter 也是在 manifest 文件中声明的。

 

56. IntentService 有何优点?

答:IntentService 的好处 * Acitivity 的进程,当处理 Intent 的时候,会产生一个对应的 Service * Android 的进程处理器现在会尽可能的不 kill 掉你 * 非常容易使用

 

57. 横竖屏切换时候 activity 的生命周期?

 1、不设置 Activity 的 android:configChanges 时,切屏会重新调用各个生命周期,切横 屏时会执行一次,切竖屏时会执行两次 2、设置 Activity 的 android:configChanges="orientation"时,切屏还是会重新调用各个 生命周期,切横、竖屏时只会执行一次 3、设置 Activity 的 android:configChanges="orientation|keyboardHidden"时,切屏不 会重新调用各个生命周期,只会执行 onConfigurationChanged 方法 如何将 SQLite 数据库(dictionary.db 文件)与 apk 文件一起发布? 解答:可以将 dictionary.db 文件复制到 Eclipse Android 工程中的 res aw 目录中。所有 在 res aw 目录中的文件不会被压缩,这样可以直接提取该目录中的文件。可以将 dictionary.db 文件复制到 res aw 目录中

 

58. 如何将打开 res aw 目录中的数据库文件?

 解答:在 Android 中不能直接打开 res aw 目录中的数据库文件,而需要在程序第一次 启动时将该文件复制到手机内存或 SD 卡的某个目录中,然后再打开该数据库文件。复制的 基本方法是使用 getResources().openRawResource 方法获得 res aw 目录中资源的 InputStream 对象,然后将该 InputStream 对象中的数据写入其他的目录中相应文件中。在 Android SDK 中可以使用 SQLiteDatabase.openOrCreateDatabase 方法来打开任意目录中的 SQLite 数据库文件。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: