1.什么是activity:
(1):界面显示:setContentView(layout布局文件),然后activity实现了OnClickListener,用户做操作我们就能收到用户操作的内容然后反馈给用户
(2)和用户进行交互:四大组件之一,作为一个界面的容器,一个可以与用户交互的界面,他能与用户交互是因为他是Context的子类,同时实现了window.callback(window.callback(窗口的回调事件)有一个dispatchTouchEvent事件,所以他能分发,既然window.callback他能分发事件,他就可以处理这些事件)和keyevent.callback(按键的回调事件,),可以处理与窗体交互的事件
servie也是Context的子类,但是他没有实现Window.callback(窗口回调事件)和keyevent.callback(按键的回调事件),所以他不能和用户交互
(3):开发举例说明:以前开发常用的有 FragmentActivity,ListActivity,PreferenceActivity,TabActivity等等,如果开发中遇到界面有共同的特点,布局大同小异,功能类似,我们就可以定义一个BaseActivity,这样代码优化比较好
为什么要使用fragment?
当我们需要动态的多节目切换时,就需要将ui元素和activity融合成一个模块.在2.3中我们一般通过各种activity中进行跳转来实现多界面的跳转和单个界面动态改变.在4.0或以上的系统中可以使用新的特性来方便的达到这个效果-fragment类.Fragment类似一个嵌套activity,可以定义自己的layout和自己的生命周期.
当一个fragment被创建的时候,他会经历以下状态
onAttach,onCreate,onCreateView,onActivityCreate
当这个fragment对用户可见的时候,他会经历以下状态
onStart,onResume
当这个fragment进入后台模式的时候,他会经历以下状态
onPause,onStop
当这个fragment被销毁(或者持有他的activity被销毁),他会经历以下状态
onPause,onStop,onDestroyView,onDestroy,onDetach
fragment的大部分状态和activity相似,但fragment都有一些新的状态
onAttached:当fragment被加入到activity的时候调用(这个方法可以获得所在的activity)
onCreateView:当activity要得到fragment的layout时,调用此方法
onActivityCreate:当activity的oncreate方法返回后调用此方法
onDestroyView:当fragm中的视图移除的时候调用此方法
onDetach:当fragment和activity分离的时候,调用这个方法
2.activity的生命周期:
activity的从出生(new)到死亡(垃圾回收)的过程,activity创建的时候是由frameWork new出来的,我们自己可以去newactivity,但是new了自己没法启动(就像servlet,我们自己虽然可以new,但是启动不了).activity被fragmentWork New出来之后,由他去管理activity的.
activity给我们提供了一系列的方法,然后在相应的方法做出相应的操作,这些方法括:onCreate,onDestroy,onstart,onstop,onresume,onpause,onRestart
这些方法都是两两对应的
onCreate():创建 onDestroy():销毁
onStart():可见 onStop():不可见
onresume():可编辑(获取焦点) onPause():不可编辑(失去焦点)
这6个方法都是相对应的,只剩下一个onRestart方法了,该方法在activity被onStop后,但是并没有被fragmentwork回收掉,在再次启动activity时,不再调用onCreate,而是调用onRestart
例子:比如我做一个商品界面,用户在点击某一个商品的时候,商品界面被按走,然后用户点击返回,我就在这个onRestart里面做对商品页面的数据操作,从网络再拿商品,然后做刷新操作,保证用户做了操作,能保证用户看到最新的数据
activity还有一些其他不常用的比如:onPostResume和onPostCreate
onPostResume:可见(onStart)完成以后框架也就是系统去回调 onPostResume方法,而不是我们去回调该方法
onPostCreate:创建完成之后框架(系统)回调此方法,自己实现了也不会去覆盖框架的该方法
3.2个activity之间的跳转必然会执行的方法:
一般情况分2种,
B完全覆盖住了A:activirt分别为A和B,当在A里面激活B组件的时候,A会调用onPause(不可编辑,失去焦点)方法,然后B调用oncreate(出生),onstart(可见),onRresume(可编辑)方法,这个时候B覆盖了窗体,A会调用onStop(不可见)方法,
B是透明的或者是个对话框:如果B是透明的,或者是对话框的样式,就不会调用onStop方法
4.横竖屏切换执行的生命周期方法
这个生命周期和清单文件的配置有关系
(1):不设置activity的android:configChanges时,切屏会重新调用各个生命周期方法,默认首先销毁当前的activity,然后重新加载,执行生命周期方法
(2):设置activity的android:configChanges="orientation|keyboardHidden|screenSize"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法
5.如何将一个activity设置成窗口的样式
1.可以在清单文件中配置activity的样式,设置成
android:theme="@android:style/Theme.DiaLog"
2.可以自己创建一个dialog,如何写一个布局文件,把布局文件当成一个dialog
6.你后台的activity被系统回收怎么办?如果后台的activity由于某种原因被系统回收了,如何在被系统回收之前保存当前状态
当activity处于不在前台界面显示,处于onPause或者onStop这2个状态的时候,activity不在内存栈的顶端,也是有可能被android回收的,
反正就是除了在栈顶的activity,其他activity都有可能在内存不足的时候被系统回收,activity越是在栈底越有可能被回收
当她们被系统回收,会调用onSaveInstanceState方法,你可以吧那些数据存取到outState里面,
@Override
protected void onSaveInstanceState(Bundle outState) {
//在activity被系统回收的时候,存取到outState路面
outState.putInt("1", 100);
super.onSaveInstanceState(outState);
}
在用户在下一次在即该activity的时候,就会调用onCreate方法
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
获取存取的数据
savedInstanceState.getInt("1");
}我们就可以从savedInstanceState里面获取activity被系统回收的时候存取的数据,如果手机以外死机了,那种超出了android所能管理的范围了我们可以每隔一段时候备份一份数据,这样即使死机了也不用担心数据丢失
7.如何退出activity?如何安全退出已调用多个activity的application?
退出activity直接调用finish()方法.用户点击back就是退出一个activity,退出activity会执行onDestory方法
1.抛异常强制退出
该方法通过抛异常,使程序force close,验证可以,但是需要解决的问题是:如何使程序结束掉,而不是弹出Fore Close的窗口
安全结束进程android.os.Process.KillProcess(android.os.Process.MyPid());
2.记录打开的activity
每打开一个activity,就记录下来,在需要退出的时候,关闭每一个activity
3.发送特定广播
在需要结束应用的时候,发送一个特定广播,每个activity收到广播,关闭即可
给某个activity注册接收广播的意图
registerReceiver(receiver,filter);
如果接收到的是关闭activity的广播,就调用finish()方法,把当前的activity finish掉
4.递归退出
在打开新的activity时使用startActivityForResult,然后自己加标志,在onActivityResult中处理,递推关闭
5.网上的做法
通过intent的flag实现,intent.setFlags(intent.FLAG_ACTIVITY_CLEAR_TOP)激活一个新的activity,在激活新的activity之前会把该栈中其他activity 杀死,然后在新的activity的oncreate方法中把自己finish掉就ok了
8.service是否在main thread中执行,service里面是否能执行耗时的操作?
默认情况,如果没有显示的指定servie所运行的进程,service和activity是运行在当前app所在的进程的main thread(UI主线程)里面的.
service里面不能执行耗时的操作(网络请求,拷贝数据库,大文件)
在子线程中执行new Thread(){}.start();
特殊情况可以在清单文件配置service执行所在的进程,让service在另外的进程中执行.注意
BroadcastReceiver(广播)的耗时时间为10秒
service的耗时为20秒
activity的耗时为5秒,
虽然servie不能做耗时操作但是service的子类intentservice可以做耗时操作
9.两个activity之间怎么传递数据?
由于android sdk限制,不能再调用activity时访问activity对象,因此,就不能像在普通对象之间传递数据一样通过构造方法或类成员传递数据.android提供了自己的数据传递方法,最常用的通过intent对象传递数据
可通过intent对象,静态常量,剪切板和全局对象进行数据传递
1.intent对象:
Intent intent=new Intent(this,MainActivity.class);
intent.putExtra("intent_integer", 300);
startActivity(intent);
2.静态常量
将类成员定义成putlic static就可以直接通过类成员来传递数据.使用静态变量可以传递任意类型的数据.
3.剪切板,可以利用android系统提供的剪切板存取数据.
Intent intent=new Intent(this,MainActivity.class);
//获取管理剪切板的对象
ClipboardManager manager=(ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
//向剪切板保存字符串
manager.setText("你好");
startActivity(intent);
//向剪切板获得数据
ClipboardManager clipboardManager=(ClipboardManager)
getSystemService(Context.CLIPBOARD_SERVICE);
//从剪切板获得字符串
String text=clipboardManager.getText().toString();
传递数据的限制:只能传递文本数据以及intent对象支持的数据
4.全局对象:可以为每一个应用程序定义一个全局的对象.该对象的创建由系统负责使用全局对象需要一个继承自application的类.并在该类中定义任何类型的成员变量和方法
public class MyApplication extends Application{
public String ountry;
public Data data=new Data();
}然后需要在androidMainfest.xml文件中定义该类
<application android:name="com.itheima.listview.MyApplication">
</application>
然后可以在应用程序的任何地方通过如下代码获取MyApplication对象
MyApplication application=(MyApplication) getApplicationContext();
虽然高版本的android允许剪切板保存intent支持的数据类型,但这并不适合所有的android版本.如果要考虑更多的android版本,除了要考虑狐狸剪切板代码的版本问题外,还可以直接使用字符串传递任何二进制的数据(包括可序列号的对象,图像)
将二进制数据转换字符串只需要将其编码(一般采用Base64编码)。例如下面的代码将一个可序列化对象转换成bSE64编码
Intent intent=new Intent(this,MainActivity.class);
//获取管理剪切板的对象
ClipboardManager manager=(ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
Data data=new Data();
data.id=6666;
data.name="通过Clipboard传递的数据";
//下面的代码将data对象转换成base64格式的字符串
ByteArrayOutputStream baos=new ByteArrayOutputStream();
String base64Str="";
try {
ObjectOutputStream oos=new ObjectOutputStream(baos);
oos.writeObject(data);
//使用base64.encodeToString方法将byte[]数据转换成base64字符串
base64Str=Base64.encodeToString(baos.toByteArray(),Base64.DEFAULT);
oos.close();
} catch (Exception e) {
// TODO: handle exception
}
//向剪切板保存字符串
manager.setText(base64Str);
startActivity(intent);
Intent intent=new Intent(this,MainActivity.class);
//获取管理剪切板的对象
ClipboardManager manager=(ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
Data data=new Data();
data.id=6666;
data.name="通过Clipboard传递的数据";
//下面的代码将data对象转换成base64格式的字符串
ByteArrayOutputStream baos=new ByteArrayOutputStream();
String base64Str="";
try {
ObjectOutputStream oos=new ObjectOutputStream(baos);
oos.writeObject(data);
//使用base64.encodeToString方法将byte[]数据转换成base64字符串
base64Str=Base64.encodeToString(baos.toByteArray(),Base64.DEFAULT);
oos.close();
} catch (Exception e) {
// TODO: handle exception
}
//向剪切板保存字符串
manager.setText(base64Str);
startActivity(intent);
10.怎么在启动一个activity的时候启动一个service
在activity的onCreate方法里面startService
在service启动activity:
在oncreate写如下代码
Intent dialogIntent = new Intent(getBaseContext(), YourActivity.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(dialogIntent);
11.同一个程序,但是不同的activity是否可以放在不同的task任务栈中?
singleInstance可以让每一个activity都对应一个任务栈
比方说在激活一个新的activity的时候,给intent设置flag,intent的flag添加FLAG_ACTIVITY_NEW_TASK,这个被激活的activity就会在新的task栈里面
Intent intent=new Intent(this,SendActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
12.activity怎么和service绑定,怎么在activity中启动自己对应的service?
startService:一旦创建service,该servie和activity就没有关系了,只有使用bindService(),他会把service和启动service的activity绑定,activity销毁,servie也会销毁
bindService我们可以使用service里面的方法
//创建服务
public class LeaderService extends Service{
@Override
public IBinder onBind(Intent intent) {
/*返回一个Binder对象,这个对象就是中间人对象用于调用服务对象里面自定义
* 的banZheng方法,否则是没法调用服务对象的自定义方法的
* */
return new ZhouMi();
}
继承binder,实现PublicBusiness接口方法## ##
class ZhouMi extends Binder implements PublicBusiness{
public void QianXian(){
banZheng();
}
}
public void banZheng(){
System.out.println("李处帮你来办证");
}
创建intent,设置服务
intent=new Intent(this,LeaderService.class);
//创建服务对外提供的接口对象
PublicBusiness pb;
//服务连接接口对象
class MyServiceConnection implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
接口对象赋值
pb=(PublicBusiness) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
}
//获取服务连接接口对象
msc=new MyServiceConnection();
//绑定领导服务
bindService(intent, msc,BIND_AUTO_CREATE);
这样就可以调用服务里面实现的接口方法了
13.什么是service以及描述下他的生命周期方法,Service有哪些启动方法,他们的区别,怎么停用Service?
什么是service: Service是运行在后台的android组件,没有用户界面,不能与用户交互,可以运行在自己的进程,也可以运行在其他应用程序的上下文里。
Service 与 Thread 的区别
很多时候,你可能会问,为什么要用 Service,而不用 Thread 呢,因为用 Thread 是很方便的,比起 Service 也方便多了,下面我详细的来解释一下。
1). Thread:Thread 是程序执行的最小单元,它是分配CPU的基本单位。可以用 Thread 来执行一些异步的操作。
2). Service:Service 是android的一种机制,当它运行的时候如果是Local Service,那么对应的 Service 是运行在主进程的 main 线程上的。如:onCreate,onStart 这些函数在被系统调用的时候都是在主进程的 main 线程上运行的。如果是Remote Service,那么对应的 Service 则是运行在独立进程的 main 线程上。因此请不要把 Service 理解成线程,它跟线程半毛钱的关系都没有!
既然这样,那么我们为什么要用 Service 呢?其实这跟 android 的系统机制有关,我们先拿 Thread 来说。Thread 的运行是独立于 Activity 的,也就是说当一个 Activity 被 finish 之后,如果你没有主动停止 Thread 或者 Thread 里的 run 方法没有执行完毕的话,Thread 也会一直执行。因此这里会出现一个问题:当 Activity 被 finish 之后,你不再持有该 Thread 的引用。另一方面,你没有办法在不同的 Activity 中对同一 Thread 进行控制。
举个例子:如果你的 Thread 需要不停地隔一段时间就要连接服务器做某种同步的话,该 Thread 需要在 Activity 没有start的时候也在运行。这个时候当你 start 一个 Activity 就没有办法在该 Activity 里面控制之前创建的 Thread。因此你便需要创建并启动一个 Service ,在 Service 里面创建、运行并控制该 Thread,这样便解决了该问题(因为任何 Activity 都可以控制同一 Service,而系统也只会创建一个对应 Service 的实例)。
因此你可以把 Service 想象成一种消息服务,而你可以在任何有 Context 的地方调用 Context.startService、Context.stopService、Context.bindService,Context.unbindService,来控制它,你也可以在 Service 里注册 BroadcastReceiver,在其他地方通过发送 broadcast 来控制它,当然这些都是 Thread 做不到的。
在service的生命周期中,被回调的方法比activity少一些,只有onCreate,onStart,OnDestroy,onBind和onUnBind,通常有2种方式启动一个service,他们的生命周期也是不一样的.
1.通过startService
service会经历onCreate,onStart,然后处于运行状态,stopServie的时候调用onDestroy.如果调用者没有stopService,那么该服务会一直运行在后台
2.通过bindServie
service会运行onCreate,然后调用onbindm这时候调用者和service绑定在一起,调用者退出了,service就会调用onUnbing和onDestroy
所谓的绑定就是共存亡了,调用者也可以通过onUnBintService方法停止服务这时候service就会调用onUnbind和onDestroy方法
需要注意的是如果这几个方法交织在一起回出问题的,一个原则是service的onCreate只会被调用一次,就是无论你绑定也好启动服务也好,service只会被创建一次
如果先是bind了,那么startService的时候就直接运行service的onStart方法,如果先startService方法,然后bingdService方法那么直接运行onBind方法
如果service运行期间调用了bindService,这时候在调用stopService的话,service是不会调用onDestroy方法的,servie是stop不掉了,只能调用unBindSefvie,service才会被销毁
如果一个servcie通过startService被start之后,多次调用startServcie的话,servie会多次调用onstart方法,多次调用stopService的话,service只会调用一次onDestroy方法
如果servie通过bindService被start之后,多次调用bindService的话,service只会调用一次onBind方法
多次调用unBindServie会抛异常
15.不用service,B页面为音乐播放器,从A跳到B,在返回,如何使音乐继续播放?
A跳转到B的时候,使用startActivityForResult(intent,10);去开启B,当用户在b界面按返回的键的时候,我们把音乐播放器的歌曲信息保存到intent里面,如使用setResult(1,intent)保存intent,然后在A界面重新写onActivityResult,获取保存的音乐信息,就可以在a界面继续播放音乐了.
16.什么是intentService?有什么优点?
普通的service,默认运行在ui main主线程,
sdk给我们提供了,带有异步处理的service里
intentService里面的onHandleIntent方法默认开启了一个
子线程,你在里面做任何耗时操作都没有问题
IntentService也是一个Service,是Service的子类;
IntentService和Service有所不同,通过Looper和Thread来解决标准Service中处理逻辑的阻塞的问题
优点:Activity的进程,当处理Intent的时候,会产生一个对应的Service,Android的进程处理器现在会尽可能的不kill掉你。
IntentService是Service类的子类,用来处理异步请求。客户端可以通过startService(Intent)方法传递请求给IntentService。IntentService在onCreate()函数中通过HandlerThread单独开启一个线程来处理所有Intent请求对象(通过startService的方式发送过来的)所对应的任务,这样以免事务处理阻塞主线程。执行完所一个Intent请求对象所对应的工作之后,如果没有新的Intent请求达到,则自动停止Service;否则执行下一个Intent请求所对应的任务。
IntentService在处理事务时,还是采用的Handler方式,创建一个名叫ServiceHandler的内部Handler,并把它直接绑定到HandlerThread所对应的子线程。 ServiceHandler把处理一个intent所对应的事务都封装到叫做onHandleIntent的虚函数;因此我们直接实现虚函数onHandleIntent,再在里面根据Intent的不同进行不同的事务处理就可以了。
另外,IntentService默认实现了Onbind()方法,返回值为null。
使用IntentService需要两个步骤:
1、写构造函数
2、实现虚函数onHandleIntent,并在里面根据Intent的不同进行不同的事务处理就可以了。
好处:处理异步请求的时候可以减少写代码的工作量,比较轻松地实现项目的需求
IntentService使用队列的方式将请求的Intent加入队列,然后开启一个worker thread(线程)来处理队列中的Intent,对于异步的startService请求,IntentService会处理完成一个之后再处理第二个,每一个请求都会在一个单独的worker thread中处理,不会阻塞应用程序的主线程,这里就给我们提供了一个思路,如果有耗时的操作与其在Service里面开启新线程还不如使用IntentService来处理耗时操作。
注意:IntentService的构造函数一定是参数为空的构造函数,然后再在其中调用super("name")这种形式的构造函数。
因为Service的实例化是系统来完成的,而且系统是用参数为空的构造函数来实例化Service的
缺点:不可以直接和UI做交互。为了把他执行的结果体现在UI上,需要发送给Activity。
工作任务队列是顺序执行的,如果一个任务正在IntentService中执行,此时你再发送一个任务请求,这个任务会一直等待直到前面一个任务执行完毕。
正在执行的任务无法打断
17.什么时候使用service?
startForeground(id, notification)
messenger
拥有service的进程具有较高的优先级
官方文档告诉我们,Android系统会尽量保持拥有service的进程运行,只要在该service已经被启动(start)或者客户端连接(bindService)到它。当内存不足时,需要保持,拥有service的进程具有较高的优先级。
1. 如果service正在调用onCreate, onStartCommand或者onDestory方法,那么用于当前service的进程相当于前台进程以避免被killed。
2. 如果当前service已经被启动(start),拥有它的进程则比那些用户可见的进程优先级低一些,但是比那些不可见的进程更重要,这就意味着service一般不会被killed.
3. 如果客户端已经连接到service (bindService),那么拥有Service的进程则拥有最高的优先级,可以认为service是可见的。
4. 如果service可以使用startForeground(int, Notification)方法来将service设置为前台状态,那么系统就认为是对用户可见的,并不会在内存不足时killed。
如果有其他的应用组件作为Service,Activity等运行在相同的进程中,那么将会增加该进程的重要性。
1.Service的特点可以让他在后台一直运行,可以在service里面创建线程去完成耗时的操作.
2.Broadcast receiver捕获到一个事件之后,可以起一个service来完成一个耗时的操作.
3.远程的service如果被启动起来,可以被多次bind, 但不会重新create. 索爱手机X10i的人脸识别的service可以被图库使用,可以被摄像机,照相机等程序使用.
18.描述一下Intent和intent filter
android通过intent对象来表示一条消息,一个intent对象不仅仅包含这个消息的目的地,还可以包含消息的内容,这就好比是一份email,其中不仅仅应该包含地址,还可以包含具体的内容.对于Intent,消息目的地是必须的,内容是可选的,通过intent可以实现各种系统组件的调整和激活
Intent filter: 可以理解为邮局或者是一个信笺的分拣系统…
这个分拣系统通过3个参数来识别
Action: 动作 view
Data: 数据uri uri
Category : 而外的附加信息
Action 匹配
Action 是一个用户定义的字符串,用于描述一个 Android 应用程序组件,一个 Intent Filter 可以包含多个 Action。在 AndroidManifest.xml 的 Activity 定义时可以在其 <intent-filter >节点指定一个 Action 列表用于标示 Activity 所能接受的“动作”,例如:
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<action android:name="cn.itcast.action" />
</intent-filter>
如果我们在启动一个 Activity 时使用这样的 Intent 对象:
Intent intent =new Intent();
intent.setAction("cn.itcast.action");
那么所有的 Action 列表中包含了“cn.itcast”的 Activity 都将会匹配成功。
Android 预定义了一系列的 Action 分别表示特定的系统动作。这些 Action 通过常量的方式定义在 android.content. Intent中,以“ACTION_”开头。我们可以在 Android 提供的文档中找到它们的详细说明。
URI 数据匹配
一个 Intent 可以通过 URI 携带外部数据给目标组件。在 <intent-filter >节点中,通过 <data/>节点匹配外部数据。
mimeType 属性指定携带外部数据的数据类型,scheme 指定协议,host、port、path 指定数据的位置、端口、和路径。如下:
<data android:mimeType="mimeType" android:scheme="scheme"
android:host="host" android:port="port" android:path="path"/>
电话的uri tel: 12345
http://www.baidu.com
自己定义的uri itcast://cn.itcast/person/10
如果在 Intent Filter 中指定了这些属性,那么只有所有的属性都匹配成功时 URI 数据匹配才会成功。
Category 类别匹配
<intent-filter >节点中可以为组件定义一个 Category 类别列表,当 Intent 中包含这个列表的所有项目时 Category 类别匹配才 会成功。
默认是DEFAULT
19. Intent传递数据时,可以传递哪些类型数据?
1.一般的基本数据类型 Intent .putextra() intent.getextra();
2.数据的uri, intent.setData() intent.getData();
20.说说activity,Intent,Service是什么关系
activity是界面,Service是后台服务,intent是桥梁,要想界面启动服务,或者服务启动界面,就必须有架起他们之间的桥梁,而intent就是那桥梁
intent是activity和service的桥梁,通信员,activity主要操作显示界面,service在后台运行,适合长时间运行,如下载,听歌等。。
21.请描述一下Broadcase Receiver
有很多广播接收者 ,系统已经实现了.
广播分两种 有序广播
无序广播
指定接收者的广播 . 是不可以被拦截掉的
<intent-filter android:priority="1000">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
abortBroadcast();
用于接收系统的广播通知, 系统会有很多sd卡挂载,手机重启,广播通知,低电量,来电,来短信等….
手机卫士中自定义一个broadcast receiver
<intent-filter android:> <action> sms_received </action> </intent-filter>
来获取短信到来的广播, 根据黑名单来判断是否拦截该短信.
画画板生成图片后,发送一个sd挂载的通知,通知系统的gallery去获取到新的图片.
Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED,Uri.parse("file://"+Environment.getExternalStorageDirectory()));
sendBroadcast(intent);
22. 在manifest和代码中如何注册和使 用 broadcast receiver 。
设置广播接收者的优先级,设置广播接受者的action名字 等…
详细见工程代码.
<intent-filter android:priority="1000">
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
<receiver android:name=".SmsReceiver">
<intent-filter android:priority="1000">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
<receiver android:name=".BootCompleteReceiver">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
使用代码注册广播
//使用代码注册电话去电广播接收者
callReceiver=new OutCallReceiver();
IntentFilter filter=new IntentFilter(Intent.ACTION_NEW_OUTGOING_CALL);
//注册广播接收者
registerReceiver(callReceiver, filter);
23. 请介绍下ContentProvider是如何实现数据共享的。
把自己的数据通过uri的形式共享出去
android 系统下 不同程序 数据默认是不能共享访问
需要去实现一个类去继承ContentProvider
public class PersonContentProvider extends ContentProvider{
public boolean onCreate(){
//..
}
query(Uri, String[], String, String[], String)
insert(Uri, ContentValues)
update(Uri, ContentValues, String, String[])
delete(Uri, String, String[])
}
一个应用程序可以通过实现一个Content provider的抽象接口将自己的数据共享给其他应用程序,而且Content providers是以类似数据库表的方式将数据暴露。
Content providers存储和检索数据,通过它可以让所有的应用程序访问到,这也是应用程序之间唯一共享数据的方法。
要想使应用程序的数据公开化,可通过2种方法:
创建一个属于你自己的Content provider或者将你的数据添加到一个已经存在的Content provider中,前提是有相同数据类型并且有写入Content provider的权限。
那么如何通过统一的接口获取其他应用程序共享的数据呢?
Android提供了ContentResolver,外界的程序可以通过ContentResolver接口访问ContentProvider提供的数据。
24. 请介绍下Android的数据存储方式。
文件 访问权限. sdcard <data>/<data>
数据库 sqlite
SharedPreference <data>/<data>/shared_preps
网络 socket tcp udp , http httpurlconnection
25. 为什么要用ContentProvider?它和sql的实现上有什么差别?
屏蔽数据存储的细节,对用户透明,用户只需要关心操作数据的uri就可以了
不同app之间共享,操作数据
Sql也有增删改查的方法.
但是contentprovider 还可以去增删改查本地文件. xml文件的读取,更改,
网络数据读取更改
26. 请介绍下Android中常用的五种布局。
FrameLayout(帧布局(堆栈布局)),LinearLayout (线性布局),AbsoluteLayout(绝对布局),RelativeLayout(相对布局),TableLayout(表格布局)
FrameLayout在布局文件中使用<FrameLayout>标签标示.FrameLayout布局中的view都会以层叠方式显示,类似于Photoshop的图层.放在最后的view会显示在最上层.因此可以将framelayout称为堆栈布局
LinearLayout可以将多个view水平或垂直排列.如果android:orientaciond的属性为horizontal,view会水平排列.属性值为vertical,view会垂直排列
RelativeLayout可以通过确定多个组件的相对位置摆放组件.与组件相对位置相关的属性包括
Android布局是应用界面开发的重要一环,在Android中,共有五种布局方式,分别是:FrameLayout(框架布局),LinearLayout
(线性布局),AbsoluteLayout(绝对布局),RelativeLayout(相对布局),TableLayout(表格布局)
一、FrameLayout
这个布局可以看成是墙脚堆东西,有一个四方的矩形的左上角墙脚,我们放了第一个东西,要再放一个,那就在放在原来放的位置的上面,这样依次的放,会盖住原来的东西。这个布局比较简单,也只能放一点比较简单的东西。
二、LinearLayout
线性布局,这个东西,从外框上可以理解为一个div,他首先是一个一个从上往下罗列在屏幕上。每一个LinearLayout里面又可分为垂直布局
(android:orientation="vertical")和水平布局(android:orientation="horizontal"
)。当垂直布局时,每一行就只有一个元素,多个元素依次垂直往下;水平布局时,只有一行,每一个元素依次向右排列。
linearLayout中有一个重要的属性 android:layout_weight="1",这个weight在垂直布局时,代表行距;水平的时候代表列宽;weight值越大就越大。
三、AbsoluteLayout
绝对布局犹如div指定了absolute属性,用X,Y坐标来指定元素的位置android:layout_x="20px"
android:layout_y="12px" 这种布局方式也比较简单,但是在垂直随便切换时,往往会出问题,而且多个元素的时候,计算比较麻烦。
四、RelativeLayout
相对布局可以理解为某一个元素为参照物,来定位的布局方式。主要属性有:
相对于某一个元素
android:layout_below="@id/aaa" 该元素在 id为aaa的下面
android:layout_toLeftOf="@id/bbb" 改元素的左边是bbb
相对于父元素的地方
android:layout_alignParentLeft="true" 在父元素左对齐
android:layout_alignParentRight="true" 在父元素右对齐
还可以指定边距等,具体详见API
五。TableLayout
表格布局类似Html里面的Table。每一个TableLayout里面有表格行TableRow,TableRow里面可以具体定义每一个元素,设定他的对齐方式 android:gravity="" 。
每一个布局都有自己适合的方式,另外,这五个布局元素可以相互嵌套应用,做出美观的界面。
27. 谈谈UI中, Padding和Margin有什么区别?
Padding 文字对边框, margin是控件对父窗体.
28. widget相对位置的完成在activity的哪个生命周期阶段实现。
这个题没看懂…
widget可以理解成桌面小控件,
也可以理解成 某个button, imageview这样的控件…
onmeasure() // 计算 控件在屏幕上的位子
某个view 要显示在界面 ondraw 被显示到界面上的 .
29. 请解释下在单线程模型中Message、Handler、Message Queue、 Looper之间的关系。
当应用一旦启动完成,就会有一个looper,looper是一个死循环,不停的去迭代一个Message Queue,Message Queue是一个信息队列,message Queue一旦发现里面有了一个消息,就把它取出来,
取出来之后,他就去找message,message里面有一个Tag,这个tag指的就是当前handler发送的某一个消息,然后这个消息就去找message对应的handler,找到了handler就去执行handler的handmessage方法,里面做执行ui主线程的操作
andriod提供了 Handler 和 Looper 来满足线程间的通信。Handler 先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(Message Exchange)。
1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列)。
2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;或者接收Looper从Message Queue取出)所送来的消息。
3) Message Queue(消息队列):用来存放线程放入的消息。
4)线程:UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。
30.AIDL的全称是什么?如何工作?
Android interface definition language android(接口定义语言),用来跨进程的访问方法
AIDL工作:
1.在eclipse android工程的java源文件目录中建立一个扩展名为aidl的文件,该文件的语法类似java,但稍有不同
2.如果aidl文件的内容是正确的,adt会自动生成一个java接口文件(*.java)
3.建立一个服务类(service的子类)
4.实现由aidl文件生成的java文件
5.在androidManifest.xml文件中配置aidl服务尤其要注意<action>标签中android:name的属性值就是客户端要引用该服务器的id,也就是intent类构造方法的参数值.
1、创建AIDL文件, 在这个文件里面定义接口, 该接口定义了可供客户端访问的方法和属性。
2、编译AIDL文件, 用Ant的话, 可能需要手动, 使用Eclipse plugin的话,可以根据adil文件自动生产java文件并编译, 不需要人为介入.
3、在Java文件中, 实现AIDL中定义的接口. 编译器会根据AIDL接口, 产生一个JAVA接口。这个接口有一个名为Stub的内部抽象类,它继承扩展了接口并实现了远程调用需要的几个方法。接下来就需要自己去实现自定义的几个接口了.
4、向客户端提供接口ITaskBinder, 如果写的是service,扩展该Service并重载onBind ()方法来返回一个实现上述接口的类的实例。
5、在服务器端回调客户端的函数. 前提是当客户端获取的IBinder接口的时候,要去注册回调函数, 只有这样, 服务器端才知道该调用那些函数
aidl支持的数据有:
1.java的简单类型(int,char,boolean).不需要导入
2.String和charSequence
3.list和map,但是要注意,list和map对象的元素必须是aidl服务支持的数据类型
4.aidl自动生成的接口.需要导入
5.实现android.os.Parcelable接口的类.需要导入.
31.解释一下Android程序运行时权限和文件系统权限的区别
Android程序执行需要读取到安全敏感项必需在androidmanifest.xml中声明相关权限请求,打电话,访问网络,获取坐标,读写sd卡等等,这个面向用户的,用户要想执行相关的操作,得有相关的权限.
文件系统权限是面向程序员的,android是一个linux的系统,而linux下的文件权限是使用10个字母表示的,d代表文件夹,_表示文件,然后后面9个字母分别为3组,rwx分别为读,写,执行.第一组rwx是文件拥有者对文件的权限,第二组rwx为文件拥有者属于同一用户组的用户对文件的访问权限,第三组rwx表示的是其他用户对文件的权限。比如sharedpreference里面的Context.Mode.private,你吧sharedpreference改为Context.Mode.private,其他的应用就不能访问该文件了. Context.Mode.world_read_able Context.Mode_world_writeable
要区分apk运行时的拥有的权限与在文件系统上被访问(读写执行)的权限两个概念。
apk程序是运行在虚拟机上的,对应的是Android独特的权限机制,只有体现到文件系统上时才使用linux的权限设置。
(一)linux文件系统上的权限
-rwxr-x--x system system 4156 2010-04-30 16:13 test.apk
代表的是相应的用户/用户组及其他人对此文件的访问权限,与此文件运行起来具有的权限完全不相关。
比如上面的例子只能说明system用户拥有对此文件的读写执行权限;system组的用户对此文件拥有读、执行权限;其他人对此文件只具有执行权限。
而test.apk运行起来后可以干哪些事情,跟这个就不相关了。
千万不要看apk文件系统上属于system/system用户及用户组,或者root/root用户及用户组,就认为apk具有system或root权限
(二)Android的权限规则
(1)Android中的apk必须签名
这种签名不是基于权威证书的,不会决定某个应用允不允许安装,而是一种自签名证书。
重要的是,android系统有的权限是基于签名的。比如:system等级的权限有专门对应的签名,签名不对,权限也就获取不到。
默认生成的APK文件是debug签名的。
获取system权限时用到的签名,见:如何使Android应用程序获取系统权限
(2)基于UserID的进程级别的安全机制
大家都知道,进程有独立的地址空间,进程与进程间默认是不能互相访问的,是一种很可靠的保护机制。
Android通过为每一个安装在设备上的包(apk)分配唯一的linux userID来实现,名称为"app_"加一个数字,比如app_43
不同的UserID,运行在不同的进程,所以apk之间默认便不能相互访问。
Android提供了如下的一种机制,可以使两个apk打破前面讲的这种壁垒。
在AndroidManifest.xml中利用sharedUserId属性给不同的package分配相同的userID,通过这样做,两个package可以被当做同一个程序,
系统会分配给两个程序相同的UserID。当然,基于安全考虑,两个package需要有相同的签名,否则没有验证也就没有意义了。
(这里补充一点:并不是说分配了同样的UserID,两程序就运行在同一进程, 下面为PS指令摘取的,
显然,system、app_2分别对应的两个进程的PID都不同,不知Android到底是怎样实现它的机制的)
User PID PPID
system 953 883 187340 55052 ffffffff afe0cbcc S system_server
app_2 1072 883 100264 19564 ffffffff afe0dcc4 S com.android.inputmethod.
system 1083 883 111808 23192 ffffffff afe0dcc4 S android.process.omsservi
app_2 1088 883 156464 45720 ffffffff afe0dcc4 S android.process.acore
(3)默认apk生成的数据对外是不可见的
实现方法是:Android会为程序存储的数据分配该程序的UserID。
借助于Linux严格的文件系统访问权限,便实现了apk之间不能相互访问似有数据的机制。
例:我的应用创建的一个文件,默认权限如下,可以看到只有UserID为app_21的程序才能读写该文件。
-rw------- app_21 app_21 87650 2000-01-01 09:48 test.txt
如何对外开放?
<1> 使用MODE_WORLD_READABLE and/or MODE_WORLD_WRITEABLE 标记。
When creating a new file with getSharedPreferences(String, int), openFileOutput(String, int), or openOrCreateDatabase(String, int, SQLiteDatabase.CursorFactory), you can use the MODE_WORLD_READABLE and/or MODE_WORLD_WRITEABLE flags to allow any other package to read/write the file. When setting these flags, the file is still owned by your application, but its global read and/or write permissions have been set appropriately so any other application can see it.
(4)AndroidManifest.xml中的显式权限声明
Android默认应用是没有任何权限去操作其他应用或系统相关特性的,应用在进行某些操作时都需要显式地去申请相应的权限。
一般以下动作时都需要申请相应的权限:
A particular permission may be enforced at a number of places during your program's operation:
At the time of a call into the system, to prevent an application from executing certain functions.
When starting an activity, to prevent applications from launching activities of other applications.
Both sending and receiving broadcasts, to control who can receive your broadcast or who can send a broadcast to you.
When accessing and operating on a content provider.
Binding or starting a service.
在应用安装的时候,package installer会检测该应用请求的权限,根据该应用的签名或者提示用户来分配相应的权限。
在程序运行期间是不检测权限的。如果安装时权限获取失败,那执行就会出错,不会提示用户权限不够。
大多数情况下,权限不足导致的失败会引发一个 SecurityException, 会在系统log(system log)中有相关记录。
(5)权限继承/UserID继承
当我们遇到apk权限不足时,我们有时会考虑写一个linux程序,然后由apk调用它去完成某个它没有权限完成的事情,很遗憾,这种方法是行不通的。
前面讲过,android权限是经营在进程层面的,也就是说一个apk应用启动的子进程的权限不可能超越其父进程的权限(即apk的权限),
即使单独运行某个应用有权限做某事,但如果它是由一个apk调用的,那权限就会被限制。
实际上,android是通过给子进程分配父进程的UserID实现这一机制的。
(三)常见权限不足问题分析
首先要知道,普通apk程序是运行在非root、非system层级的,也就是说看要访问的文件的权限时,看的是最后三位。
另外,通过system/app安装的apk的权限一般比直接安装或adb install安装的apk的权限要高一些。
言归正传,运行一个android应用程序过程中遇到权限不足,一般分为两种情况:
(1)Log中可明显看到权限不足的提示。
此种情况一般是AndroidManifest.xml中缺少相应的权限设置,好好查找一番权限列表,应该就可解决,是最易处理的情况。
有时权限都加上了,但还是报权限不足,是什么情况呢?
Android系统有一些API及权限是需要apk具有一定的等级才能运行的。
比如 SystemClock.setCurrentTimeMillis()修改系统时间,WRITE_SECURE_SETTINGS权限好像都是需要有system级的权限才行。也就是说UserID是system.
(2)Log里没有报权限不足,而是一些其他Exception的提示,这也有可能是权限不足造成的。
比如:我们常会想读/写一个配置文件或其他一些不是自己创建的文件,常会报java.io.FileNotFoundException错误。
系统认为比较重要的文件一般权限设置的也会比较严格,特别是一些很重要的(配置)文件或目录。
如
-r--r----- bluetooth bluetooth 935 2010-07-09 20:21 dbus.conf
drwxrwx--x system system 2010-07-07 02:05 data
dbus.conf好像是蓝牙的配置文件,从权限上来看,根本就不可能改动,非bluetooth用户连读的权利都没有。
/data目录下存的是所有程序的私有数据,默认情况下android是不允许普通apk访问/data目录下内容的,通过data目录的权限设置可知,其他用户没有读的权限。
所以adb普通权限下在data目录下敲ls命令,会得到opendir failed, Permission denied的错误,通过代码file.listfiles()也无法获得data目录下的内容。
上面两种情况,一般都需要提升apk的权限,目前我所知的apk能提升到的权限就是system(具体方法见:如何使Android应用程序获取系统权限),
32.系统上安装了多种浏览器,能否知道某浏览器访问指定页面.
可以的,只要他的浏览器在清单文件中配置了一个隐式的<intent-filter>
</intent-filter>
找到对应的浏览器的意图,传递数据URI,激活这个意图
Intent intent=new Intent();
intent.setClassName(packageName,className);
intent.seturi();
Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
Uri content_uri_browsers = Uri.parse("http://isomobile.com");
intent.setData(content_uri_browsers);
intent.setClassName("com.android.browser", "com.android.browser.BrowserActivity");
startActivity(intent);
问题的关键在于我们设置了class name,也就是我们想要跳转的pakcage的activity。如果你想要跳转到其它的浏览器,只需要修改一下这个函数就OK了。
好,我们现在来让刚刚的思路来指导我们的实践。假如我们现在要直接启动UC浏览器,那么我们该怎么做呢?让我们step by step吧。
1)下载UC apk:http://i-uc.net/read.php?2
2)用7zip解压apk文件,得到classes.dex文件
3)下载反编译dex文件工具:http://nchc.dl.sourceforge.net/project/dedexer/dedexer/1.5/ddx1.5.jar(Dedexer 项目主页: http://dedexer.sourceforge.net/)
4)执行命令:java -jar ddx1.5.jar -o -D -d c:\ c:\classes.dex
5)得到package name是:com.uc.browser,启动的activity是:com.uc.browser.ActivityUpdate(补充:当我在这里选择采用ActivityBrowser的时候发觉权限不够,报permiss denied 异常,而且也不是我们要的那个activity,幸运的是在第二次尝试用ActivityUpdate,刚好能满足要求)
6)修改上面的代码为intent.setClassName("com.uc.browser","com.uc.browser.ActivityUpdate");****
33.对android主线程的运用和理解
主ui线程不能执行耗时的操作
耗时操作都是自己开启子线程去执行.
在ui主线程中的分别有
receiver 10秒
content provide 5秒
service 20秒
activity 5秒
34.对android虚拟机的理解,包括内存管理机制和垃圾回收机制.
虚拟机很小,空间很小,androdi的虚拟机的默认是16mb,有些手机厂商的虚拟机的内存大小改为32mb.
讲到androd的内存管理机制就说说加载图片去处理大图片,android加载大图片的时候,我们曾创建一个Options对象,该对象把解析图片需要的参数都封装了起来,这样我们可以把图片的长宽进行压缩.记住bitmap用完后使用bm.describeContents();把他的内存给回收掉。
垃圾回收,没有引用的对象,在某个时刻被系统gc掉
与windows内存区别
在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然。这是Linux内存管理的一个优秀特性,在这方面,区别于 Windows的内存管理。主要特点是,无论物理内存有多大,Linux都将其充份利用,将一些程序调用过的硬盘数据读入内存,利用内存读写的高速特性来提高Linux系统的数据访问性能。而Windows是只在需要内存时,才为应用程序分配内存,并不能充分利用大容量的内存空间。换句话说,每增加一些物理内存,Linux都将能充分利用起来,发挥了硬件投资带来的好处,而Windows只将其做为摆设,即使增加8GB甚至更大。
android内存的意义
其实我们在用安卓手机的时候不用太在意剩余内存,Android上的应用是java,当然需要虚拟机,而android上的应用是带有独立虚拟机的,也就是每开一个应用就会打开一个独立的虚拟机。其实和java的垃圾回收机制类似,系统有一个规则来回收内存。进行内存调度有个阀值,只有低于这个值系统才会按一个列表来关闭用户不需要的东西。当然这个值默认设置得很小,所以你会看到内存老在很少的数值徘徊。但事实上他并不影响速度。相反加快了下次启动应用的速度。这本来就是 android标榜的优势之一,如果人为去关闭进程,没有太大必要。特别是使用自动关进程的软件。为什么内存少的时候运行大型程序会慢呢,原因是:在内存剩余不多时打开大型程序时会触发系统自身的调进程调度策略,这是十分消耗系统资源的操作,特别是在一个程序频繁向系统申请内存的时候。这种情况下系统并不会关闭所有打开的进程,而是选择性关闭,频繁的调度自然会拖慢系统。
Android的内存管理
Android的程序由Java语言编写,所以Android的内存管理与Java的内存管理相似。程序员通过new为对象分配内存,所有对象在java堆内分配空间;然而对象的释放是由垃圾回收器来完成的。C/C++中的内存机制是“谁污染,谁治理”,java的就比较人性化了,给我们请了一个专门的清洁工(GC)。
GC
GC是垃圾收集的意思(GabageCollection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。
垃圾回收的优点和原理
Java语言中一个显著的特点就是引入了垃圾回收机制,使得Java程序员在编写程序的时候不再需要考虑内存管理。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。
对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是"可达的",哪些对象是"不可达的"。当GC确定一些对象为"不可达"时,GC就有责任回收这些内存空间。程序员可以手动执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。
² Android系统中GC出现内存泄露
导致内存泄漏主要的原因是,先前申请了内存空间而忘记了释放。如果程序中存在对无用对象的引用,那么这些对象就会驻留内存,消耗内存,因为无法让垃圾回收器GC验证这些对象是否不再需要。如果存在对象的引用,这个对象就被定义为"有效的活动",同时不会被释放。要确定对象所占内存将被回收,我们就要务必确认该对象不再会被使用。典型的做法就是把对象数据成员设为null或者从集合中移除该对象。但当局部变量不需要时,不需明显的设为null,因为一个方法执行完毕时,这些引用会自动被清理。Java 内存泄露的根本原因就是 保存了不可能再被访问的变量类型的引用。
Android的内存溢出
因为系统为每一个dalvik虚拟机分配的内存是有限的,它的最大堆大小一般是16M,有的机器为24M。也就是说我们所能利用的内存空间是有限的。如果我们的内存占用超过了一定的水平就会出现OutOfMemory的错误。
内存不够用的原因
由于我们程序的失误,长期保持某些资源(如Context)的引用,造成内存泄露,资源造成得不到释放。保存了多个耗用内存过大的对象(如Bitmap),造成内存超出限制
35.Frameword工作方式及原理,activity是如何生成一个view的,机制是什么
反射+配置文件.
我们可以把我们做的每一个android应用理解成一个容器,而每一个activity里面都有window.callback(窗口的回调事件)和keyevent.callback(键盘的回调事件).一些回调的接口或函数把,framework把activity创建出来就会调用里面的这些回调方法,会调用activity生命周期的相关方法,比如说你在activity按了某个按钮的点击事件,在这之前,我们把应用打包成apk发送到手机上,apk会启动一个dvm,dvm把apk解压,找到一AndroidManifest.xml,然后dvm看你的清单文件中有哪些组件,一旦发现用户做了点击操作,就去找这些组件做出对应的操作
activity里面的view是通过ondraw画出来的,在ondraw方法之前还会调用onmeasure方法来计算显示的大小.
36.android本身的一些限制,比如apk包大小限制,读取大文件时的时间限制.
这个问题问的真有问题,apk包大小限制不好说.极品飞车100m还是能安装到手机上呢.这个大小呢和安装有关系,你100mb的apk读取到手机上的时候,可能手机的性能问题等等,会出现读取中断了的问题.
读取大文件的时间限制和你读取大文件的子线程在什么组件下有关系,比如在activty里面不要好过5秒,在service里面不要超过20秒.
37.加载音乐信息,如果改善其效率.
android提供了mediascanner,mediaStore等接口,音乐文件的信息都会存放到系统的数据库表中,可以通过content provider获取.
改善效率可以从分批加载,延时加载,合理使用缓存等去改善.
38.lisview如何提高其效率?
复用convertview,历史的view对象
减少子view查询的次数,用用viewholder
然后就是异步加载数据,分页加载数据,使用静态的view对象,避免创建过多的view.
1.在adapter中的getview方法中尽量少使用逻辑
比如你在getview里面判断子view的显示隐藏,我们可以放到创建viewholder里面去做.
2.尽最大的可能避免对象被gc
当你创建了大量的对象的时候,GC就会频繁的执行,所以在getView()方法中不要创建很多的对象,最好的优化是,不要在ViewHolder以外创建任何对象,如果你的你的log里面发现“GC has freed some memory”频繁出现的话,那你的程序肯定有问题了。你可以检查一下:
a) item布局的层级是否太深
b) getView()方法中是否有大量对象存在
c) ListView的布局属性
3.滑动的时候不要加载图片
如果你的ListView中需要显示从网络上下载的图片的话,我们不要在ListView滑动的时候加载图片,那样会使ListView变得卡顿,所以我们需要再监听器里面监听ListView的状态,如果滑动的时候,停止加载图片,如果没有滑动,则开始加载图片
listView.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView listView, int scrollState) {
//停止加载图片
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
imageLoader.stopProcessingQueue();
} else {
//开始加载图片
imageLoader.startProcessingQueue();
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
}
});
4.将ListView的scrollingCache和animateCache设置为false
scrollingCache: scrollingCache本质上是drawing cache,你可以让一个View将他自己的drawing保存在cache中(保存为一个bitmap),这样下次再显示View的时候就不用重画了,而是从cache中取出。默认情况下drawing cahce是禁用的,因为它太耗内存了,但是它确实比重画来的更加平滑。而在ListView中,scrollingCache是默认开启的,我们可以手动将它关闭。
animateCache: ListView默认开启了animateCache,这会消耗大量的内存,因此会频繁调用GC,我们可以手动将它关闭掉
5.item的布局层级越少越好
我们应该尽量减少item布局深度,因为当滑动ListView的时候,这回直接导致测量与绘制,因此会浪费大量的时间,所以我们应该将一些不必要的布局嵌套关系去掉。减少item布局深度
6.使用ViewHolder
1.在adapter中的getView方法中尽量少使用逻辑
39.启动应用后,改变系统语言,应用的语言会改变吗?
40.启动一个程序,可以从主界面点击图标进入,也可以从一个程序跳转过去,二者的区别是什么?
其实也没有什么不同,只不过写startActivity的位置不一样而已.
是因为启动程序(主界面也是一个app),发现了在这个程序中存在一个设置为<category android:name="android.intent.category.LAUNCHER" />的activity,
所以这个launcher会把icon提出来,放在主界面上。当用户点击icon的时候,发出一个Intent:
Intent intent = mActivity.getPackageManager().getLaunchIntentForPackage(packageName);
mActivity.startActivity(intent);
跳过去可以跳到任意允许的页面,如一个程序可以下载,那么真正下载的页面可能不是首页(也有可能是首页),这时还是构造一个Intent,startActivity.
这个intent中的action可能有多种view,download都有可能。系统会根据第三方程序向系统注册的功能,为你的Intent选择可以打开的程序或者页面。所以唯一的一点
不同的是从icon的点击启动的intent的action是相对单一的,从程序中跳转或者启动可能样式更多一些。本质是相同的
41.Android程序和java程序的区别?
Android程序用android sdk开发,java程序用javasdk开发.
Android SDK引用了大部分的Java SDK,少数部分被Android SDK抛弃,比如说界面部分,java.awt swing package除了java.awt.font被引用外,其他都被抛弃,在Android平台开发中不能使用。 android sdk 添加工具jar httpclient , pull opengl
将Java 游戏或者j2me程序移植到Android平台的过程中,
Android SDK 与Java SDK的区别是很需要注意的地方。
sampledataadpter()
java文件在android的后缀为dex,在java中是.class
42.Androdi中Task任务栈的分配
首先我们来看下Task的定义,Google是这样定义Task的:a task is what the user experiences as an "application." It's a group of related activities, arranged in a stack. A task is a stack of activities, not a class or an element in the manifest file. 这意思就是说Task实际上是一个Activity栈,通常用户感受的一个Application 它只是针对Activity而言的。
Activity有不同的启动模式, 可以影响到task的分配
Task,简单的说,就是一组以栈的模式聚集在一起的Activity组件集合。它们有潜在的前后驱关联,新加入的Activity组件,位于栈顶,并仅有在栈顶的Activity,才会有机会与用户进行交互。而当栈顶的Activity完成使命退出的时候,Task会将其退栈,并让下一个将跑到栈顶的Activity来于用户面对面,直至栈中再无更多Activity,Task结束。
事件 Task栈 (粗体为栈顶组件)
点开Email应用,进入收件箱(Activity A) A
选中一封邮件,点击查看详情(Activity B) AB
点击回复,开始写新邮件(Activity C) ABC
写了几行字,点击选择联系人,进入选择联系 ABCD
人界面(Activity D)
选择好了联系人,继续写邮件 ABC
写好邮件,发送完成,回到原始邮件 AB
点击返回,回到收件箱 A
退出Email程序 null
如上表所示,是一个实例。从用户从进入邮箱开始,到回复完成,退出应用整个过程的Task栈变化。这是一个标准的栈模式,对于大部分的状况,这样的Task模型,足以应付,但是,涉及到实际的性能、开销等问题,就会变得残酷许多。
比如,启动一个浏览器,在Android中是一个比较沉重的过程,它需要做很多初始化的工作,并且会有不小的内存开销。但与此同时,用浏览器打开一些内容,又是一般应用都会有的一个需求。设想一下,如果同时有十个运行着的应用(就会对应着是多个Task),都需要启动浏览器,这将是一个多么残酷的场面,十个Task栈都堆积着很雷同的浏览器Activity,
是多么华丽的一种浪费啊。
于是你会有这样一种设想,浏览器Activity,可不可以作为一个单独的Task而存在,不管是来自那个Task的请求,浏览器的Task,都不会归并过去。这样,虽然浏览器Activity本身需要维系的状态更多了,但整体的开销将大大的减少,这种舍小家为大家的行为,还是很值得歌颂的
standard", "singleTop", "singleTask", "singleInstance"。
standard模式, 是默认的也是标准的Task模式,在没有其他因素的影响下,使用此模式的Activity,会构造一个Activity的实例,加入到调用者的Task栈中去,对于使用频度一般开销一般什么都一般的Activity而言,standard模式无疑是最合适的,因为它逻辑简单条理清晰,所以是默认的选择。
而singleTop模式,基本上于standard一致,仅在请求的Activity正好位于栈顶时,有所区别。此时,配置成singleTop的Activity,不再会构造新的实例加入到Task栈中,而是将新来的Intent发送到栈顶Activity中,栈顶的Activity可以通过重载onNewIntent来
处理新的Intent(当然,也可以无视...)。这个模式,降低了位于栈顶时的一些重复开销,更避免了一些奇异的行为(想象一下,如果在栈顶连续几个都是同样的Activity,再一级级退出的时候,这是怎么样的用户体验...),很适合一些会有更新的列表Activity展示。一个活生生的实例是,在Android默认提供的应用中,浏览器(Browser)的书签Activity(BrowserBookmarkPage),就用的是singleTop。
singleTask,和singleInstance,则都采取的另辟Task的蹊径。
标志为singleTask的Activity,最多仅有一个实例存在,并且,位于以它为根的Task中。所有对该Activity的请求,都会跳到该Activity的Task中展开进行。singleTask,很象概念中的单件模式,所有的修改都是基于一个实例,这通常用在构造成本很大,但切换成本较小的Activity中。最典型的例子,还是浏览器应用的主Activity(名为Browser...),它是展示当前tab,当前页面内容的窗口。它的构造成本大,但页面的切换还是较快的,于singleTask相配,还是挺天作之合的。
singleInstance显得更为极端一些。在大部分时候singleInstance与singleTask完全一致,唯一的不同在于,singleInstance的Activity,是它所在栈中仅有的一个Activity,如果涉及到的其他Activity,都移交到其他Task中进行。这使得singleInstance的Activity,像一座孤岛,彻底的黑盒,它不关注请求来自何方,也不计较后续由谁执行。在Android默认的各个应用中,很少有这样的Activity,在我个人的工程实践中,曾尝试在有道词典的快速取词Activity中采用过,
是因为我觉得快速取词入口足够方便(从notification中点选进入),并且会在各个场合使用,应该做得完全独立。
大的apk 拆成 很多小的apk
●Activity的android:affinity属性
1.配置后 当启动这个activity时就先去找有没有activity的亲和力属性相同 有就加入这个
activity所在的任务中没有就新开任务
2.affinity起作用需要的条件二者具备一个:
1.intent包含FLAG_ACTIVITY_NEW_TASK标记
2.activity元素启用了allowTaskReparenting属性.
43.在Android中,怎么节省内存的使用,怎么主动回收内存?
回收已经使用的资源
比如你创建了一个list,你用完之后,确定以后不需要再用他的,及时的list.clear(),就不会造成内存泄露
合理的使用缓存
比如我们listview设置图片的时候,第一次加载会吧图片从网络加载,然后在加载到本地,从本地加载到内存.
合理设置变量的作用范围… application 对象
//未来的某一段时间执行
System.gc();
44.不同的工程的方法是否可以相互调用?
可以,比如aidl.
45.在Android中是如何实现判断区分电话的状态,去电,来电,未接来电?
46.dvm的进程和linux的进程,应用程序的进程是否为同一概念?
Dvm的进程是dalivk虚拟机进程,每个android程序都运行在自己的进程里面,
每个android程序系统都会给他分配一个单独的liunx uid(user id),
每个dvm都是linux里面的一个进程.所以说这两个进程是一个进程.
47.sim卡的ef文件有何作用?
没有接触过,ef是做存储用的.我研究研究就会了.
sim卡的文件系统有自己规范,主要是为了和手机通讯,sim本 身可以有自己的操作系统,EF就是作存储并和手机通讯用的
48.如何判断是否有sd卡?
配置文件中有sd卡的权限,通过environment的静态方法
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
49.嵌入式操作系统内存管理有哪几种,各有什么特性?
页式,比如有一个2g的内存,如何把2g的内存分成很多份,一页就打2mb吧,如果你有一个文件小于2mb,就分一页给文件,如果大于2mb,就多分一页给他.页式有一个缺点,如果是0.2mb的,就会造成内存浪费.
段式,是随机的分,比如1mb,2mb,或者更小,分完以后,他把段式的地址保存起来,类似于hashmap的,然后就去匹配.段式的缺点是你比如一个5mb的文件,要把相邻的内存地址加起来,直到匹配,这是一个复杂的过程.
段页,把所有的内存,分成很多页,然后每一页分成很多段的
50.什么是嵌入式实时操作系统,Android操作系统属于实时操作系统吗?
实时操作系统是指当外界事件或数据产生时,能够接受并以足够快的速度予以处理,其处理的结果又能在规定的时间之内来控制生产过程或对处理系统作出快速响应,并控制所有实时任务协调一致运行的嵌入式操作系统。主要用于工业控制、军事设备、航空航天等领域对系统的响应时间有苛刻的要求,这就需要使用实时系统。
简单来说实时操作系统就是你在系统干一件事,然后你突然想干另外一件事了,系统说好,我保存一个这件事的状态,然后就去干另外一件事了.
又可分为软实时和硬实时两种,而android是基于linux内核的,因此属于软实时。软实时就是通过软件去中断,硬实时就是通过邮件去实时.硬实时比软实时更加快速.
嵌入式指的就是对cpu,内存要求非常低,只需要一个cpu和几mb的内存,就能启动一个程序.
51.一条最长的短信息约占多少byte?
标准的是中文70(包括标点),英文160,160个字节,这个说法不是很准确,要跟手机制式运营商等信息有关.
做个试验就知道了
SmsManager sm=SmsManager.getDefault();
ArrayList<String> msgs=sm.divideMessage("信息");
sm.sendTextMessage(phone,null, s, null, null);
52.Linux中跨进程通信的几种方式.
Linux
# 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
# 有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
# 信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
# 消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
# 信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
# 共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。
# 套接字( socket ) : 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。
53. 谈谈对Android NDK的理解。
native develop kit 只是一个交叉编译的工具 .so
1.什么时候用ndk, 实时性要求高,游戏,图形渲染, opencv (人脸识别) , ffmpeg , rmvb mp5 avi 高清解码. ffmpeg, opencore.
2.为什么用ndk,ndk的优点,效率高
缺点 ,出现了bug很难解决
NDK是一些列工具的集合,
NDK提供了一系列的工具,帮助开发者迅速的开发C/C++的动态库,并能自动将so和java 应用打成apk包。
NDK集成了交叉编译器,并提供了相应的mk文件和隔离cpu、平台等的差异,开发人员只需简单的修改mk文件就可以创建出so
54.谈谈android的优点和不足之处
1、开放性,开源 ophone 阿里云( 完全兼容android)
2、挣脱运营商束缚
3、丰富的硬件选择 mtk android
4、不受任何限制的开发商
5、无缝结合的Google应用
缺点也有5处:
1、安全问题、隐私问题
2、卖手机的不是最大运营商
3、运营商对Android手机仍然有影响
4、山寨化严重
5、过分依赖开发商,缺乏标准配置
55.Android系统中GC什么情况会出现内存泄露?
视频编解码/内存泄露
检测内存泄露 工具
mat
C:\Users\lenovo\Desktop\prof>hprof-conv com.example.testmat.hprof convert-com.ex
ample.testmat.hprof
导致内存泄漏主要的原因是,先前申请了内存空间而忘记了释放。如果程序中存在对无用对象的引用,那么这些对象就会驻留内存,消耗内存,因为无法让垃圾回收器GC验证这些对象是否不再需要。如果存在对象的引用,这个对象就被定义为"有效的活动",同时不会被释放。要确定对象所占内存将被回收,我们就要务必确认该对象不再会被使用。典型的做法就是把对象数据成员设为null或者从集合中移除该对象。但当局部变量不需要时,不需明显的设为null,因为一个方法执行完毕时,这些引用会自动被清理。
Java带垃圾回收的机制,为什么还会内存泄露呢?
Vector v = new Vector(10);
for (int i = 1; i < 100; i++){
Object o = new Object();
v.add(o);
o = null;
}//此时,所有的Object对象都没有被释放,因为变量v引用这些对象。
Java 内存泄露的根本原因就是 保存了不可能再被访问的变量类型的引用
56. Android UI中的View如何刷新。
在主线程中 拿到view调用Invalide()方法,查看画画板里面更新imageview的方法
在子线程里面可以通过postInvalide()方法;
View view;
view.invalidate();//主线程
view.postInvalidate();//子线程
57. 简单描述下Android 数字签名。
Android 数字签名
在Android系统中,所有安装到系统的应用程序都必有一个数字证书,此数字证书用于标识应用程序的作者和在应用程序之间建立信任关系
Android系统要求每一个安装进系统的应用程序都是经过数字证书签名的,数字证书的私钥则保存在程序开发者的手中。Android将数字证书用来标识应用程序的作者和在应用程序之间建立信任关系,不是用来决定最终用户可以安装哪些应用程序。
这个数字证书并不需要权威的数字证书签名机构认证(CA),它只是用来让应用程序包自我认证的。
同一个开发者的多个程序尽可能使用同一个数字证书,这可以带来以下好处。
(1)有利于程序升级,当新版程序和旧版程序的数字证书相同时,Android系统才会认为这两个程序是同一个程序的不同版本。如果新版程序和旧版程序的数字证书不相同,则Android系统认为他们是不同的程序,并产生冲突,会要求新程序更改包名。
(2)有利于程序的模块化设计和开发。Android系统允许拥有同一个数字签名的程序运行在一个进程中,Android程序会将他们视为同一个程序。所以开发者可以将自己的程序分模块开发,而用户只需要在需要的时候下载适当的模块。
在签名时,需要考虑数字证书的有效期:
(1)数字证书的有效期要包含程序的预计生命周期,一旦数字证书失效,持有改数字证书的程序将不能正常升级。
(2)如果多个程序使用同一个数字证书,则该数字证书的有效期要包含所有程序的预计生命周期。
(3)Android Market强制要求所有应用程序数字证书的有效期要持续到2033年10月22日以后。
Android数字证书包含以下几个要点:
(1)所有的应用程序都必须有数字证书,Android系统不会安装一个没有数字证书的应用程序
(2)Android程序包使用的数字证书可以是自签名的,不需要一个权威的数字证书机构签名
58. 什么是ANR 如何避免它?
在Android上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框称作应用程序无响应(ANR:Application Not Responding)对话框。用户可以选择让程序继续运行,但是,他们在使用你的应用程序时,并不希望每次都要处理这个对话框。因此,在程序里对响应性能的设计很重要,这样,系统不会显示ANR给用户。
Activity 5秒 broadcast10秒
耗时的操作 worker thread里面完成, handler message…AsynTask , intentservice.等…
59. android中的动画有哪几类,它们的特点和区别是什么?
两种,一种是Tween动画、还有一种是Frame动画。
Tween动画,这种实现方式可以使视图组件移动、放大、缩小以及产生透明度的变化;
可以通过布局文件,可以通过代码
1、控制View的动画
a) alpha(AlphaAnimation)渐变透明
b) scale(ScaleAnimation) 渐变尺寸伸缩
c) translate(TranslateAnimation)画面转换、位置移动
d) rotate(RotateAnimation)画面转移,旋转动画
2、 控制一个Layout里面子View的动画效果
a) layoutAnimation(LayoutAnimationController)
b) gridAnimation(GridLayoutAnimationController)
另一种Frame动画,传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影。
属性动画 ObjectAnimator
Tween和Frame动画是把view显示的位置改变的,但是view原生的位置是不变的,
属性动画是真正的把view的位置改变了
63. 通过点击一个网页上的url 就可以完成程序的自动安装,描述下原理
通过javascript,用过webview的都知道,可以在网页中,用js调用java方法,我们就可以通过这种形式去搞定
64,Service和Activity在同一个线程吗
默认情况同一线程 main主线程 ui线程
65,java中的soft reference是个什么东西
StrongReference 是 Java 的默认引用实现(软引用), 它会尽可能长时间的存活于 JVM 内, 当没有任何对象指向它时 GC 执行后将会被回收
SoftReference 会尽可能长的保留引用直到 JVM 内存不足时才会被回收(虚拟机保证), 这一特性使得 SoftReference 非常适合缓存
在android2.3以上的系统,会更倾向于回收软引用和弱引用,因此使用它们不在变得可靠,
鉴于此,谷歌推出了新的缓存
LruCache
least recentlly use最少最近使用算法
会将内存控制在一点的大小内,超出最大值时会自动回收,这个最大值开发者自己定
应用详细见客户端图片的缓存
66,udp连接和TCP的不同之处
tcp/滑动窗口协议. 拥塞控制. 面向连接 流
udp 不关心数据是否达到,是否阻塞 面向无连接
画面优先. tcp
流畅优先 udp
简单的说TCP与UDP的区别是有无连接状态。
TCP是有连接状态的,而UDP没有,所以TCP是一种比较安全的通讯协议,而UDP则比较方便
TCP 127.0.0.1:1026 0.0.0.0:0 LISTENING
TCP 是传输协议 TCP是主动连接 网页什么的用TCP(貌似)
UDP也是传输协议 UDP迂回连接 QQ就用UDP (貌似)
127.0.0.1 是本地回环地址
1026 是端口
LISTENING 是监听
TCP 127.0.0.1:1026 0.0.0.0:0 LISTENING
全意是 监听 TCP 1026端口
0.0.0.0 是没有东西 为零
0 端口就是没有。。。ING
TCP是面向连接的
UDP是面向无连接的
就是这种关系了
TCP(Transmission Control Protocol,传输控制协议)
UDP(User Datagram Protocol,用户数据包协议)
当IP包通过路由将数据传输到目的地时,会根据TCP或UDP包头中的源端口和目的端口信息,请求和获取不同的应用。也就是说,不管TCP还是UDP,都含有网络服务必须的源端口和目的端口信息,以建立和实现网络传输服务。这时,你的疑问就来了:既然都用于传输,为何要搞两个不同的协议呢?这就需要从网络中不同服务的需求来谈起。
在网络中,有些服务,如HTTP、FTP等,对数据的可靠性要求较高,在使用这些服务时,必须保证数据包能够完整无误的送达;而另外一些服务,如DNS、即时聊天工具等,并不需要这么高的可靠性,高效率和实时性才是它们所关心的。根据这两种服务不同的需求,也就诞生了面向连接的TCP协议,以及面向无连接的UDP协议。
这里的连接(Connection)和无连接(Connectionless)是网络传输中常用的术语,它们的关系可以用一个形象地比喻来说明,就是打电话和写信。
打电话时,一个人首先必须拨号(发出连接请求),等待对方响应,接听电话(建立了连接)后,才能够相互传递信息。通话完成后,还需要挂断电话(断开连接),才算完成了整个通话过程。写信则不同,你只需填写好收信人的地址信息,然后将信投入邮局,就算完成了任务。此时,邮局会根据收信人的地址信息,将信件送达指定目的地。
我们可以看到,这两者之间有很大不同。打电话时,通话双方必须建立一个连接,才能够传递信息。连接也保证了信息传递的可靠性,因此,面向连接的协议必然是可靠的。无连接就没有这么多讲究,它不管对方是否有响应,是否有回馈,只管将信息发送出去。就像信件一旦进了邮箱,在它到达目的地之前,你没法追踪这封信的下落;接收者即使收到了信件,也不会通知你信件何时到达。在整个通讯过程中,没有任何保障。因此我们常说,面向无连接的协议也是不可靠的。当然,邮局会尽力将右键送到目的地,99%的情况信件会安全到达,但在少数情况下也有例外。
面向连接的协议比面向无连接的协议在可靠性上有着显著的优势,但建立连接前必须等待接收方响应,传输信息过程中必须确认信息是否传到,断开连接时需要发出响应信号等,无形中加大了面向连接协议的资源开销。具体到TCP和UDP协议来说,除了源端口和目的端口,TCP还包括序号、确认信号、数据偏移、控制标志(通常说的URG、ACK、PSH、RST、SYN、FIN)、窗口、校验和、紧急指针、选项等信息,UDP则只包含长度和校验和信息。UDP数据报比TCP小许多,这意味着更小的负载和更有效的使用带宽。许多即时聊天软件采用UDP协议,与此有莫大的关系。
TCP---传输控制协议,提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。 UDP---用户数据报协议,是一个简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。 用TCP还是UDP,那要看你的程序注重哪一个方面?可靠还是快速?
TCP UDP是两个协议,简单的说,TCP连接要对方确认的,而UDP却不需要对方确认收到包,所以TCP连接更加安全,但是一般播放网络流媒体使用UDP协议
传输层协议一般有TCP和UDP,TCP为可靠传输,协议本身会保证数据传输的可靠,但为此会付出很多额外的网络开销。UDP为不可靠传输,所以传输效率比较高,本端只负责发送数据,不保证对端能否收到。对于UDP,可靠性可以在应用层实现
http是基于tcp的,udp我们一般用于视频开发
67, android开发中怎么去调试bug
逻辑错误
1.断点 debug
2. logcat(Threads:能检测你执行到哪个方法了),
3. traceview:检测每块代码执行的时间,对代码进行优化
如何在百万代码中快速定位错误的代码:
如果有错误,肯定会在界面显示,然后我们在tools/hierarchyviewer.bat
68.service里面可以弹土司么
可以.
69.写10个简单的linux命令
70 JNI调用常用的两个参数
JNIEnv *env, jobject javaThis
71. 书写出android工程的目录结构
src
android. jar
asset
res
gen
manifest
72. ddms 和traceview的区别.
DDMS透视图包含了多个视图,例如,File Explorer(用于浏览移动设备目录中的目录和文件)Logcat(查看调试信息),Emulator Control(用于控制模拟器)等,也就是谁DDMS是一个集调试,浏览,控制等操作为一体的工具集.而Traceview只是一个性能调试工具.开发人员可以利用该TraceView查看程序中方法的执行效率
72.1TraceView的使用方法
TraceView是一个性能调优的图形化工具,在使用TraceView之前,使用下面的代码生成一个trace文件
Debug.startMethodTracing("test")
其中activity_trace是跟踪文件名,执行上面的代码后,会在sdcard目录生成一个test.trace文件,字节数为0,一般在activity.ondestroy方法中执行如下的代码将跟踪结果写入activity_trace.trace文件
Debug.stopMethodTracing();
将sdcard目录中的test.trace文件复制到pc上的相应目录(假设复制到了D:\sdcard目录),然后在windows控制台输入如下的命令启动TraceView图形化的跟踪界面
Traceview d:\sdcard\test.trace
执行该命令会启动traceview的图形界面,在该界面显示了从跟踪开始到跟踪结束的所有方法的调用事件,执行事件,被调用次数等信息,可以利用这些信息对程序进行调优
73. 如何将SQLite数据库(dictionary.db文件)与apk文件一起发布?
任何文件(包括sqlite数据库文件)与apk程序一同发布都必须将该文件嵌入到apk文件中.对于sqlite数据库来说,androdi程序不能打开和操作嵌入在apk程序中的数据库文件.因此需要想办法在程序第一次启动时将sqlite数据库文件复制到手机内存或sd卡,然后在操作sqlite熟客.
由于android程序不能打开嵌入apk文件中的sqlite数据库,因此将sqlite数据库放在androdi应用程序的assets或res/raw目录中.因为只有这2个目录中的资源文件不会被编译.在程序第一次启动时将使用下面的代码将sqlite数据库文件赋值到手机内或sd卡
String databaseFilename="";
try {
databaseFilename="/sdcard/test.db";
//当test.db文件不存在时,将res/raw目录中的数据文件复制到sd卡
if(!(new File(databaseFilename).exists())){
InputStream is=getResources().openRawResource(R.raw.test);
//写文件
FileOutputStream fos=new FileOutputStream(databaseFilename);
byte[] buffer=new byte[1024];
int count=0;
while ((count=is.read(buffer))>0) {
fos.write(buffer,0,count);
}
fos.close();
is.close();
}
} catch (Exception e) {
// TODO: handle exception
}
//打开数据库
SQLiteDatabase database=SQLiteDatabase.openOrCreateDatabase(databaseFilename,
null);
74. 如何将打开res aw目录中的数据库文件?
解答:在Android中不能直接打开res aw目录中的数据库文件,而需要在程序第一次启动时将该文件复制到手机内存或SD卡的某个目录中,然后再打开该数据库文件。复制的基本方法是使用getResources().openRawResource方法获得res aw目录中资源的 InputStream对象,然后将该InputStream对象中的数据写入其他的目录中相应文件中。在Android SDK中可以使用SQLiteDatabase.openOrCreateDatabase方法来打开任意目录中的SQLite数据库文件。
75. Android引入广播机制的用意?
答:a:从MVC的角度考虑(应用程序内)
其实回答这个问题的时候还可以这样问,android为什么要有那4大组件,现在的移动开发模型基本上也是照搬的web那一套MVC架构,只不过 是改了点嫁妆而已。android的四大组件本质上就是为了实现移动或者说嵌入式设备上的MVC架构,它们之间有时候是一种相互依存的关系,有时候又是一 种补充关系,引入广播机制可以方便几大组件的信息和数据交互。
b:程序间互通消息(例如在自己的应用程序内监听系统来电)
c:效率上(参考UDP的广播协议在局域网的方便性)
d:设计模式上(反转控制的一种应用,类似监听者模式)
76.android 中有哪几种解析xml的类?官方推荐哪种?以及它们的原理和区别。
XML解析主要有三种方式,SAX、DOM、PULL。常规在PC上开发我们使用Dom相对轻松些,但一些性能敏感的数据库或手机上还是主要采用SAX方 式,SAX读取是单向的,优点:不占内存空间、解析属性方便,但缺点就是对于套嵌多个分支来说处理不是很方便。而DOM方式会把整个XML文件加载到内存 中去,这里Android开发网提醒大家该方法在查找方面可以和XPath很好的结合如果数据量不是很大推荐使用,而PULL常常用在J2ME对于节点处 理比较好,类似SAX方式,同样很节省内存,在J2ME中我们经常使用的KXML库来解析。
详细情况请参考 http://blog.csdn.net/Android_Tutor/archive/2010/09/17/5890835.aspx
http://www.linuxidc.com/Linux/2010-11/29768.htm
http://littlefermat.blog.163.com/blog/static/59771167200981853037951/
77 描述一下android的系统架构
android系统架构分从下往上为linux 内核层、运行库、应用程序框架层、和应用程序层
linuxkernel:负责硬件的驱动程序、网络、电源、系统安全以及内存管理等功能。
libraries和 androidruntime:libraries:即c/c++函数库部分,大多数都是开放源代码的函数库,例如webkit,该函数库负责 android网页浏览器的运行,例如标准的c函数库libc、openssl、sqlite等,当然也包括支持游戏开发2dsgl和 3dopengles,在多媒体方面有mediaframework框架来支持各种影音和图形文件的播放与显示,例如mpeg4、h.264、mp3、 aac、amr、jpg和png等众多的多媒体文件格式。android的runtime负责解释和执行生成的dalvik格式的字节码。
applicationframework(应用软件架构),java应用程序开发人员主要是使用该层封装好的api进行快速开发。该层主要由view,通知管理器(notification manager),活动管理器(Activity Manager)等由开发人员直接调用的api组成.
applications:该层是java的应用程序层,android内置的googlemaps、e-mail、即时通信工具、浏览器、mp3播放 器等处于该层,java开发人员开发的程序也处于该层,而且和内置的应用程序具有平等的位置,可以调用内置的应用程序,也可以替换内置的应用程序。
上面的四个层次,下层为上层服务,上层需要下层的支持,调用下层的服务,这种严格分层的方式带来的极大的稳定性、灵活性和可扩展性,使得不同层的开发人员可以按照规范专心特定层的开发。
android应用程序使用框架的api并在框架下运行,这就带来了程序开发的高度一致性,另一方面也告诉我们,要想写出优质高效的程序就必须对整个 applicationframework进行非常深入的理解。精通applicationframework,你就可以真正的理解android的设计 和运行机制,也就更能够驾驭整个应用层的开发。
78.Android的特点
1.Android拥有完善的应用程序框架,支持四大组件,可以在任一层次上进行复用和更换
2.虽然android的主要编程语言是Java,但是Android中java字节码是运行在Dalvi虚拟机上的,传统的JVM是基于堆栈的,而Dalvik虚拟机是基于寄存器的.因此,在Dalvik运行的java程序要比在传统的JVM上运行的Java程序速度更快
3.Android中内置了WEBKIT核心的浏览器,支持HTML5等新的web标准
4.2d和3d绘图功能丰富,支持OpenGl 2.0,如果手机中带有硬件加速器,3d图形的渲染会更加流畅.
5.支持轻量级的SQLite数据库
6.支持众多的硬件传感器(比如方向传感器,重力传感器,光学传感器,压力传感器)和其他一些硬件,比如蓝牙,3g,WIFI,Camera,GPS等
79.搭建Android开发环境需要些什么?
1.jdk(1.6以上)
2.Eclipse(3.4以上版本)
3.Android SDK
4.ADT
80.说说mvc模式的原理,Android sdk有哪些组件使用到了mvc模式,其基本原理是什么?
到现在为止MVC模式已经得到了广泛的应用,各种类型的程序(桌面程序,WEB程序,移动程序)都涉及了mvc模式,著名的java web框架Strtus就是一套不折不扣的mvc框架.mvc的主要目的就是使程序中的数据和界面分离,其中
m表示模型(model),也就是数据
v表示视图(view),界面
c表示控制器(controller),用于处理m和v之间的联系
MVC基本原理就是通过controller连接view和model,也就是说,当view中显示的数据变化时,会通知controller,而不是直接通知model,这是controller接到view的通知,会在model中采取相应的动作,根据用户在view做的动作,ontroller会通知给model做出相应的操作,moder中的变化会通知控制器,然后控制器会通过视图重新更新显示数据.
使用mvc模式可以将显示部分和数据部分分离解耦,这样当更换视图或模型可以不影响对方,更有利于程序的维护.
在Anddroid sdk中使用mv模式的组件非常多,例如所有的列表控制(listview,spinner(下拉列表),Gridview)都采用mvc模式和数据交互.在Android中的mvc的
m就是代表各种数据源以及操作数据库的库.
C则代表Adapter类.而android的adapter分很多程度,但拥有共同的接口.这些Adapter类主要包括BaseAdapter,SimpleAdapter,SimpleCursorAdapter,ArrayAdapter,CursorAdapter等,他们分别对应不同的数据源,例如ArrayAdapter对应list和数组数据源,而cursorAdapter对应Cursor对象(一般从数据库中获取的记录集).这些adapter会调用getView方法用于重新显示组件中的内容.当组件中显示的数据发生变化,例如删除一行,组件会通过adapter中的方法删除model中相应的记录,然后在调用baseAdapter.notofyDataSetChanged方法使组件中显示的数据发生变化,总之一句话,无论是数据变化,还是组件中显示的数据发生变化,都需要adapter作为桥梁来达到view和model之间同步的目的.
81.ADB突然死掉了怎么办?
ADT通过adb服务与模拟器进行通信.由于adb服务并不算稳定,可能在启动时间较长时间或启动多个模拟器时会突然死的,死掉后的ADT就会与模拟器失去联系,例如无非浏览模拟器中的目录,无非向模拟器发短信.在这种情况下,就需要对adb服务进行重启.重启的方式
1.在ddms的devices视图右上菜单中点击reset adb菜单项重启adb服务.
2.关闭模拟器,并重新启动
3.在任何管理器的进程列表结束adb.exe进,任何关闭模拟器,再次重新启动模拟器
4.如果还是不行,只能重启eclipse
82.<LinearLayoutxmlns:android="http:schemas.android.com/apk/res/android"..>中的xmlns:android是什么意思?xmlns:android的值可以任意设置吗?请说明原因.
这道题表面上考查xml命名空间与布局文件的关系,但实际上这个问题可以进一步深入.例如,布局文件的命名空间与自定义组件的关系紧密.可以考查应聘者如何预定义自定义组件的属性?
在自定义组件时,需要使用<declare-styleable>标签定义属性名,然后需要在布局文件的最顶层标签中指定R。java文件的位置.
假设有一个Android程序的package是mobile.android.yd.interview.现在编写一个自定义组件.首先在res\values目录中建立一个attrs.xml文件.
<resources>
<declare-styleable name="EditTextExt">
<attr name="attr1" format="referene">
</declare-styleable>
</resources>
上面的代码会在R.attr类中生成一个attr1变量.如果在布局文件中使用EditTestExt的attr1属性,就需要指定命名空间.
xml:android是xml中的命名空间,为了防止属性冲突.类似于java中的package.xml:android的值不允许任意设置.xml:android的值必须以“http://schemas.android.com/apk/res”开头,后面的部分表示定义属性的R.java文件所在的包名.在R.java文件中包含了属性名的定义.例如,如果使用系统属性,需要指定系统R.java文件的位置.该文件位于res\android目录中.因此,xmlns:android的值的最后是android
83.FrameLayout的主要用途
FrameLayout主要用于进行层次结构的布局.例如想把多个图片叠加到一起形成一张图像的效果就用framelayout.
84.FrameLayout中的view是层叠摆放的,后一个view会覆盖前一个view,这种说法对面?说明原因
不正确,Framelayout中的view只有在所在的view同样大小并且位置一样才会覆盖.否则view是以层叠方式显示的,类似于photoshop的图层,未被上一层view覆盖的部分会显示出来.
85.在relativeLayout中有一个button按钮,请确定该按钮相对于手机屏幕的位置坐标
获取button,使用button.getLocationOnScren方法可以获取当前view相对于屏幕的坐标
86.在relativeLayout不居中可以设置标签的android:layout_toleOf,android:layout_toRightof等属性确定组件的相对位置,那么如何用java代码来完成这些工作.
以button按钮为例
//装载一个布局文件,要向这个布局文件动态添加一个button
RelativeLayout relativeLayout=(RelativeLayout) getLayoutInflater().
inflate(R.layout.activity_main,null);
//装载要动态添加的按钮布局
Button button=(Button)getLayoutInflater().inflate(R.layout.button,null);
//创建一个layoutParams对象
RelativeLayout.LayoutParams layoutParams=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
//R.id.button1是relativelayout中已经存在的一个按钮的id,动态添加的按钮在该按钮的右下方
//设置android:layout_toRightOf属性的值
layoutParams.addRule(RelativeLayout.RIGHT_OF,R.id.button1);
layoutParams.addRule(RelativeLayout.BELOW,R.id.button1);
//更新button按钮中相应属性的值
button.setLayoutParams(layoutParams);
//relativeLyout动态添加一个按钮
relativeLayout.addView(button);
87.TableLayout布局的用法
TableLayout布局使用<TableLayout>来表示,在<TableLayout>中嵌套<TableRow>标签来表示表格布局中的每一条.<TableRow>标签中可以有不定数目的view.因此,每一条中的列数可以不相等.
<TableLayout>
<TableRow>
<TextView android:text="第一行第一列"/>
<TextView android:text="第一行第二列"/>
</TableRow>
<TableRow>
<TextView android:text="第一行第一列"/>
<TextView android:text="第一行第二列"/>
<TextView android:text="第一行第三列"/>
</TableRow>
<TableLayout>
88.TableLayout标签的stretchColumns属性的作用是什么,如何使用stretchColumns属性
strechColumns属性用于要拉伸(所谓的拉伸就是比如是水平方向的你把第一列设置到了strechColumns属性中,他会主动把你第一列的宽度占用了)的列的索引(从0开始),如果指定多个索引,中间用逗号(,)隔开.TableLayout会在设置完未通过strechColumns指定的列宽度后,使用stretchColumns指定的列填充剩余的宽度.如果strehColumns指定了多列,这些列会平分剩余的宽度
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:stretchColumns="1"
>
<TableRow
>
<TextView
android:text="第一行第一列"
android:layout_column="1"
/>
<TextView
android:text="第一行第二列"
/>
</TableRow>
<TableRow
>
<TextView
android:text="第二行第一列"
android:layout_column="1"
/>
<TextView
android:text="第二行第二列"
/>
</TableRow>
</TableLayout>
89.介绍AbsoluteLayout布局的用法
AbsoluteLayout称为绝对布局,也可以称为坐标布局.view可以在absoluteLayout布局中通过坐标定位.
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@android:drawable/btn_default"
android:layout_x="13px"
android:layout_y="24px"/>
</AbsoluteLayout>
90.如何动态都是改变absoluteLayout布局中view的位置?
ImageView view=(ImageView) findViewById(R.id.iv1);
//设置view的坐标(layoutParams构造方法的最后2个参数,
//也可以通过LayoutParams.x和LayoutParams.y设置)
AbsoluteLayout.LayoutParams layoutParams=new AbsoluteLayout
.LayoutParams(android.widget.AbsListView.LayoutParams.WRAP_CONTENT,
android.widget.AbsListView.LayoutParams.WRAP_CONT ENT,300, 300);
view.setLayoutParams(layoutParams);
91.如何将当前界面的可视组件以同样的相对位置和大小写保存成png图像文件中?
本题分2部分回答:截取当前界面的组件和保存成png图像文件.首先要调用view.setDrawingCacheEnabled方法打开图像缓存,然后使用view.getDrawingCache方法获取view的bitmap对象.保存成png图像使用biemap.compress方法即可.
将当前界面的可视化组件以同样的相对位置和大小保存在png图像文件即可
View view=getLayoutInflater().inflate(R.layout.main1,null);
//打开图像缓存
view.setDrawingCacheEnabled(true);
//必须要调用measure和layout方法才能成功保存可视组件的截图到png图像文件
//测量view的大小
view.measure(MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED) ,
MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED));
//发送位置和尺寸到view及其所有的子view
view.layout(0,0,view.getMeasuredWidth(),view.getMeasuredHeight());
try {
//获取可视化组件的截图
Bitmap bitmap=view.getDrawingCache();
//将截图保存在sd卡根目录的test.png图像文件中
File file=new File(getCacheDir(),"/test.png");
FileOutputStream fos=new FileOutputStream(file);
//将bitmap对象中的图像数据压缩成png格式的图像数据,
//并将数据保存在test.png文件中
bitmap.compress(CompressFormat.PNG,100,fos);
fos.close();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
92.使用下面代码可以成功的获取布局的bitmap对象吗?并说明原因
View view=getLayoutInflater().inflate(R.layout.main1,null);
//打开图像缓存
view.setDrawingCacheEnabled(true);
Bitmap bitmap=view.getDrawingCache();
不能,因为在 view.getDrawingCache();方法之前需要先主动调用view的测量和布局方法才能成功的获取布局的bitmap对象
93.如何将Android应用程序窗口的背景色设成渐变颜色?
虽然可以使用渐变色的图像来渲染窗口背景,但是更好的选择是使用GradientDrawable类,因为这样更灵活,可以随时变化背景的渐变色.
//设置从上到下的渐变色,上方是红色,下方是黄色
GradientDrawable gradientDrawable=new GradientDrawable(Orientation.TOP_BOTTOM,
new int[]{Color.RED,Color.YELLOW});
//设置当前窗口的渐变背景色
getWindow().setBackgroundDrawable(gradientDrawable);
94.如何在editText中显示提示文本,在提示文本后面可以输入文本?
在EditTest内部提示文本(前部分被锁,不可删除和修改,文本在后部分输入)一般可以通过android:drawableLeft属性来实现.首先做一个带有提示文本的图像(文字当做图像来显示),并通过android:drawableLeft属性指定该图文件的资源id,但是这种方法并不灵活,如果想换提示文本,需要换图像.当然另外一种就是通过android:paddingLeft属性和Canvas来实现.这种方法可以更灵活的处理提示文本.在回答这类问题时建议采用第二种方法
直接在edittext中绘制文本.首先写一个继承自edittext的类,并覆盖onDraw方法,在该方法中绘制提示文本
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
Paint paint=new Paint();
paint.setTextSize(18);
paint.setColor(Color.GRAY);
canvas.drawText("输入提示文本",2,getHeight()/2+5, paint);
super.onDraw(canvas);
}
绘制完文本以后,需要在提示文本后输入文本,这需要使用到paddingleft属性,根据提示文本的宽度设置开始输入到文本的位置,例如android:paddingLeft=100dp,表示从左侧100个dp开始输入文本
95.android:padding、android:layout_margin、android:layout_width、android:layout_height、android:textSize等属性可以设置哪几种尺寸计量单位
目前android sdk支持的尺寸单位有6个:px(像素),in(英寸),mm(毫米),pt(一个物理点1/72英寸),dp(与密度无关的像素),sp(与比例无关的像素),其中px,in,mm,pt,用来设置绝对尺寸的单位,并不会随着屏幕的分辨率的变化而做出相应的调整,而dp和sp会随着分辨率的变化进行调整,所以除了特殊需要,建议使用dp作为尺寸单位,而使用sp作为字体的尺寸单位.
由于手机屏幕分辨率各有不同而且无法调整手机的分辨率,因此android sdk提供了dp和sp这2个尺寸单位来根据分辨率的调整组件和字体的大小。dp和sp都是相对于160dpi的尺寸单位的.160dp相当于每英寸屏幕上有160个物理像素点,一般320*480或类似大小的分辨率的屏幕都是160dpi.因此如果程序运行在160dpi屏幕的手机上,dp、sp和px的效果是一样的,但如果是更高分辨率从的屏幕,如240dpi(480*800),px依然会根据实际物理像素处理,而dp和sp会用当前值乘以一个系数(240/160=1.5)例如,如果2个按钮的android:layout_width属性值分别设为160px和160dp,在320*480分辨率的屏幕上按钮的宽度是完全相同的,但是在480*800分辨率从的屏幕上的宽度为160dp的按钮的实际宽度为240px,会比宽度在160px的按钮宽50%。在不同分辨率屏幕上显示的效果
sp不仅可以按屏幕密度对尺寸进行调整还可以按着用户设置的不同字体调整文字的尺寸使文字以最好的效果显示.因此建议设置文字大小时使用sp,设置其他尺寸使用dp
96.android:layout_gravity属性和android:gravity属性的区别
android:layout_gravity属性指定了当前view在父view中的位置,而android:gravity属性指定了view内容的位置
97.如何重用布局文件
可以使用include标签引用其他布局文件
98.你觉得直接在布局文件的顶层节点使用framelayout好不好,有没有可能使用其他节点取代framela?
无论布局文件的根节点是什么,系统会在上一层生成一个framelayout标签,因此在布局文件的根节点使用framelayout是多余的,但是xml文件又不能没有根节点,因此使用merge代替framelayout,系统在编译xml布局文件不会喂merge生成任何阶段,相当于一个xml文件的节点占位符.merge的意思实际上也是合并2个framela,所以使用merge代替根节点的framelayout可以大大减少framelayout标签的生成.
99.为了研究修改布局的实现,如何查看apk文件中的布局文件源代码呢?
由于apk的ml布局文件是经过编译处理的,无法直接阅读.因此,需要使用反编译工具处理后在阅读这些文件.例如可以先将apk文件解压,然后使用AXMLPrinter2工具对xml布局文件反编译,为了方便,可以将调用AXMLPrinter2的命令行代码放在axml.cmd文件中
100.android:id属性是必须的吗?
android:id属性在xml布局文件中并不一定要知道,当你需要在java代码中通过xml布局代码创建组件属性,在相对布局中组件通过一些属性确定组件之间的相对位置那么久需要知道android:id属性
101.Android sdk支持哪些方式显示富文本信息(不同颜色、大小、并包含图像的文本信息),并简要说明实现方法
1.使用textView组件可以显示富文本信息.在textview组件中可以使用富文本标签显示富文本信息,这种标签类似于HTML标签,但比html标签简单,支持有限的几种显示富文本的方式.如<font>标签用于设置字体和颜色,<b>用于设置粗体.包含这些标签的文本不能直接作为textview方法的参数值,要先使用Html.fromHtml方法将这些文本转换为CharSequene对象,然后再将该对象作为textview.settext方法的参数值.代码:
TextView tv2=(TextView)findViewById(R.id.tv2);
//通过Html.fromHtml方法设置
CharSequence charSequence=Html.fromHtml("你好",new ImageGetter() {
@Override
public Drawable getDrawable(String source) {
//转载图像资源
Drawable drawable=getResources().getDrawable(R.drawable.ic_launcher);
//设置要显示图像的大小
drawable.setBounds(0,0,
drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight());
return drawable;
}
},null);
tv.setText(charSequence);
2.使用webview组件显示html页面
3.继承view类或子类,并覆盖onDraw方法,在该方法直接绘制富文本或图像
4.上面三种方法都支持图文混排效果,但是第一种方法在显示图像时,需要实现imagegetter接口,并通过imageGetter.getDrawable方法返回封装图像资源的Drawable对象.
5.在textview组件中显示图像还可以使用imageSpan对象,imageSpan对象用于封装bitmap对象,并通过spannableString对象封装imageSpan对象,最后将SpannableString对象作为Textview.settext方法的参数将图像显示在textview组件上
代码:
//使用ImageSpan对象在textview组件显示图像
//根据资源id获取资源图像的bitmap对象
Bitmap bitmap=BitmapFactory.decodeResource(getResources(),
R.drawable.icon);
//根据bitmap对象创建imagespan对象
ImageSpan imageSpan=new ImageSpan(this,bitmap);
/创建一个spannableString对象,以便插入用imagespan对象封装的图像
SpannableString spannableString=new SpannableString("ion");
//用imagespan对象替换icon
spannableString.setSpan(imageSpan, 0,1,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
//将图像显示在textview组件上
tv2.setText(spannableString);
102.TextView组件本身可以显示URL,Email等特殊信息,这些特殊信息都会以链接形式显示,在单机链接时会执行相应的动作,如单机URL链接会打开浏览器显示指定的页面.那么如果想在单机链接后弹出我们自定义的activity,应该怎么做.
使用android.text.style.ClickableSpan.onClick方法编写单机url链接时执行的代码.
String text="显示Activity";
SpannableString spannableString2=new SpannableString(text);
spannableString2.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
// TODO Auto-generated method stub
Intent intent=new Intent(MainActivity.this,ClickActivity.class);
startActivity(intent);
}
}, 0,text.length(),Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
TextView tv3=(TextView) findViewById(R.id.tv3);
//设置内容
tv3.setText(spannableString2);
//在单机链接时必须有要执行的动作
tv3.setMovementMethod(LinkMovementMethod.getInstance());
103.如何为textView组件中显示的文本添加背景色?
使用BackgroundColorSpan对象设置文字背景色
//设置带背景色的文本
TextView tv5=(TextView) findViewById(R.id.tv5);
String text1="带背景色的文本";
//将字符串转换为SpannableString对象
SpannableString spannableString3=new SpannableString(text1);
//确定要设置的字符串的start和end
int start=0;
int end=text1.length();
//创建BackgroundColorSpan对象,指定背景色为黄色
BackgroundColorSpan backgroundColorSpan=new
BackgroundColorSpan(Color.YELLOW);
//使用setSpan方法将指定字符串转换为BackgroundColorSpan对象
spannableString3.setSpan(backgroundColorSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv5.setText(spannableString3);
104.同时设置文字色和背景颜色
实现CharacterStyle,
public class ColorSpan extends CharacterStyle{
private int mTextColor;
private int mBackgrounColor;
public ColorSpan(int textColor,int backgroundColor){
mTextColor=textColor;
mBackgrounColor=backgroundColor;
}
//覆盖characterStyle类中的updateDrawState方法,并设置文字和背景颜色
@Override
public void updateDrawState(TextPaint tp) {
// TODO Auto-generated method stub
tp.bgColor=mBackgrounColor;
tp.setColor(mTextColor);
}
}
TextView tv7=(TextView) findViewById(R.id.tv7);
//定义要显示的字符串
String text2="<没有背景><黄色背景>\n\n<蓝色背景,红色文字>";
//设置黄色背景
SpannableString spannableString4=new SpannableString(text2);
int start1=6;
int end1=12;
BackgroundColorSpan backgroundColorSpan2=new
BackgroundColorSpan(Color.YELLOW);
spannableString4.setSpan(backgroundColorSpan2, start1,
end1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
//设置蓝色背景,红色文字
ColorSpan colorSpan=new ColorSpan(Color.RED,Color.BLUE);
// /将指定文本转换为ColorSpan对象
spannableString4.setSpan(colorSpan,
14,text2.length(),Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv7.setText(spannableString4);
105.在设计电子词典,当用户输入单词时,应显示以当前输入单词开头的单词列表.Android sdk那个组件可以实现这个功能?
这道题考查了AutoCompleteTextView组件的用户以及如何将数据库与该组件放在一起使用.当每次在autoCompleteTextView组件中输入新字符串时都需要查询数据库中与当前输入相匹配的记录,并更新Adapter对象
使用AutoCompleteTextView组件可以在文本输入框下方显示一个列表m,可用于显示当前输入字符开头的单词列表.获取以某些字符串开头的单词列表的代码应该放在textWatcherafterTextChanged方法中,在该方法中会不断更新单词列表.
public void afterTextChanged(Editable e){
//查询以当前输入的字符开头的单词
Cursor cursor=database.rawQuery("sql语句");
DictionaryAdapter adapter=new DictionaryAdapter(this,cursor,true);
autoCompleteTextView.setAdapter(dictionaryAdapter);
}
106.在按钮上显示图像的方式有哪些?
Android sdk支持在Button imageButton以及radioButton上显示图像
107.如何用代码动态改变button的大小和位置?
由于button是view的子类,因此可以使用button.layout方法动态改变button的大小和位置.layout方法有4个参数,分别表示button的左上角定点位置和右下角顶点位置.
108.如果想让一个显示图像的按钮在不同的状态显示不同的图像,应该这怎么做?
使用drawable资源可以很容易的实现按钮图像切换的功能.如果只是简单的切换图像状态(如按下,焦点,正常状态)可以使用状态资源,然后通过button按钮的android:background属性指定该状态资源文件的id即可.状态资源文件需要在drawable目录建立一个xml文件,并在select标签指定各种状态对应的状态图像
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- 按钮按下的状态 -->
<item
android:state_pressed="true"
android:drawable=""></item>
<!-- 按钮处于焦点的状态 -->
<item android:state_focused="true">
</item>
<!-- 正常状态 -->
<item android:drawable=""></item>
drawable目录不进可以存储普通的图像资源,还可以存储xml图像资源,图像状态资源就是其中之一.与图像状态资源类似的还有淡入淡出资源和图像基本资源.其中淡入淡出资源只允许在更多的图像定义级别,单需要使用代码进行控制.
淡入淡出
<transition xmlns:android="">
<item android:drawable="">
<item android:drawable="">
</transition>
图像级别资源文件
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/button" android:minLevel="6"
android:maxLevel="10"></item>
<item android:drawable="@drawable/st" android:minLevel="12"
android:maxLevel="20"></item>
</layer-list>
其中图像级别资源中的某一个item标签表示一个级别区间.级别区间用android:minLevel和android:maxLevel属性设置.setImageLevel或setLevel方法设置的级别的某个区间内(android:minLevel<=level<=android:maxLevel)系统就会先用那个区间对应的图像
imageView=(ImageView)findViewById(R.id.imageview_lamp);
//设置level为8
imageView.setImageLevel(8);
109.如何实现图像的半透明度?
可以采用2种实现图像半透明的方法
1.使用Paint.setAlpha方法设置图像的透明度.基本原理是先使用bitmap对象装载图像,然后在view.onDraw方法使用Canvas.drawBitmap方法将bitmap对象绘制在当前的view上
InputStream is=getResources().openRawResource(R.drawable.icon);
//装载图像
Bitmap bitmap = BitmapFactory.decodeStream(is);
proteted void onDraw(Canvas canvas){
Paint paint=new Paint();
paint.setAlpha(180);//0-255
//绘制半透明的图像
canvas.drawBitmap(bitmap,new Ret(0,0,bitmap.getWidth(),bitmap.getHeightr()),new Rect(0,0,bitmap.getWidth(),bitmap.getHeight()),paint);
}
2.可以在不透明的图像上覆盖一层半透明的膜(可以用半透明的imageview实现)
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<!-- 不透明的图像,将被半透明薄膜覆盖 -->
<ImageView
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:src="@drawable/icon"/>
<!-- 半透明的薄膜 -->
<ImageView
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:background="#EFFF"/>
</FrameLayout>
110.如何在imageview组件中显示图像的一部分?
在imageview中显示图像的一部分最直接的方法就是截取图像的一部分显示.当然,使用图像剪切资源也可以实现截取图像的效果
如果想任意截取图像,可以使用biemap.createBitmap方法在原图像的基础上截获某一部分,并创建这部分图像的bitmap对象
Bitmap bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.icon);
//截取(10,10,100,100)范围的图像
Bitmap createBitmap = Bitmap.createBitmap(bitmap,20,20,100,100);
//将截取后的图像显示在imageview组件中
ImageView iv1=(ImageView) findViewById(R.id.iv1);
iv1.setImageBitmap(createBitmap);
如果只想从图像的一端(上,下,左,右)截取图像,也可以使用图像剪切资源.这种资源需要在res/drawable目录中建立一个xml文件,并使用下面的代码从图像左侧开始截取图像,然后需要将图像剪切资源当中普通图像资源使用即可.
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/icon"
将android:clipOrientation设置为vertival,可以从上下方向截取图像
android:clipOrientation="horizontal"
android:gravity="left">
</clip>
只使用图像剪切资源还无法获得图像剪切效果,最后需要使用ClipDraw方法设置截取的百分百
ImageView iv=(ImageView) findViewById(R.id.iv1);
获取imageview的背景图
ClipDrawable drawable=(ClipDrawable)iv.getDrawable();
//从图像左侧截取图像30%
drawable.setLevel(300);
111.如何为图像加上边框?
首先做一个透明的带边框的nine-patch格式图像,如何通过<imageView>标签的android:background属性指定这个图像就可以为图像加上边框.
112.请描述如何使用Matrix对象旋转和缩放图像
使用Matrix.setTotate方法可以旋转图像
Bitmap bitmap=((BitmapDrawable)getResources()
.getDrawable(R.drawable.icon)).getBitmap();
Matrix matrix=new Matrix();
//顺时针旋转45度
matrix.setRotate(45);
//旋转图像,并为旋转后的图像创建新的bitmap对象
bitmap=Bitmap.createBitmap(bitmap,0,0,
bitmap.getWidth(),bitmap.getHeight(),matrix,true);
//在imageview组件中显示旋转后的图像
iv.setImageBitmap(bitmap);
使用Matrix.setScale(0.5f,0.5f)缩放图像
Bitmap bitmap=((BitmapDrawable)getResources()
.getDrawable(R.drawable.icon)).getBitmap();
Matrix matrix=new Matrix();
//图像等比例缩小50%
matrix.setScale((float)0.5,(float)0.5);
//旋转图像,并为旋转后的图像创建新的bitmap对象
bitmap=Bitmap.createBitmap(bitmap,0,0,
bitmap.getWidth(),bitmap.getHeight(),matrix,true);
iv2.setImageBitmap(bitmap);
113.ProgressBar的进度条颜色是否可以修改?如果可以修改,请写出具体的实现代码?
可以改变progressBar的进度条颜色.ProgressBar有三种颜色:背景颜色,第一级进度条颜色,第二季进度条颜色.可以使用图层列表(layer-list)资源修改这三种颜色.首先需要准备3个纯色的图像,然后在res/drawable目录中建立一个progressbar.xml文件,并输入下面的内容
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- 设置背景色图像资源 -->
<item android:id="@android:id/background"
android:drawable="@drawable/icon"></item>
<!-- 设置第二级进度条颜色图像资源 -->
<item android:id="@android:id/secondaryProgress"
android:drawable="@drawable/ic_launcher"></item>
<!-- 设置第一级进度条颜色图像资源 -->
<item android:id="@android:id/progress"
android:drawable="@drawable/sy"></item>
</layer-list>
最后在progressbar标签中使用android:progressDrawable属性指定progressbar.xml文件的资源id.
114.如何实现垂直进度条
Android SDK并没有提供垂直进度条组件,因此,我们可以自己绘制垂直进度条
垂直进度条绘制可以有很多种方法,最简单的方法是使用图像剪切资源.
115.将数据显示在listview组件可以使用baseAdapter的子类,请描述如何使用baseadapter的抽象方法
BaseAdapter有4个抽象方法:getItem,getItemId,getCount,getView,前2个方法分别用于返回object对象和long类型的值.不一定要在这2个方法中编写具体的代码.一般用这2个方法返回与当前列表项相关的对象和列表项的id
116.如何对gridview,listview等列表组件中的数据进行增删改查?
由于列表组件采用mvc模式,因此不能直接通过列表组件对数据进行操作,必须在修改数据后使用notifyDataSetInvalidated方法通知列表组件刷新数据.
首先对数据源的数据进行操作,然后调用baseadapter.notifyDataSetInvalidated方法通知列表组件更新数据.在调用该方法后,系统会调用当前列表的getview方法获取当前的列表项的view镀锡,这样更新当前列表.
117.在listview组件中显示数据库的数据应该如何做?
如果数据简单,可以用simpleCurorAdapter.如果复杂,可以编写一个继承自usorAdapter的类,并在newview方法中创建新的列表项view对象,在bingview方法中为相应的组件赋值.
118.如何改变listview列表项的背景色?
改变列表项选中状态的背景色可以在listview标签的android:listSelector属性,也可以使用listview.setSelector方法.
119.如果要做一个文件管理器,使用gridview组件显示文件列表,有的文件需要显示缩略图(如图像文件,视频文件,apk程序文件)
有很多没有经验的开发人员在.显示文件缩略图都是直接选择装载图像,这样做当然没有问题.但是当图像比较大时,在baseAdapter.getVIew方法中直接装载图像会用GridView组件列表上下滑动时出现卡顿的现象.最好的做法是使用任务队列中然后使用另外一个线程不断的扫描任务队列,并处理未完成的任务.当狐狸完 某个任务,可以刷新gridView组件来表示该图像文件的缩略图.如果列表中的数据来自网络,也可以使用这种方法装载数据.例如微博客户端显示微博列表时会异步从网络下载头像.
如果在BaseAdapter.getView方法中执行耗时澳洲,需要进行异步处理,否则会使队列出现卡顿的现象,可以使用数组或list对象建立任务队列和数据缓冲,getview方法中一旦遇到比较耗时的操作(如显示文件图像缩略图,从网络下载图像)需要将这些操作加入到任务队列中,然后在使用另外一个线程从任务队列取得相应任务,并执行当前的任务.最后需要调用BaseAdapter.notifyDataSetChanged方法刷新列表中的数据(会再次调用BaseAdapter。getviw方法)如果再次显示当前列表项,需要直接从数据缓冲中获取数据.线程可以通过不断你扫描任务队列的方法获取任务.
120.如何为listview组件加上快速滑块,是否可以修改快速滑动图像?
所谓的列表快速滑块就是当你快速滑动列表右侧会出现小方块,这就是列表的快速滑块,如果停止一秒,快速滑块就会消失.
使用布局文件需要将android:fastScrollEnabled属性设置为true,使用java代码需要调用listview.setFastScrollEnabled(true)方法
ListView组件并没有提供修改快速滑块图像的api,因此不能直接修改快速滑块图像,但是可以通过反射技术修改快速滑块图像.
ListView listView=(ListView) findViewById(R.id.lv);
listView.setFastScrollEnabled(true);
listView.setAdapter(new MyAdapter());
//FastScroller.mThumbDrawable变量保存了快速滑块图像,首先通过
//AbsListView.mFastScroller变了获取fastScroller对象
try {
Field field = AbsListView.class
.getDeclaredField("mFastScroller");
field.setAccessible(true);
Object obj=field.get(listView);
//获取fastScroller.mThumbDrawable变量的field对象
field = field.getType().getDeclaredField("mThumbDrawable");
field.setAccessible(true);
//获取fastScroller.mThumbDrawable变量的值
Drawable drawable=(Drawable)field.get(obj);
//装载新的快速滑块图像
drawable=getResources().getDrawable(R.drawable.sy);
//重新设置快速滑块的图像
field.set(obj, drawable);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
121.请尽可能的说出android sdk支持的容器组件
只有是viewGroup的子类
五大布局组件,GridView,Gallery,listView
122.如何使容器内的组件可以水平和垂直滑动?
将scrollView和HorizontalScrollView组件结合视图,就可以实现绘制和水平滑动的效果.所谓的结合就是在srollview组件里面使用HorizontalSrollView,或者在HorizontalScrollview使用scrollView标签
123.如何使Gallery循环显示图像?例如,通过一个数组(长度为10)保存图像文件路径,用gallery组件显示数组中的路径对应的图像.当gallery组件显示到第10个图像后,第11个图像显示第10个图像.
本题实际上是靠BaseAdapter.getview和getcount方法的应用技巧.原则上getcount方法返回小于等于数据源中的个数,但为了产生循环效果需要改变主人公规则.时BaseAdapter.getCount返回一个较大的值(Integer.Max_Value)当baseadapter.getview方法不能直接通过position参数获得的数据的位置,需要将position参数对10取余,并将余数作为新的数据位置
124.Android可以动态引用组件吗?如果可以,请尽可能的说出android支持哪些可动态引用的组件类型
引用组件分为静态和动态.静态引用就是将组件连同主程序一起封装在编译后的目标文件中,如vc的lib文件.动态引用就是指主程序和组件是分离的组件可以单独升级和卸载.
可以动态引用组件,android应用程序可以动态引用的组件类型包括未安装的apk文件,包含classes.dex文件的jar文件,JavaScript脚本,四大应用程序租金
125.请描述如何将可视化组件封装在jar文件中以及如何通过java代码适应不同的屏幕分辨率
jar文件可以封装很多类型的组件,如可视化组件(对androidsdk原生组件的扩展),四大组件.每种组件在使用时都有一些注意事项这在使用被封装在jar文件里面的组件一定要注意.可以直接将可视组件的lass文件放到jar文件中,不过组件使用的资源文件要放到主工程的res目录的相关子目录.在xml布局文件中使用组件要指定全名
虽然组件中可以引用R类中的资源,但是不建议这么做.因为这样做了在使用组件时主程序必须包含这些资源,使用和发布组件比较麻烦,也不灵活如果组件中确实要使用一些资源,最好提高一些属性,由使用者负责指定这些资源.
自定义可视组件还要考虑屏幕分辨率的问题.虽然不建议使用资源文件,也不能用dp或sp设置与分辨率无关的单位.因此需要使用下面的java代码将dp或sp转换为实际的像素点
DisplayMetrics displayMetrics=new DisplayMetrics();
displayMetrics.setToDefaults();
//根据像素分辨率将dp转换成像素点
Int pixel=(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dip,displayMetrics);
126.如果想编写一个自定义可视组件,你打算怎么做?
开发自定义可视组件一般可使用三种模式
1.扩展现有的组件.如组件类可以直接继承textview
2.组合多种组件。如组件类可以直接继承自容器可将多个组件添加到组件类中
3.直接从view继承.此类从0开始编写
127.Android支持的四大应用程序组件可以封装在jar文件中吗?使用时应该注意什么?
四大应用程序组件可以放在jar文件中,并在android工程中静态引用jar文件虽然四大应用程序组件相关的class文件都封装在jar文件,但是使用这些组件仍然要注册在清单文件中,否则无法使用这些组件.
128如何动态装载apk文件(未安装)中的类?
要注意的是本题要求动态装载未安装的apk文件.由于android程序运行在Dalivk虚拟机上,而不是传统的jvm上,因此android程序不能动态装载传统的jar文件,而apk文件已经编译成dalivk虚拟机格式因此可以被动态装载
动态装载未安装的apk文件中的类的java代码
//my.apk表示要动态装载的apk文件,my_temp.apk表示为了优化
//临时产生的apk文件(系统处理)
DexFile dexFile=dalvik.system.DexFile
.loadDex("/sdcard/my.apk","/sdard/my_temp.apk",0);
//装载apk文件中的类,并创造该类的对象实例
Object object=dexFile
.loadClass("mobile.android.file.explorer.width.Test",null).newInstance();
//使用java反射技术获取getname方法的method对象
Method method=object.getClass().getDeclaredMethod("getName",null);
//调用类中的方法,并获取方法返回值
String result=String.valueOf(method.invoke(object,null));
129.下面的代码是包含在mywidget.apk文件中的java接口和java类
package mobile.android.file.explorer.widget;
//java接口代码
public interface MyInterface {
String getName();
}
package mobile.android.file.explorer.widget;
//java类代码
public class MyClass implements MyInterface{
public String getName() {
// TODO Auto-generated method stub
return "我的名字是Jobs";
}使用下面的代码可以成功调用getname方法吗?为什么?
DexFile dexFile=dalvik.system.DexFile.loadDex("/sdcard/mywidget.apk",
"/sdcard/mywidget_temp.apk",0);
Object obj=dexFile.loadClass("mobile.android.file.explorer.widget.TestAPK",
null).newInstance();
Method method=obj.getClass().getDeclaredMethod("getName",null);
String result=String.valueOf(method.invoke(obj, null));
如果apk文件中的类实现了接口,或继承了其他的类,必须同时装载这些接口和类,否则无法成功创建该类的对象.不能成功调用getName方法.因为没有装载MyInterface接口,可按下面的代码调用getname方法
DexFile dexFile=dalvik.system.DexFile.loadDex("/sdcard/mywidget.apk",
"/sdcard/mywidget_temp.apk",0);
//装载接口
dexFile.loadClass("mobile.android.file.explorer.widget.MyInterface",
null);
Object obj=dexFile.loadClass("mobile.android.file.explorer.widget.TestAPK",
null).newInstance();
//object对象强转为MyInterfae
MyInterface interface1=(MyInterface)obj;
//使用强类型调用getname方法
String name=interface1.getName();
130.android应用程序是否可以动态引用jar文件?
该jar文件是属于哪类的jar.传统jar文件(包含.class)由于是基于jvm格式的,因此无法由android应用查询调用.不过jar文件中只要包含dalivk虚拟机格式的二进制代码就可以被android应用程序动态调用.apk文件中的classes.dex就是dalivk虚拟机格式的二进制文件.
jvm格式的jar文件不能被androi应用程序动态调用,但包含了classes.dex文件的jar文件可以被android应用程序动态调用.可以使用下面的命令将lasses.dex文件打包成jar文件.
jar cvf my.jar classes.dex
131.如何判断包含某个activity action的android应用程序是否安装?
将包含activity ation的应用程序作为组件使用时,首先需要判断该应用程序是否被安装.如果未被安装改应用程序,应先要求用户安装改应用程序.如何在调用应用程序的activity.
调用manager.queryIntentActivities方法可以查询系统中是否注册了某个activity ation,如果未返回任何结果,说明该系统没有安装包含指定activity ation的apk。
PackageManager manager=getPackageManager();
//指定要查找的activity action:com.android.phone.action.TOUCH_DIALER
Intent intent=new Intent("com.android.phone.action.TOUCH_DIALER");
//在系统中查询指定的activityu ation
List<ResolveInfo> infos=manager.
queryIntentActivities(intent, PackageManager.GET_INTENT_FILTERS);
//如果没有返回任何结果,表明系统中没有指定的activity action
if(infos.size()==0){
Log.d("Ativity Action", "activity action不存在");
}
不仅Activity可以作为组件使用,servie,Broadast reeiver和Content provider同样也可以作为组件使用.因此,除了activity外,其他三个应用程序组件也需要判断他们是否已经安装
BroadastReceiver
PackageManager manager=getPackageManager();
//指定要查找的boradcast action
Intent intent=new Intent("mobile.android.MYBROADCAST");
//在系统中查询指定的 broadcast action
List<ResolveInfo> infos=manager.
queryBroadcastReceivers(intent, PackageManager.GET_INTENT_FILTERS);
//如果没有返回任何结果,表明系统中没有指定的activity action
if(infos.size()==0){
Log.d("broadcast Action", "broadcasr action不存在");
}
service指的是aidl service,也就是一个允许android应用程序访问另外一个应用程序中的类,aidl servie在调用时需要使用bindservice方法进行绑定.如果aidl service不存在,则绑定失败,也就是说bingservice方法会返回false。因此通过bindservie方法可以判断指定的aidl servie是否存在
//返回true,表示绑定成功,否则返回失败
if(!bindService(new Intent("mobile.android.IMyservice"),
serviceConnection,Context.BIND_AUTO_CREATE)){
Log.d("aidl servie","不存在");
}
判断指定的Content provider是否存在只需要根据ContentResolver对象的相应方法的返回值进行判断即可.
//返回true,表示绑定成功,否则返回失败
if(!bindService(new Intent("mobile.android.IMyservice"),
serviceConnection,Context.BIND_AUTO_CREATE)){
Log.d("aidl servie","不存在");
}
132.在android应用程序中java与JavaScript如何交互?
在android应用程序中可以使Java代码和JavaScript脚本进行交互,所谓的交互就是互相调用以及传送数据.这项技术的核心就是webview组件,该组件不进可以执行javascript脚本,也允许在js脚本中执行java代码.由于android可动态执行,并且执行java代码,所在在JavaScript也常被当做android的动态组件使用.
WebView webView=new WebView(this);
WebSettings webSettings=webView.getSettings();
//必须执行下面的语句,否则webview无法执行js脚本
webSettings.setJavaScriptEnabled(true);
webView.setWebChromeClient(new WebChromeClient());
String s="";
//s为string类型变量,保存javascript脚本
webView.loadDataWithBaseURL(null,s,"text/html","utf-8",null);
//在java代码和js脚本之间传递数据以及使用js脚
//本执行java代码需要使用webview.addJavascriptInterfae方法添加
//在js中调用的java代码
webView.addJavascriptInterface(new Object(){
//可在js脚本中调用的java方法
public void move(int x,int y){
//java代码
}
},"demo");//demo为js中可访问的对象,通过该对象调用move
在js脚本中调用move方法
window.demo.move(20,100);
133.请描述ndk方法的命名规则,并描述ndk方法中前2个参数的作用
假设调用ndk方法的java类是mobile.android.HelloWorldJNI,在该类型中实际访问的本地方法名是process,返回值是String,没有参数m那么ndk方法的定义如下
jstring Java_mobile_android_HelloWroldJNI_proess(JNIEnv *env,jobjet obj){
}
NDK方法必须以java开头后面跟调用NDK方法的java全类名(package+lass)最后才是实际的方法名.各部分之间用下划线分隔.所有的你的看方法的前2个参数类型必须是JNIEnv*和jobjet.JNIEnv*表示当前ndk环境的对象指针,可以通过该参数访问ndk中的内置成员.jobject表示调用当前ndk方法的java对象,可以用该参数值访问调用当前ndk方法的java对象的成员.
134.如何用java代码让android market显示指定的程序以使用用户下载?
如果使用四大应用程序组件作为动态组件,当这些组件未安装时需要提示用户下载太慢.包含这些组件的apk程序被发布到android market上时可以用程序直接调用内置在手机上的android market程序进行下载.本题是考查我们是否了解如何用java代码访问android market.在android系统中很多内置的应用汇包含若干个activity action。因此,可以通过ativity ation直接调用其他应用程序的窗口,访问android market就采用了这样一种方式.
让android market直接显示我们所期望的程序以供用户下载可以通过应用程序名称或id进行查询
Uri uri=Uri.parse("market://searh:q=应用名称");
Intent intent=new Intent(Intent.ACTION_VIEW,uri);
startActivity(intent);
根据应用程序id(也就是应用程序的package name)查找应用程序的代码
//mobile.android.library为应用程序的package name
Uri uri=Uri.parse("market://details?id=mobile.android.library");
Intent intent=new Intent(Intent.ACTION_VIEW,uri);
startActivity(intent);
135.请写出安装apk程序的代码
Intent intent=new Intent(Intent.ACTION_VIEW);
//指定apk文件的路径
String filepath="/sdcard/FileExplorer.apk";
//指定文件类型
intent.setDataAndType(Uri.parse("file://"+filepath),
"application/vnd.android.package-archive");
//执行这条语句弹出安装界面
startActivity(intent);
136.如何配置Activity才能让程序启动时将该activity作为启动窗口?
Android系统在启动一个应用程序时会调用该应用程序中可接收的MAIN动作(一个系统的activity action)的activity,因此,只要在定义activity时指定MAIN动作就可以使该Ativity在应用程序时被调用.但要注意,如果androidManifest.xml文件中如果有多个可接收MAIN动作的activity,系统只会启动第一个可接收main动作的activity
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
定义MAIN动作
<action android:name="android.intent.action.MAIN" />
必须指定ategory,否则无法启动该activity
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
137.如何将Activity变成半透明的对话框
在定义activity时指定Theme.Dialog主题可以将Ativity设置成对话框风格.通过修改Theme.Dialog主题的android:windowsBackground属性值可以改变activity的背景图像.如果背景图像使用半透明的图像,则activity就会变成半透明的对话框.为了修改android:windowsBackground属性,可以定义一个新的主题,该主题继承自Theme.dialog
<style name="MyTheme" parent="@android:style/Theme.Dialog">
<item name="android:windowBackground">@drawable/ic_launcher</item>
</style>
然后在定义activiy时直接指定MyTheme即可
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/MyTheme"
138.如何设置activity显示和关闭时的动画效果
通过overridePendingTransition方法可以设置activity显示和关闭的动画效果.首先在res/anim目录建立相应的动画资源文件,然后使用下面的代码在显示和关闭activity时添加动画效果.
Intent intent=new Intent(this,MainActivity.class);
startActivity(intent);
//通过淡入淡出小郭显示和关闭activity
overridePendingTransition(R.anim.fade_in,R.anim.fade_out);
139.请描述Content provider url有哪几部分组件
Content provider url和http url类似.
有4部分:
1.content://相当于http url的http://
2.authority:相当于httpURL中的域名
3.路径(path)
4.参数(param)
假如有如下的ontent provider URL其中最后面的数字可以任意编号
content://mobile.android.mydata/product/20
其中authority是mobile.android.mydata,path是produt,param是20
请描述开发一个Content provider的步骤
开发ontent provider的步骤
1.编写一个类,继承contentProvider
2.实现contentProvider的所有抽象方法
3.定义content Provider的URl。URL的形式为content://android/path/param.一般情况下authority建议使用域名因为域名是唯一的不会重复
Android的标准对话框最多可以有几个按钮,并写出显示对话框按钮的方法
Android的标准对话框最多可以有3个按钮.AlertDialog类显示这3个按钮的方法是setButton、setButton2、setButton3.另外AlertDialog.Builder类也提供了另外3个更直观的显示按钮方法:setPositiveButton、setNeutralButton和setNegativeButton.AlertDialog和AlertDialog.Builder提供的3个显示按钮方法的调用顺序是可以任意的,但是无论调用顺序是什么,使用setPositiveButton方法设置的按钮总会排在左起第一位,使用setNeutralButton的方法设置总会排在第二位,使用setNegativeButton方法设置的按钮排在第三位.
如何响应android标准对应的按钮单击事件?
通过AlertDialog.Builder.setPositiveButton、setNeutralButton和setNegativeButton方法可以设置按钮单击事件监听对象.
请描述以下进度条对话框(ProgressDialog)的使用方法
进度条对话框通过ProgressDialog类实现,该类是AlertDialog的子类,但是与AlertDialog不同,我们可以直接使用new关键字创建ProgressDialog对象
ProgressDialog dialog=new ProgressDialog(this);
dialog.setIcon(android.R.drawable.progress_horizontal);
dialog.setTitle("正在处理数据...");
dialog.setMessage("请稍后");
//设置进度条对话框的风格
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
//设置进度条对话框的最大值
dialog.setMax(100);
//设置进度条的当前进度
dialog.setProgress(20);
dialog.setButton("暂停",new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
dialog.setButton2("取消",new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
dialog.show();
如果想将进度条样式改为圆环可以将setProgressStyle方法的参数值改为ProgressDialog.STYLE_SPINNER.但是要注意圆形进度条只是一个不断旋转的动画并没有实际的进度,一般会用在无法准确的获取进度条的情况下因此,setMax和setProgress方法对于圆形进度条没有任何意义.
默认情况下对话框都是屏幕中心显示,这个位置是否可以改变,如果可以改变,应该怎么做?
使用setGravity方法可以设置对话框的位置
AlertDialog alertDialog=new AlertDialog
.Builder(this).setMessage("在顶端显示对话框")
.setPositiveButton("确定",null).create();
Window window=alertDialog.getWindow();
//调用setGravity方法使对话狂在屏幕左上角
window.setGravity(Gravity.TOP| Gravity.LEFT);
alertDialog.show();
请描述一下在状态栏上显示notification(通知)的实现步骤,并写出相应的java代码.
1.通过getSysteSERVICE方法获取一个Notification对象
2.创建一个Notification对象.每一个Notification对应一个Notification对象.在这一步需要设置显示在屏幕上方状态栏的通知信息、通知消息前方的图像资源id和发出通知的时间,一般为当前时间
3.由于notification可以与应用程序脱离,也就是即使应用程序关闭了,notification任然会显示在状态栏.当应用程序再次启动后,又快又重新控制这些notification,如清楚或替换他们。因此需要创建一个pendingIntent对象。该对象由android系统负责维护,因此,在应用程序关闭,该对象不会被释放.
4.使用notification的setLatestEventinfo方法设置notification的详细信息.
5.使用notificationManager的notifi方法显示notification信息.在这一步需要指定标识notification的唯一id。这id必须相对于notification对象是唯一的,否则就会覆盖相同id的notification
//第一步
NotificationManager notificationManager=(NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
//第二步
Notification notification=new Notification(android.R.drawable.ic_delete,
"您有新消息了",System.currentTimeMillis());
//第三步
PendingIntent intent=PendingIntent.getActivity(this,0,getIntent(),0);
//第四步
notification.setLatestEventInfo(this, "天气预报","晴转多云",
intent);
//第五步
notificationManager.notify(R.drawable.ic_launcher,notification);
点击通知(notifiation)弹出activity
PendingIntent intent=PendingIntent.getActivity(this,0,new Intent(this,Main.class),0);
notification.setLatestEventInfo(this, "天气预报","晴转多云",
intent);
notificationManager.notify(R.drawable.ic_launcher,notification);
点击通知不仅仅可以发生activity,广播和服务也可以发送
android支持哪几种菜单
选项菜单,上下文菜单,子菜单
哪些android支持的菜单项可以显示图像
只有选项菜单项可以显示图像,上下文菜单和子菜单的菜单条可以显示图像,但菜单项不能显示图像
请描述如何为1个activity添加选项菜单
实现activity.onCreateOptionsMenu方法,并利用menu对象添加菜单
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
menu.add(1,1,1,"菜单项1");
menu.add(1,2,2,"菜单项2");
menu.add(1,3,3,"菜单项3");
return true;
}
添加上下文菜单
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
// TODO Auto-generated method stub
menu.add(1,1,1,"上下文菜单项1");
menu.add(1,2,2,"上下文菜单项2");
menu.add(1,3,3,"上下文菜单项3");
super.onCreateContextMenu(menu, v, menuInfo);
}然后使用registerforContentMenu方法将上下文菜单与可视组件绑定
Button button=(Button)findViewById(R.id.bt_id);
registerForContextMenu(button);长按button就会弹出在oncreateContentmenu方法中创建的上下文菜单
在单击菜单项时,除了使用java代码显示一个activity外,还可以用什么方法显示activity
本题考查了我们是否了解一个activity可以与菜单项关联,从而单击该菜单项会自动显示与其绑定的activity,但是要注意,如果设置了菜单项的单击事件,并且单击事件返回true,则与菜单项关联的activity将失效,
可以将一个activity与某个菜单项关联,在单机该的会自动显示activity
MenuItem add = menu.add(1,1,1,"上下文菜单项1");
add.setIntent(new Intent(this,MenuActivity.class));
响应菜单项目单击事件有哪些方法
有如下3个方法可以响应菜单项的单击事件
onOptionsItemSelected
onMenuItemSelected
add.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
// TODO Auto-generated method stub
return false;
}
});
既然有3个响应菜单单击事件的方法,就会产生一个问题:如果同时使用这三种方法,他们都会起作用吗?实际上当onMenuItemClick方法返回true时,另外2种方法就失效了。如果未设置菜单项的单击事件,而同时使用另外2种方法响应单击事件的方式,系统会根据在onMenuItemSelected方法调用父类activity类的onmenuitemselected方法的位置来决定先调用onoptionsitemselected方法还是先调用onmenuitemselected方法
android支持哪些文件存储技术?
使用sharedPreferecees保存key-value对类型的数据,流文件存储(使用openFileoutput和openFileinput方法或fileinputstream和fileoutputstream对象),xml半结构化存储,用json保存数组或对象,用数据库保存结构化数据,用第三方的面向对象数据库直接保存java对象.
sharedPreferences是否可以将数据文件保存在sd卡上?
SharedPreferences原则上只能保存在当前应用程序的私有的shared_prefs目录,不过不是绝对的。可以利用反射技术改变系统内定的文件保存路径
可以将数据文件保存在sd卡上,但由于sharedPreferences未提供改变文件保存路径的aoi,
sharedPreferenes文件可以保存图像数据吗?
原则上不能保存,但可以采用编码的方式将任何二进制数据换成字符串形式,从而可以将二进制数据保存在sharedPrefrecesces中.将二进制的数据转换成字符串的编码格式采用了Base64
如何通过PrefereneActivity类实现一个设置界面.
PreferenceActivity是activity的子类,可以方便的实现设置界面,preferenceActivity会通过一个xml配置文件来描述设置界面的设置项,并且系统会自动保存当前设置项的最后状态.通过一个xml配置文件来描述设置界面的设置项,并且系统会自动保存当前设置项的最后状态.preferenceActivity预定意了一些专用组件,可以实现常用的设置项目
CheckBoxPreference:对应checkboxPreference标签,单击该设置会创建一个checkbox组件
EdittextPreference
listPreference:listview
首先需要编写一个继承自preferenceActivity的子类,然后在xml目录建议一个用于描述设置界面的xml文件
preferene_setting.xml,并且在该文件中使用preferenceactivity预定义的组件对设置界面布局
请说出prefereneactivity保存数据文件的路径m文件的命名规则。默认的文件名是否可以更改
由于preferenceActivity内部使用了sharedpreferences对象保存数据,因此在默认情况下仍然会将数据保存在手机内存中的shared_prefs目录.默认文件名为packagename_preferences.xml.如果当前窗口属于net.blogjava.mobile包,则默认文件名为net.blogjava.moblie_preferences.xml.可以通过preferenceManager.setSharedPreferencesName方法修改默认的文件名
getPreferenceManager().setSharedPreferencesName("setting");
如何使用imageview组件装载sd卡中图像文件?
ImageView imageView=new ImageView(this);
imageView.setImageDrawable(Drawable.createFromPath("/sdcard/face.png"));
androidsdl支持读取xml吗?
只支持采用sax技术读取xml.
请描述sax引擎分析xml文档的过程
sax引擎需要处理如下5个分析点,也可称为分析事件
开始分析xml文件.该分析点表示sax引擎刚开始处理xml文件,还没有读取xml文件的内容.该分析点对应于
DefaultHandler.startDocument方法,可以在该方法做一些初始化的工作
开始处理每一个xml元素,也就是遇到<product>、<item>这样的起始标记.sax引擎每次扫描到新的xml元素的起始标记会触发这个分析事件,对应的事件方法是startElement。在该方法可以获得当前元素的名称、元素属性的相关信息.
处理完一个xml元素,也就是遇到</product>、</item>这样的结束标记。该分析点对应的事件方法是endElement。在该事件中可以获得当前处理完的元素的全部信息
处理完xml文件。如果sax引擎将整个xml文件的内容扫描完了,就到了这个分析点,该分析点对应的事件方法是endDocument。该事件方法可能不是必需的,如果最后还有一些收尾工作,如释放一些资源,可以在该方法完成.
读取字符串分析.这是最重要的环境.虽然读取了xml文件中的所有内容,但是没有保存这些内容.而这个分析点所对应的haracters事件方法的主要作用就是保存sax引擎读取的xml文件中的内容.更准确的是保存xml元素的文本,也就是product节点中的内容
描述json文档的格式
json是一种轻量型的数据存储和传输方式,可以使用自动重形式保存数组和对象属性值。数组使用中括号[]对象使用大括号
[{'name':'地球','satellite_count':'1','satellite_names':'moon'},
{'name':'火星','satellite_count':'2','satellite_names':'moon1'}
]
写出解析下面json格式文档的java代码,并将对象的属性值输出到logcat视图中
如何管理sqlite数据库
sqlite官方提供了一个命令行工具.在这个命令行工具中可以执行2种命令:sql命令和控制台命令.其实sql命令必须以;号为结尾,在控制台命令必须以实心点(.)开头,如.help.
为了更方便的管理,也可以使用第三方的可视化数据库管理工具,如sqliteExpertProfessional就是一种比较流行的基于windows平台的sqlite数据库管理工具。
sqllite数据库如何查询表table的第2条到第30条记录
sqlite和mysql一样,select语句也支持limit字句
select * from table limit 19,11
假设有一个table表,该表中有id和name字段,要在table表中插入一条id=1,name=nill的记录.如果id=1不存在,则正常插入.如果存在,则更新name字段的值
本题使用insert语句肯定不行,insert语句当遇到约束冲突后会抛异常.在sqlite提供了replace语句,可以使用replae来替换insert
replace into table(id,name) value(1,'bill');
如何将table表结构和数据复制到table2上
create table table2 as select * from table
写出创建视图的sql语句
create view if not exists view as select * from table1
请说出sqlite函数abs(X)函数的返回值有几种情况?
由于abs函数会尝试将当前字段值转换成整型,再取绝对值.因此只要当前字段值可以转换成数值型的值,abs函数就可以成功返回正确的结果.但是要考虑abs函数抛异常的情况
X为正值和0,abs(x)函数返回x本身
x为负值,abs(x)函数返回x的绝对值,也就是-x
x为null,返回null
x为字符串、blob等不能转换为数值的类型,abs(X)函数返回0,
如果x值超出64位整数值范围,abs(x)函数会抛出一个溢出错误
如何获取最近一次执行sql语句所影响的记录行数,并写出相应的sql语句.
changes函数的用法
insert into table values(1,'bill');
--返回insert语句影响的记录行数
select changes();
如何使用一条sql语句查询不为null的字段值
通过coalesce函数可以返回第一个不为null的字段值
select coalesce(name,id) as value from table
ifnull函数与coalesce函数的功能相同,只是ifnull函数只有2个参数,相当于有2个参数的coalesce函数
select ifnull(name,id)as value from table
请说出length(X)函数在以下几种情况返回怎样的值?
1.X是字符串 2.x是bolb类型的值 3.X为null 4.x为数值型
返回字符串中包含的字符数 返回二进制数据中包含的字节数
返回null length会将x作为字符串处理.例如length(123)的值就是3
请分别使用like字句和like函数查询table中name字段值包含null的记录
使用like函数的sql
select * from table where like('%bill%',name);
使用like子句的sql
select * from table1 where name like '%bill%'
请描述nullif(X,Y)函数的用法
当x和y不同时,nulluif返回x。如果x和y相同,nullif返回null
select nullif(20,30)
select nullif(20,20)
请描述substr函数的用法
substr函数用于截取字符串的子字符串.substr有substr(X,Y)和substr(X,Y,Z)两种形式.
其中x是原字符串,y是要截取的字符串的第一个字符在原字符串的位置,z表示要截取的子字符串的毒.如果不指定z,substr会截取y以后的所有字符串.如果y为正值,表示的起始位置从原字符串的左侧开始,如果是负值,表示的起始位置从原字符串的右侧开始.如果z为负值,会取z的绝对值
select substr('abcdefg',2):bcdefg
select substr('abcdefg',2,3)bcd
select substr('abdefg',-2):fg
select substr('abdefg',-4,2):de
如何知道当前字段属于什么类型?
select typeof(fieldl)from table1
sqlite支持哪几个日期和时间函数
date,time,datetime,julianday和strftime
如果当前日期是2012-11-01将年-1,月+1输出日期是2011-12-01
本题考查我们是否了解日期和时间函数经常遇到的调节器(Modifier)调节器可以在日期和时间上进行微调,可以通过调节器很容易的对年,月,日,时,分,秒进行加减操作
select data('2012-11-01','-1 years','+1 months');
使用date函数输出当前日期和当前时间
select date('now')
请描述一下SQLiteOpenHelper.onCreate和SqliteOpenHelper.onUpgrade在说明情况下执行?
sqliteopenHelper类实际上是一个数据库框架,主要用于操作数据库和升级数据库.其实oncreate和onUpgrade是该类的2个抽象方法,一般负责数据库的创建和升级
如果数据库文件不存在调用oncrete方法,在该方法中创建数据库表,视图等组件
如果数据库文件存在,调用onUpgrade方法,调用该方法,会更新数据库版本号
请解释一下什么是db40数据库
db40(database for ibjects)是一个嵌入式的开源面向对象数据库,可以使用在java和.net平台上.不同于其他对象持久化框架,db40是基于对象的数据库,操作的数据本身是对象.而对象持久化框架需要一个映射文件将关系型数据库与对象进行关系,这样不仅使用麻烦,而且也无法处理更复杂的问题
db40的特点
存储时不改变类特征,使之易于存储
与java,。net无缝绑定
自动数据绑定
使用简单,只需要一个jar或dll文件
一个数据库文件
直接通过对象实例查询
创建scoket对象至少要指定哪些信息?
创建Scoket对象至少需要知道ip(域名)和端口号
Socket socket=new Socket("www.microsoft.com",80);
请写出使用scoket连接服务器(ip:192.168.17.100,端口号:8080)以及与服务端交互的java代码
本题考查我们是否了解socket的用法。与服务器交互实际上就是从服务器读取数据以及向服务器写数据.
Socket socket=new Socket("192.168.17.100",8080);
OutputStream os=socket.getOutputStream();
OutputStreamWriter osw=new OutputStreamWriter(os);
BufferedWriter bw=new BufferedWriter(osw);
//向数据库写数据
bw.write("hello world\r\n\r\n");
bw.flush();
InputStream is=socket.getInputStream();
InputStreamReader isr=new InputStreamReader(is);
BufferedReader br=new BufferedReader(isr);
String s="";
//从服务器读数据
while((s=br.readLine())!=null){
Log.d("line", s);
}
os.close();
is.close();
socket.close();
除了直接调用Socket.close方法会使网络连接关闭,还会有其他情况可以是网络连接关闭
1.直接调用Socket.close
2.只要InputStream和OutputStream有一个关闭,则网络连接自动关闭
3.在程序退出时网络连接自动关闭
4.将Socket对象设为null或在Socket对象未被是否的情况下将新的socket对象覆盖,有dalivk虚拟机垃圾回收器回收为socket对象分配的内存空间时自动关闭网络连接
虽然这4种方法都可以达到同样的目的,但一个健壮的网络程序关闭最好使用第一种和第二种.这是因为第三四种一般不会马上关闭网络连接.如果是这样的话,对于某些应用程序,将会遗留大量无用的网络连接,这些网络连接会占用大量的系统资源.
判断socket是否关闭
Socket socket=new Socket("192.168.17.100",8080);
socket.isClosed();判断是否关闭
socket.isConnected();判断socket对象是否连接成功
其实isConnected方法判断的并不是当前socket对象连接状态,而是socket对象是否曾经成功连接过,也就是说要socket.isClosed()=false且socket.isConnected()=true,socket对象才处于连接状态
如何使用Soket.connet方法连接服务器
Socket socket=new Socket();
socket.connect(new InetSocketAddress("192.168.18.100",8080));
如何设置Socket连接的超时时间
通过socket.connect方法可以设置超时
Socket socket=new Socket();
socket.connect(new InetSocketAddress("192.168.18.100",8080),2000);
客户端Socket的超时是指客户端通过socket和服务器进行通信的过程中,由于网络延迟,网络阻塞等原因,造成服务器未及时响应客户端的一种现象.在一段时间后,客户端由于未收到服务器的响应而抛出一个超时错误,其中客户端所等待的时间就是超时时间.
对于客户端来说,只有2个地方涉及到超时:一个是在连接服务器时,另外一个是在连接服务器成功后,接收服务器发过来的数据.因此客户端超时也分为2种类型:连接超时和读取超时.
1.连接超时:只有通过Socket.connect方法才能指定连接超时的世界,由于使用该方法必须指定ip和端口,因此无效的端口和ip将会抛超时错误.
2.读取数据超时
Socket.setSoTimeout(5000);
使用socket成功连接服务器后,如何让获取服务器的ip和域名
Socket socket=new Socket("192.168.10.1",80);
//获取服务器的id
socket.getInetAddress().getHostAddress();
//获取服务器的域名
socket.getInetAddress().getHostName();
除了Socket.getInerAddress方法,Socket类还有很多的getter方法,通过这些getter方法可以获取各种信息
public SocketAddress getRemoteSoketAddress()
该方法是将getInetAddress和getPort合在一起,利用这个方法可以同时得到服务器的ip和端口号.但是这个方法返回了一个socketAddress对象,这个对象只能作为connect方法的参数用于连接服务器,而要想获得服务器的ip和端口号,必须将socketAddress转换为他的子类inetSocketAddress
Socket socket=new Socket("192.168.10.1",80);
((InetSocketAddress)socket.getRemoteSocketAddress()).getHostName();
((InetSocketAddress)socket.getRemoteSocketAddress()).getPort();
public InetAddress getLoalAddress():
这个方法返回了本机的inetAddress对象.通过这个方法可以得到本机的ip和机器名,当本机绑定了多个ip时,socket对象使用哪一个ip连接服务器,就返回哪个ip.如果本机使用adsl上网,并且通过socket对象连接到intenrnet上的某一个ip或域名商,则getLocaladdress将返还adsl连接临时绑定的ip
Socket socket=new Socket();
socket.connect(new InetSocketAddress("www.microsoft.com",80));
String hostAddress = socket.getLocalAddress().getHostAddress();
String hostName = socket.getLocalAddress().getHostName();
public int getLocalPort()
通过这个方法可以得到socket对象绑定的本机的一个端口号.如果未绑定端口号,则返回一个从1024到65535之间的随机数.因此使用这个方法可能每次得到的端口号不一样
如果在调用Socket.close方法时还有未发出的数据,这些数据将被丢失,为了尽量保证在调用Socket.close方法后将所有的数据都发往服务端,应该如何做?
当调用socket.close方法时会立即返回,所有未发送的数据将被丢失,为了避免这类事情发送,可以使用Socket选项设置关闭延迟时间,这样可以留出足够的时间用来发送数据
设置调用Socket.close方法30秒后关闭socket连接
socket.setSoLinger(true,30);
请写出创建服务端Socket的java代码
ServerSocket socket=new ServerSocket(1234);
如何设置服务端Socket的请求队列长度
ServerSocket socket=new ServerSocket(1234,100);
在编写服务端程序时,一般会通过多线程来同时处理多个客户端请求.也就是说,使用一个线程来接收客户端请求当接到一个请求后(一个socket对象),就会创建一个新的线程,将这个客户端请求交给这个新线程狐狸.而那个接收客户端请求的线程继续接收客户端请求.
请说出android支持哪些访问http资源的方法
一般可以使用http api直接访问http资源,但是也可以使用Socket发送http请求.
(1):界面显示:setContentView(layout布局文件),然后activity实现了OnClickListener,用户做操作我们就能收到用户操作的内容然后反馈给用户
(2)和用户进行交互:四大组件之一,作为一个界面的容器,一个可以与用户交互的界面,他能与用户交互是因为他是Context的子类,同时实现了window.callback(window.callback(窗口的回调事件)有一个dispatchTouchEvent事件,所以他能分发,既然window.callback他能分发事件,他就可以处理这些事件)和keyevent.callback(按键的回调事件,),可以处理与窗体交互的事件
servie也是Context的子类,但是他没有实现Window.callback(窗口回调事件)和keyevent.callback(按键的回调事件),所以他不能和用户交互
(3):开发举例说明:以前开发常用的有 FragmentActivity,ListActivity,PreferenceActivity,TabActivity等等,如果开发中遇到界面有共同的特点,布局大同小异,功能类似,我们就可以定义一个BaseActivity,这样代码优化比较好
为什么要使用fragment?
当我们需要动态的多节目切换时,就需要将ui元素和activity融合成一个模块.在2.3中我们一般通过各种activity中进行跳转来实现多界面的跳转和单个界面动态改变.在4.0或以上的系统中可以使用新的特性来方便的达到这个效果-fragment类.Fragment类似一个嵌套activity,可以定义自己的layout和自己的生命周期.
当一个fragment被创建的时候,他会经历以下状态
onAttach,onCreate,onCreateView,onActivityCreate
当这个fragment对用户可见的时候,他会经历以下状态
onStart,onResume
当这个fragment进入后台模式的时候,他会经历以下状态
onPause,onStop
当这个fragment被销毁(或者持有他的activity被销毁),他会经历以下状态
onPause,onStop,onDestroyView,onDestroy,onDetach
fragment的大部分状态和activity相似,但fragment都有一些新的状态
onAttached:当fragment被加入到activity的时候调用(这个方法可以获得所在的activity)
onCreateView:当activity要得到fragment的layout时,调用此方法
onActivityCreate:当activity的oncreate方法返回后调用此方法
onDestroyView:当fragm中的视图移除的时候调用此方法
onDetach:当fragment和activity分离的时候,调用这个方法
2.activity的生命周期:
activity的从出生(new)到死亡(垃圾回收)的过程,activity创建的时候是由frameWork new出来的,我们自己可以去newactivity,但是new了自己没法启动(就像servlet,我们自己虽然可以new,但是启动不了).activity被fragmentWork New出来之后,由他去管理activity的.
activity给我们提供了一系列的方法,然后在相应的方法做出相应的操作,这些方法括:onCreate,onDestroy,onstart,onstop,onresume,onpause,onRestart
这些方法都是两两对应的
onCreate():创建 onDestroy():销毁
onStart():可见 onStop():不可见
onresume():可编辑(获取焦点) onPause():不可编辑(失去焦点)
这6个方法都是相对应的,只剩下一个onRestart方法了,该方法在activity被onStop后,但是并没有被fragmentwork回收掉,在再次启动activity时,不再调用onCreate,而是调用onRestart
例子:比如我做一个商品界面,用户在点击某一个商品的时候,商品界面被按走,然后用户点击返回,我就在这个onRestart里面做对商品页面的数据操作,从网络再拿商品,然后做刷新操作,保证用户做了操作,能保证用户看到最新的数据
activity还有一些其他不常用的比如:onPostResume和onPostCreate
onPostResume:可见(onStart)完成以后框架也就是系统去回调 onPostResume方法,而不是我们去回调该方法
onPostCreate:创建完成之后框架(系统)回调此方法,自己实现了也不会去覆盖框架的该方法
3.2个activity之间的跳转必然会执行的方法:
一般情况分2种,
B完全覆盖住了A:activirt分别为A和B,当在A里面激活B组件的时候,A会调用onPause(不可编辑,失去焦点)方法,然后B调用oncreate(出生),onstart(可见),onRresume(可编辑)方法,这个时候B覆盖了窗体,A会调用onStop(不可见)方法,
B是透明的或者是个对话框:如果B是透明的,或者是对话框的样式,就不会调用onStop方法
4.横竖屏切换执行的生命周期方法
这个生命周期和清单文件的配置有关系
(1):不设置activity的android:configChanges时,切屏会重新调用各个生命周期方法,默认首先销毁当前的activity,然后重新加载,执行生命周期方法
(2):设置activity的android:configChanges="orientation|keyboardHidden|screenSize"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法
5.如何将一个activity设置成窗口的样式
1.可以在清单文件中配置activity的样式,设置成
android:theme="@android:style/Theme.DiaLog"
2.可以自己创建一个dialog,如何写一个布局文件,把布局文件当成一个dialog
6.你后台的activity被系统回收怎么办?如果后台的activity由于某种原因被系统回收了,如何在被系统回收之前保存当前状态
当activity处于不在前台界面显示,处于onPause或者onStop这2个状态的时候,activity不在内存栈的顶端,也是有可能被android回收的,
反正就是除了在栈顶的activity,其他activity都有可能在内存不足的时候被系统回收,activity越是在栈底越有可能被回收
当她们被系统回收,会调用onSaveInstanceState方法,你可以吧那些数据存取到outState里面,
@Override
protected void onSaveInstanceState(Bundle outState) {
//在activity被系统回收的时候,存取到outState路面
outState.putInt("1", 100);
super.onSaveInstanceState(outState);
}
在用户在下一次在即该activity的时候,就会调用onCreate方法
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
获取存取的数据
savedInstanceState.getInt("1");
}我们就可以从savedInstanceState里面获取activity被系统回收的时候存取的数据,如果手机以外死机了,那种超出了android所能管理的范围了我们可以每隔一段时候备份一份数据,这样即使死机了也不用担心数据丢失
7.如何退出activity?如何安全退出已调用多个activity的application?
退出activity直接调用finish()方法.用户点击back就是退出一个activity,退出activity会执行onDestory方法
1.抛异常强制退出
该方法通过抛异常,使程序force close,验证可以,但是需要解决的问题是:如何使程序结束掉,而不是弹出Fore Close的窗口
安全结束进程android.os.Process.KillProcess(android.os.Process.MyPid());
2.记录打开的activity
每打开一个activity,就记录下来,在需要退出的时候,关闭每一个activity
3.发送特定广播
在需要结束应用的时候,发送一个特定广播,每个activity收到广播,关闭即可
给某个activity注册接收广播的意图
registerReceiver(receiver,filter);
如果接收到的是关闭activity的广播,就调用finish()方法,把当前的activity finish掉
4.递归退出
在打开新的activity时使用startActivityForResult,然后自己加标志,在onActivityResult中处理,递推关闭
5.网上的做法
通过intent的flag实现,intent.setFlags(intent.FLAG_ACTIVITY_CLEAR_TOP)激活一个新的activity,在激活新的activity之前会把该栈中其他activity 杀死,然后在新的activity的oncreate方法中把自己finish掉就ok了
8.service是否在main thread中执行,service里面是否能执行耗时的操作?
默认情况,如果没有显示的指定servie所运行的进程,service和activity是运行在当前app所在的进程的main thread(UI主线程)里面的.
service里面不能执行耗时的操作(网络请求,拷贝数据库,大文件)
在子线程中执行new Thread(){}.start();
特殊情况可以在清单文件配置service执行所在的进程,让service在另外的进程中执行.注意
BroadcastReceiver(广播)的耗时时间为10秒
service的耗时为20秒
activity的耗时为5秒,
虽然servie不能做耗时操作但是service的子类intentservice可以做耗时操作
9.两个activity之间怎么传递数据?
由于android sdk限制,不能再调用activity时访问activity对象,因此,就不能像在普通对象之间传递数据一样通过构造方法或类成员传递数据.android提供了自己的数据传递方法,最常用的通过intent对象传递数据
可通过intent对象,静态常量,剪切板和全局对象进行数据传递
1.intent对象:
Intent intent=new Intent(this,MainActivity.class);
intent.putExtra("intent_integer", 300);
startActivity(intent);
2.静态常量
将类成员定义成putlic static就可以直接通过类成员来传递数据.使用静态变量可以传递任意类型的数据.
3.剪切板,可以利用android系统提供的剪切板存取数据.
Intent intent=new Intent(this,MainActivity.class);
//获取管理剪切板的对象
ClipboardManager manager=(ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
//向剪切板保存字符串
manager.setText("你好");
startActivity(intent);
//向剪切板获得数据
ClipboardManager clipboardManager=(ClipboardManager)
getSystemService(Context.CLIPBOARD_SERVICE);
//从剪切板获得字符串
String text=clipboardManager.getText().toString();
传递数据的限制:只能传递文本数据以及intent对象支持的数据
4.全局对象:可以为每一个应用程序定义一个全局的对象.该对象的创建由系统负责使用全局对象需要一个继承自application的类.并在该类中定义任何类型的成员变量和方法
public class MyApplication extends Application{
public String ountry;
public Data data=new Data();
}然后需要在androidMainfest.xml文件中定义该类
<application android:name="com.itheima.listview.MyApplication">
</application>
然后可以在应用程序的任何地方通过如下代码获取MyApplication对象
MyApplication application=(MyApplication) getApplicationContext();
虽然高版本的android允许剪切板保存intent支持的数据类型,但这并不适合所有的android版本.如果要考虑更多的android版本,除了要考虑狐狸剪切板代码的版本问题外,还可以直接使用字符串传递任何二进制的数据(包括可序列号的对象,图像)
将二进制数据转换字符串只需要将其编码(一般采用Base64编码)。例如下面的代码将一个可序列化对象转换成bSE64编码
Intent intent=new Intent(this,MainActivity.class);
//获取管理剪切板的对象
ClipboardManager manager=(ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
Data data=new Data();
data.id=6666;
data.name="通过Clipboard传递的数据";
//下面的代码将data对象转换成base64格式的字符串
ByteArrayOutputStream baos=new ByteArrayOutputStream();
String base64Str="";
try {
ObjectOutputStream oos=new ObjectOutputStream(baos);
oos.writeObject(data);
//使用base64.encodeToString方法将byte[]数据转换成base64字符串
base64Str=Base64.encodeToString(baos.toByteArray(),Base64.DEFAULT);
oos.close();
} catch (Exception e) {
// TODO: handle exception
}
//向剪切板保存字符串
manager.setText(base64Str);
startActivity(intent);
Intent intent=new Intent(this,MainActivity.class);
//获取管理剪切板的对象
ClipboardManager manager=(ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
Data data=new Data();
data.id=6666;
data.name="通过Clipboard传递的数据";
//下面的代码将data对象转换成base64格式的字符串
ByteArrayOutputStream baos=new ByteArrayOutputStream();
String base64Str="";
try {
ObjectOutputStream oos=new ObjectOutputStream(baos);
oos.writeObject(data);
//使用base64.encodeToString方法将byte[]数据转换成base64字符串
base64Str=Base64.encodeToString(baos.toByteArray(),Base64.DEFAULT);
oos.close();
} catch (Exception e) {
// TODO: handle exception
}
//向剪切板保存字符串
manager.setText(base64Str);
startActivity(intent);
10.怎么在启动一个activity的时候启动一个service
在activity的onCreate方法里面startService
在service启动activity:
在oncreate写如下代码
Intent dialogIntent = new Intent(getBaseContext(), YourActivity.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(dialogIntent);
11.同一个程序,但是不同的activity是否可以放在不同的task任务栈中?
singleInstance可以让每一个activity都对应一个任务栈
比方说在激活一个新的activity的时候,给intent设置flag,intent的flag添加FLAG_ACTIVITY_NEW_TASK,这个被激活的activity就会在新的task栈里面
Intent intent=new Intent(this,SendActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
12.activity怎么和service绑定,怎么在activity中启动自己对应的service?
startService:一旦创建service,该servie和activity就没有关系了,只有使用bindService(),他会把service和启动service的activity绑定,activity销毁,servie也会销毁
bindService我们可以使用service里面的方法
//创建服务
public class LeaderService extends Service{
@Override
public IBinder onBind(Intent intent) {
/*返回一个Binder对象,这个对象就是中间人对象用于调用服务对象里面自定义
* 的banZheng方法,否则是没法调用服务对象的自定义方法的
* */
return new ZhouMi();
}
继承binder,实现PublicBusiness接口方法## ##
class ZhouMi extends Binder implements PublicBusiness{
public void QianXian(){
banZheng();
}
}
public void banZheng(){
System.out.println("李处帮你来办证");
}
创建intent,设置服务
intent=new Intent(this,LeaderService.class);
//创建服务对外提供的接口对象
PublicBusiness pb;
//服务连接接口对象
class MyServiceConnection implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
接口对象赋值
pb=(PublicBusiness) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
}
//获取服务连接接口对象
msc=new MyServiceConnection();
//绑定领导服务
bindService(intent, msc,BIND_AUTO_CREATE);
这样就可以调用服务里面实现的接口方法了
13.什么是service以及描述下他的生命周期方法,Service有哪些启动方法,他们的区别,怎么停用Service?
什么是service: Service是运行在后台的android组件,没有用户界面,不能与用户交互,可以运行在自己的进程,也可以运行在其他应用程序的上下文里。
Service 与 Thread 的区别
很多时候,你可能会问,为什么要用 Service,而不用 Thread 呢,因为用 Thread 是很方便的,比起 Service 也方便多了,下面我详细的来解释一下。
1). Thread:Thread 是程序执行的最小单元,它是分配CPU的基本单位。可以用 Thread 来执行一些异步的操作。
2). Service:Service 是android的一种机制,当它运行的时候如果是Local Service,那么对应的 Service 是运行在主进程的 main 线程上的。如:onCreate,onStart 这些函数在被系统调用的时候都是在主进程的 main 线程上运行的。如果是Remote Service,那么对应的 Service 则是运行在独立进程的 main 线程上。因此请不要把 Service 理解成线程,它跟线程半毛钱的关系都没有!
既然这样,那么我们为什么要用 Service 呢?其实这跟 android 的系统机制有关,我们先拿 Thread 来说。Thread 的运行是独立于 Activity 的,也就是说当一个 Activity 被 finish 之后,如果你没有主动停止 Thread 或者 Thread 里的 run 方法没有执行完毕的话,Thread 也会一直执行。因此这里会出现一个问题:当 Activity 被 finish 之后,你不再持有该 Thread 的引用。另一方面,你没有办法在不同的 Activity 中对同一 Thread 进行控制。
举个例子:如果你的 Thread 需要不停地隔一段时间就要连接服务器做某种同步的话,该 Thread 需要在 Activity 没有start的时候也在运行。这个时候当你 start 一个 Activity 就没有办法在该 Activity 里面控制之前创建的 Thread。因此你便需要创建并启动一个 Service ,在 Service 里面创建、运行并控制该 Thread,这样便解决了该问题(因为任何 Activity 都可以控制同一 Service,而系统也只会创建一个对应 Service 的实例)。
因此你可以把 Service 想象成一种消息服务,而你可以在任何有 Context 的地方调用 Context.startService、Context.stopService、Context.bindService,Context.unbindService,来控制它,你也可以在 Service 里注册 BroadcastReceiver,在其他地方通过发送 broadcast 来控制它,当然这些都是 Thread 做不到的。
在service的生命周期中,被回调的方法比activity少一些,只有onCreate,onStart,OnDestroy,onBind和onUnBind,通常有2种方式启动一个service,他们的生命周期也是不一样的.
1.通过startService
service会经历onCreate,onStart,然后处于运行状态,stopServie的时候调用onDestroy.如果调用者没有stopService,那么该服务会一直运行在后台
2.通过bindServie
service会运行onCreate,然后调用onbindm这时候调用者和service绑定在一起,调用者退出了,service就会调用onUnbing和onDestroy
所谓的绑定就是共存亡了,调用者也可以通过onUnBintService方法停止服务这时候service就会调用onUnbind和onDestroy方法
需要注意的是如果这几个方法交织在一起回出问题的,一个原则是service的onCreate只会被调用一次,就是无论你绑定也好启动服务也好,service只会被创建一次
如果先是bind了,那么startService的时候就直接运行service的onStart方法,如果先startService方法,然后bingdService方法那么直接运行onBind方法
如果service运行期间调用了bindService,这时候在调用stopService的话,service是不会调用onDestroy方法的,servie是stop不掉了,只能调用unBindSefvie,service才会被销毁
如果一个servcie通过startService被start之后,多次调用startServcie的话,servie会多次调用onstart方法,多次调用stopService的话,service只会调用一次onDestroy方法
如果servie通过bindService被start之后,多次调用bindService的话,service只会调用一次onBind方法
多次调用unBindServie会抛异常
15.不用service,B页面为音乐播放器,从A跳到B,在返回,如何使音乐继续播放?
A跳转到B的时候,使用startActivityForResult(intent,10);去开启B,当用户在b界面按返回的键的时候,我们把音乐播放器的歌曲信息保存到intent里面,如使用setResult(1,intent)保存intent,然后在A界面重新写onActivityResult,获取保存的音乐信息,就可以在a界面继续播放音乐了.
16.什么是intentService?有什么优点?
普通的service,默认运行在ui main主线程,
sdk给我们提供了,带有异步处理的service里
intentService里面的onHandleIntent方法默认开启了一个
子线程,你在里面做任何耗时操作都没有问题
IntentService也是一个Service,是Service的子类;
IntentService和Service有所不同,通过Looper和Thread来解决标准Service中处理逻辑的阻塞的问题
优点:Activity的进程,当处理Intent的时候,会产生一个对应的Service,Android的进程处理器现在会尽可能的不kill掉你。
IntentService是Service类的子类,用来处理异步请求。客户端可以通过startService(Intent)方法传递请求给IntentService。IntentService在onCreate()函数中通过HandlerThread单独开启一个线程来处理所有Intent请求对象(通过startService的方式发送过来的)所对应的任务,这样以免事务处理阻塞主线程。执行完所一个Intent请求对象所对应的工作之后,如果没有新的Intent请求达到,则自动停止Service;否则执行下一个Intent请求所对应的任务。
IntentService在处理事务时,还是采用的Handler方式,创建一个名叫ServiceHandler的内部Handler,并把它直接绑定到HandlerThread所对应的子线程。 ServiceHandler把处理一个intent所对应的事务都封装到叫做onHandleIntent的虚函数;因此我们直接实现虚函数onHandleIntent,再在里面根据Intent的不同进行不同的事务处理就可以了。
另外,IntentService默认实现了Onbind()方法,返回值为null。
使用IntentService需要两个步骤:
1、写构造函数
2、实现虚函数onHandleIntent,并在里面根据Intent的不同进行不同的事务处理就可以了。
好处:处理异步请求的时候可以减少写代码的工作量,比较轻松地实现项目的需求
IntentService使用队列的方式将请求的Intent加入队列,然后开启一个worker thread(线程)来处理队列中的Intent,对于异步的startService请求,IntentService会处理完成一个之后再处理第二个,每一个请求都会在一个单独的worker thread中处理,不会阻塞应用程序的主线程,这里就给我们提供了一个思路,如果有耗时的操作与其在Service里面开启新线程还不如使用IntentService来处理耗时操作。
注意:IntentService的构造函数一定是参数为空的构造函数,然后再在其中调用super("name")这种形式的构造函数。
因为Service的实例化是系统来完成的,而且系统是用参数为空的构造函数来实例化Service的
缺点:不可以直接和UI做交互。为了把他执行的结果体现在UI上,需要发送给Activity。
工作任务队列是顺序执行的,如果一个任务正在IntentService中执行,此时你再发送一个任务请求,这个任务会一直等待直到前面一个任务执行完毕。
正在执行的任务无法打断
17.什么时候使用service?
startForeground(id, notification)
messenger
拥有service的进程具有较高的优先级
官方文档告诉我们,Android系统会尽量保持拥有service的进程运行,只要在该service已经被启动(start)或者客户端连接(bindService)到它。当内存不足时,需要保持,拥有service的进程具有较高的优先级。
1. 如果service正在调用onCreate, onStartCommand或者onDestory方法,那么用于当前service的进程相当于前台进程以避免被killed。
2. 如果当前service已经被启动(start),拥有它的进程则比那些用户可见的进程优先级低一些,但是比那些不可见的进程更重要,这就意味着service一般不会被killed.
3. 如果客户端已经连接到service (bindService),那么拥有Service的进程则拥有最高的优先级,可以认为service是可见的。
4. 如果service可以使用startForeground(int, Notification)方法来将service设置为前台状态,那么系统就认为是对用户可见的,并不会在内存不足时killed。
如果有其他的应用组件作为Service,Activity等运行在相同的进程中,那么将会增加该进程的重要性。
1.Service的特点可以让他在后台一直运行,可以在service里面创建线程去完成耗时的操作.
2.Broadcast receiver捕获到一个事件之后,可以起一个service来完成一个耗时的操作.
3.远程的service如果被启动起来,可以被多次bind, 但不会重新create. 索爱手机X10i的人脸识别的service可以被图库使用,可以被摄像机,照相机等程序使用.
18.描述一下Intent和intent filter
android通过intent对象来表示一条消息,一个intent对象不仅仅包含这个消息的目的地,还可以包含消息的内容,这就好比是一份email,其中不仅仅应该包含地址,还可以包含具体的内容.对于Intent,消息目的地是必须的,内容是可选的,通过intent可以实现各种系统组件的调整和激活
Intent filter: 可以理解为邮局或者是一个信笺的分拣系统…
这个分拣系统通过3个参数来识别
Action: 动作 view
Data: 数据uri uri
Category : 而外的附加信息
Action 匹配
Action 是一个用户定义的字符串,用于描述一个 Android 应用程序组件,一个 Intent Filter 可以包含多个 Action。在 AndroidManifest.xml 的 Activity 定义时可以在其 <intent-filter >节点指定一个 Action 列表用于标示 Activity 所能接受的“动作”,例如:
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<action android:name="cn.itcast.action" />
</intent-filter>
如果我们在启动一个 Activity 时使用这样的 Intent 对象:
Intent intent =new Intent();
intent.setAction("cn.itcast.action");
那么所有的 Action 列表中包含了“cn.itcast”的 Activity 都将会匹配成功。
Android 预定义了一系列的 Action 分别表示特定的系统动作。这些 Action 通过常量的方式定义在 android.content. Intent中,以“ACTION_”开头。我们可以在 Android 提供的文档中找到它们的详细说明。
URI 数据匹配
一个 Intent 可以通过 URI 携带外部数据给目标组件。在 <intent-filter >节点中,通过 <data/>节点匹配外部数据。
mimeType 属性指定携带外部数据的数据类型,scheme 指定协议,host、port、path 指定数据的位置、端口、和路径。如下:
<data android:mimeType="mimeType" android:scheme="scheme"
android:host="host" android:port="port" android:path="path"/>
电话的uri tel: 12345
http://www.baidu.com
自己定义的uri itcast://cn.itcast/person/10
如果在 Intent Filter 中指定了这些属性,那么只有所有的属性都匹配成功时 URI 数据匹配才会成功。
Category 类别匹配
<intent-filter >节点中可以为组件定义一个 Category 类别列表,当 Intent 中包含这个列表的所有项目时 Category 类别匹配才 会成功。
默认是DEFAULT
19. Intent传递数据时,可以传递哪些类型数据?
1.一般的基本数据类型 Intent .putextra() intent.getextra();
2.数据的uri, intent.setData() intent.getData();
20.说说activity,Intent,Service是什么关系
activity是界面,Service是后台服务,intent是桥梁,要想界面启动服务,或者服务启动界面,就必须有架起他们之间的桥梁,而intent就是那桥梁
intent是activity和service的桥梁,通信员,activity主要操作显示界面,service在后台运行,适合长时间运行,如下载,听歌等。。
21.请描述一下Broadcase Receiver
有很多广播接收者 ,系统已经实现了.
广播分两种 有序广播
无序广播
指定接收者的广播 . 是不可以被拦截掉的
<intent-filter android:priority="1000">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
abortBroadcast();
用于接收系统的广播通知, 系统会有很多sd卡挂载,手机重启,广播通知,低电量,来电,来短信等….
手机卫士中自定义一个broadcast receiver
<intent-filter android:> <action> sms_received </action> </intent-filter>
来获取短信到来的广播, 根据黑名单来判断是否拦截该短信.
画画板生成图片后,发送一个sd挂载的通知,通知系统的gallery去获取到新的图片.
Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED,Uri.parse("file://"+Environment.getExternalStorageDirectory()));
sendBroadcast(intent);
22. 在manifest和代码中如何注册和使 用 broadcast receiver 。
设置广播接收者的优先级,设置广播接受者的action名字 等…
详细见工程代码.
<intent-filter android:priority="1000">
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
<receiver android:name=".SmsReceiver">
<intent-filter android:priority="1000">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
<receiver android:name=".BootCompleteReceiver">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
使用代码注册广播
//使用代码注册电话去电广播接收者
callReceiver=new OutCallReceiver();
IntentFilter filter=new IntentFilter(Intent.ACTION_NEW_OUTGOING_CALL);
//注册广播接收者
registerReceiver(callReceiver, filter);
23. 请介绍下ContentProvider是如何实现数据共享的。
把自己的数据通过uri的形式共享出去
android 系统下 不同程序 数据默认是不能共享访问
需要去实现一个类去继承ContentProvider
public class PersonContentProvider extends ContentProvider{
public boolean onCreate(){
//..
}
query(Uri, String[], String, String[], String)
insert(Uri, ContentValues)
update(Uri, ContentValues, String, String[])
delete(Uri, String, String[])
}
一个应用程序可以通过实现一个Content provider的抽象接口将自己的数据共享给其他应用程序,而且Content providers是以类似数据库表的方式将数据暴露。
Content providers存储和检索数据,通过它可以让所有的应用程序访问到,这也是应用程序之间唯一共享数据的方法。
要想使应用程序的数据公开化,可通过2种方法:
创建一个属于你自己的Content provider或者将你的数据添加到一个已经存在的Content provider中,前提是有相同数据类型并且有写入Content provider的权限。
那么如何通过统一的接口获取其他应用程序共享的数据呢?
Android提供了ContentResolver,外界的程序可以通过ContentResolver接口访问ContentProvider提供的数据。
24. 请介绍下Android的数据存储方式。
文件 访问权限. sdcard <data>/<data>
数据库 sqlite
SharedPreference <data>/<data>/shared_preps
网络 socket tcp udp , http httpurlconnection
25. 为什么要用ContentProvider?它和sql的实现上有什么差别?
屏蔽数据存储的细节,对用户透明,用户只需要关心操作数据的uri就可以了
不同app之间共享,操作数据
Sql也有增删改查的方法.
但是contentprovider 还可以去增删改查本地文件. xml文件的读取,更改,
网络数据读取更改
26. 请介绍下Android中常用的五种布局。
FrameLayout(帧布局(堆栈布局)),LinearLayout (线性布局),AbsoluteLayout(绝对布局),RelativeLayout(相对布局),TableLayout(表格布局)
FrameLayout在布局文件中使用<FrameLayout>标签标示.FrameLayout布局中的view都会以层叠方式显示,类似于Photoshop的图层.放在最后的view会显示在最上层.因此可以将framelayout称为堆栈布局
LinearLayout可以将多个view水平或垂直排列.如果android:orientaciond的属性为horizontal,view会水平排列.属性值为vertical,view会垂直排列
RelativeLayout可以通过确定多个组件的相对位置摆放组件.与组件相对位置相关的属性包括
Android布局是应用界面开发的重要一环,在Android中,共有五种布局方式,分别是:FrameLayout(框架布局),LinearLayout
(线性布局),AbsoluteLayout(绝对布局),RelativeLayout(相对布局),TableLayout(表格布局)
一、FrameLayout
这个布局可以看成是墙脚堆东西,有一个四方的矩形的左上角墙脚,我们放了第一个东西,要再放一个,那就在放在原来放的位置的上面,这样依次的放,会盖住原来的东西。这个布局比较简单,也只能放一点比较简单的东西。
二、LinearLayout
线性布局,这个东西,从外框上可以理解为一个div,他首先是一个一个从上往下罗列在屏幕上。每一个LinearLayout里面又可分为垂直布局
(android:orientation="vertical")和水平布局(android:orientation="horizontal"
)。当垂直布局时,每一行就只有一个元素,多个元素依次垂直往下;水平布局时,只有一行,每一个元素依次向右排列。
linearLayout中有一个重要的属性 android:layout_weight="1",这个weight在垂直布局时,代表行距;水平的时候代表列宽;weight值越大就越大。
三、AbsoluteLayout
绝对布局犹如div指定了absolute属性,用X,Y坐标来指定元素的位置android:layout_x="20px"
android:layout_y="12px" 这种布局方式也比较简单,但是在垂直随便切换时,往往会出问题,而且多个元素的时候,计算比较麻烦。
四、RelativeLayout
相对布局可以理解为某一个元素为参照物,来定位的布局方式。主要属性有:
相对于某一个元素
android:layout_below="@id/aaa" 该元素在 id为aaa的下面
android:layout_toLeftOf="@id/bbb" 改元素的左边是bbb
相对于父元素的地方
android:layout_alignParentLeft="true" 在父元素左对齐
android:layout_alignParentRight="true" 在父元素右对齐
还可以指定边距等,具体详见API
五。TableLayout
表格布局类似Html里面的Table。每一个TableLayout里面有表格行TableRow,TableRow里面可以具体定义每一个元素,设定他的对齐方式 android:gravity="" 。
每一个布局都有自己适合的方式,另外,这五个布局元素可以相互嵌套应用,做出美观的界面。
27. 谈谈UI中, Padding和Margin有什么区别?
Padding 文字对边框, margin是控件对父窗体.
28. widget相对位置的完成在activity的哪个生命周期阶段实现。
这个题没看懂…
widget可以理解成桌面小控件,
也可以理解成 某个button, imageview这样的控件…
onmeasure() // 计算 控件在屏幕上的位子
某个view 要显示在界面 ondraw 被显示到界面上的 .
29. 请解释下在单线程模型中Message、Handler、Message Queue、 Looper之间的关系。
当应用一旦启动完成,就会有一个looper,looper是一个死循环,不停的去迭代一个Message Queue,Message Queue是一个信息队列,message Queue一旦发现里面有了一个消息,就把它取出来,
取出来之后,他就去找message,message里面有一个Tag,这个tag指的就是当前handler发送的某一个消息,然后这个消息就去找message对应的handler,找到了handler就去执行handler的handmessage方法,里面做执行ui主线程的操作
andriod提供了 Handler 和 Looper 来满足线程间的通信。Handler 先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(Message Exchange)。
1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列)。
2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;或者接收Looper从Message Queue取出)所送来的消息。
3) Message Queue(消息队列):用来存放线程放入的消息。
4)线程:UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。
30.AIDL的全称是什么?如何工作?
Android interface definition language android(接口定义语言),用来跨进程的访问方法
AIDL工作:
1.在eclipse android工程的java源文件目录中建立一个扩展名为aidl的文件,该文件的语法类似java,但稍有不同
2.如果aidl文件的内容是正确的,adt会自动生成一个java接口文件(*.java)
3.建立一个服务类(service的子类)
4.实现由aidl文件生成的java文件
5.在androidManifest.xml文件中配置aidl服务尤其要注意<action>标签中android:name的属性值就是客户端要引用该服务器的id,也就是intent类构造方法的参数值.
1、创建AIDL文件, 在这个文件里面定义接口, 该接口定义了可供客户端访问的方法和属性。
2、编译AIDL文件, 用Ant的话, 可能需要手动, 使用Eclipse plugin的话,可以根据adil文件自动生产java文件并编译, 不需要人为介入.
3、在Java文件中, 实现AIDL中定义的接口. 编译器会根据AIDL接口, 产生一个JAVA接口。这个接口有一个名为Stub的内部抽象类,它继承扩展了接口并实现了远程调用需要的几个方法。接下来就需要自己去实现自定义的几个接口了.
4、向客户端提供接口ITaskBinder, 如果写的是service,扩展该Service并重载onBind ()方法来返回一个实现上述接口的类的实例。
5、在服务器端回调客户端的函数. 前提是当客户端获取的IBinder接口的时候,要去注册回调函数, 只有这样, 服务器端才知道该调用那些函数
aidl支持的数据有:
1.java的简单类型(int,char,boolean).不需要导入
2.String和charSequence
3.list和map,但是要注意,list和map对象的元素必须是aidl服务支持的数据类型
4.aidl自动生成的接口.需要导入
5.实现android.os.Parcelable接口的类.需要导入.
31.解释一下Android程序运行时权限和文件系统权限的区别
Android程序执行需要读取到安全敏感项必需在androidmanifest.xml中声明相关权限请求,打电话,访问网络,获取坐标,读写sd卡等等,这个面向用户的,用户要想执行相关的操作,得有相关的权限.
文件系统权限是面向程序员的,android是一个linux的系统,而linux下的文件权限是使用10个字母表示的,d代表文件夹,_表示文件,然后后面9个字母分别为3组,rwx分别为读,写,执行.第一组rwx是文件拥有者对文件的权限,第二组rwx为文件拥有者属于同一用户组的用户对文件的访问权限,第三组rwx表示的是其他用户对文件的权限。比如sharedpreference里面的Context.Mode.private,你吧sharedpreference改为Context.Mode.private,其他的应用就不能访问该文件了. Context.Mode.world_read_able Context.Mode_world_writeable
要区分apk运行时的拥有的权限与在文件系统上被访问(读写执行)的权限两个概念。
apk程序是运行在虚拟机上的,对应的是Android独特的权限机制,只有体现到文件系统上时才使用linux的权限设置。
(一)linux文件系统上的权限
-rwxr-x--x system system 4156 2010-04-30 16:13 test.apk
代表的是相应的用户/用户组及其他人对此文件的访问权限,与此文件运行起来具有的权限完全不相关。
比如上面的例子只能说明system用户拥有对此文件的读写执行权限;system组的用户对此文件拥有读、执行权限;其他人对此文件只具有执行权限。
而test.apk运行起来后可以干哪些事情,跟这个就不相关了。
千万不要看apk文件系统上属于system/system用户及用户组,或者root/root用户及用户组,就认为apk具有system或root权限
(二)Android的权限规则
(1)Android中的apk必须签名
这种签名不是基于权威证书的,不会决定某个应用允不允许安装,而是一种自签名证书。
重要的是,android系统有的权限是基于签名的。比如:system等级的权限有专门对应的签名,签名不对,权限也就获取不到。
默认生成的APK文件是debug签名的。
获取system权限时用到的签名,见:如何使Android应用程序获取系统权限
(2)基于UserID的进程级别的安全机制
大家都知道,进程有独立的地址空间,进程与进程间默认是不能互相访问的,是一种很可靠的保护机制。
Android通过为每一个安装在设备上的包(apk)分配唯一的linux userID来实现,名称为"app_"加一个数字,比如app_43
不同的UserID,运行在不同的进程,所以apk之间默认便不能相互访问。
Android提供了如下的一种机制,可以使两个apk打破前面讲的这种壁垒。
在AndroidManifest.xml中利用sharedUserId属性给不同的package分配相同的userID,通过这样做,两个package可以被当做同一个程序,
系统会分配给两个程序相同的UserID。当然,基于安全考虑,两个package需要有相同的签名,否则没有验证也就没有意义了。
(这里补充一点:并不是说分配了同样的UserID,两程序就运行在同一进程, 下面为PS指令摘取的,
显然,system、app_2分别对应的两个进程的PID都不同,不知Android到底是怎样实现它的机制的)
User PID PPID
system 953 883 187340 55052 ffffffff afe0cbcc S system_server
app_2 1072 883 100264 19564 ffffffff afe0dcc4 S com.android.inputmethod.
system 1083 883 111808 23192 ffffffff afe0dcc4 S android.process.omsservi
app_2 1088 883 156464 45720 ffffffff afe0dcc4 S android.process.acore
(3)默认apk生成的数据对外是不可见的
实现方法是:Android会为程序存储的数据分配该程序的UserID。
借助于Linux严格的文件系统访问权限,便实现了apk之间不能相互访问似有数据的机制。
例:我的应用创建的一个文件,默认权限如下,可以看到只有UserID为app_21的程序才能读写该文件。
-rw------- app_21 app_21 87650 2000-01-01 09:48 test.txt
如何对外开放?
<1> 使用MODE_WORLD_READABLE and/or MODE_WORLD_WRITEABLE 标记。
When creating a new file with getSharedPreferences(String, int), openFileOutput(String, int), or openOrCreateDatabase(String, int, SQLiteDatabase.CursorFactory), you can use the MODE_WORLD_READABLE and/or MODE_WORLD_WRITEABLE flags to allow any other package to read/write the file. When setting these flags, the file is still owned by your application, but its global read and/or write permissions have been set appropriately so any other application can see it.
(4)AndroidManifest.xml中的显式权限声明
Android默认应用是没有任何权限去操作其他应用或系统相关特性的,应用在进行某些操作时都需要显式地去申请相应的权限。
一般以下动作时都需要申请相应的权限:
A particular permission may be enforced at a number of places during your program's operation:
At the time of a call into the system, to prevent an application from executing certain functions.
When starting an activity, to prevent applications from launching activities of other applications.
Both sending and receiving broadcasts, to control who can receive your broadcast or who can send a broadcast to you.
When accessing and operating on a content provider.
Binding or starting a service.
在应用安装的时候,package installer会检测该应用请求的权限,根据该应用的签名或者提示用户来分配相应的权限。
在程序运行期间是不检测权限的。如果安装时权限获取失败,那执行就会出错,不会提示用户权限不够。
大多数情况下,权限不足导致的失败会引发一个 SecurityException, 会在系统log(system log)中有相关记录。
(5)权限继承/UserID继承
当我们遇到apk权限不足时,我们有时会考虑写一个linux程序,然后由apk调用它去完成某个它没有权限完成的事情,很遗憾,这种方法是行不通的。
前面讲过,android权限是经营在进程层面的,也就是说一个apk应用启动的子进程的权限不可能超越其父进程的权限(即apk的权限),
即使单独运行某个应用有权限做某事,但如果它是由一个apk调用的,那权限就会被限制。
实际上,android是通过给子进程分配父进程的UserID实现这一机制的。
(三)常见权限不足问题分析
首先要知道,普通apk程序是运行在非root、非system层级的,也就是说看要访问的文件的权限时,看的是最后三位。
另外,通过system/app安装的apk的权限一般比直接安装或adb install安装的apk的权限要高一些。
言归正传,运行一个android应用程序过程中遇到权限不足,一般分为两种情况:
(1)Log中可明显看到权限不足的提示。
此种情况一般是AndroidManifest.xml中缺少相应的权限设置,好好查找一番权限列表,应该就可解决,是最易处理的情况。
有时权限都加上了,但还是报权限不足,是什么情况呢?
Android系统有一些API及权限是需要apk具有一定的等级才能运行的。
比如 SystemClock.setCurrentTimeMillis()修改系统时间,WRITE_SECURE_SETTINGS权限好像都是需要有system级的权限才行。也就是说UserID是system.
(2)Log里没有报权限不足,而是一些其他Exception的提示,这也有可能是权限不足造成的。
比如:我们常会想读/写一个配置文件或其他一些不是自己创建的文件,常会报java.io.FileNotFoundException错误。
系统认为比较重要的文件一般权限设置的也会比较严格,特别是一些很重要的(配置)文件或目录。
如
-r--r----- bluetooth bluetooth 935 2010-07-09 20:21 dbus.conf
drwxrwx--x system system 2010-07-07 02:05 data
dbus.conf好像是蓝牙的配置文件,从权限上来看,根本就不可能改动,非bluetooth用户连读的权利都没有。
/data目录下存的是所有程序的私有数据,默认情况下android是不允许普通apk访问/data目录下内容的,通过data目录的权限设置可知,其他用户没有读的权限。
所以adb普通权限下在data目录下敲ls命令,会得到opendir failed, Permission denied的错误,通过代码file.listfiles()也无法获得data目录下的内容。
上面两种情况,一般都需要提升apk的权限,目前我所知的apk能提升到的权限就是system(具体方法见:如何使Android应用程序获取系统权限),
32.系统上安装了多种浏览器,能否知道某浏览器访问指定页面.
可以的,只要他的浏览器在清单文件中配置了一个隐式的<intent-filter>
</intent-filter>
找到对应的浏览器的意图,传递数据URI,激活这个意图
Intent intent=new Intent();
intent.setClassName(packageName,className);
intent.seturi();
Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
Uri content_uri_browsers = Uri.parse("http://isomobile.com");
intent.setData(content_uri_browsers);
intent.setClassName("com.android.browser", "com.android.browser.BrowserActivity");
startActivity(intent);
问题的关键在于我们设置了class name,也就是我们想要跳转的pakcage的activity。如果你想要跳转到其它的浏览器,只需要修改一下这个函数就OK了。
好,我们现在来让刚刚的思路来指导我们的实践。假如我们现在要直接启动UC浏览器,那么我们该怎么做呢?让我们step by step吧。
1)下载UC apk:http://i-uc.net/read.php?2
2)用7zip解压apk文件,得到classes.dex文件
3)下载反编译dex文件工具:http://nchc.dl.sourceforge.net/project/dedexer/dedexer/1.5/ddx1.5.jar(Dedexer 项目主页: http://dedexer.sourceforge.net/)
4)执行命令:java -jar ddx1.5.jar -o -D -d c:\ c:\classes.dex
5)得到package name是:com.uc.browser,启动的activity是:com.uc.browser.ActivityUpdate(补充:当我在这里选择采用ActivityBrowser的时候发觉权限不够,报permiss denied 异常,而且也不是我们要的那个activity,幸运的是在第二次尝试用ActivityUpdate,刚好能满足要求)
6)修改上面的代码为intent.setClassName("com.uc.browser","com.uc.browser.ActivityUpdate");****
33.对android主线程的运用和理解
主ui线程不能执行耗时的操作
耗时操作都是自己开启子线程去执行.
在ui主线程中的分别有
receiver 10秒
content provide 5秒
service 20秒
activity 5秒
34.对android虚拟机的理解,包括内存管理机制和垃圾回收机制.
虚拟机很小,空间很小,androdi的虚拟机的默认是16mb,有些手机厂商的虚拟机的内存大小改为32mb.
讲到androd的内存管理机制就说说加载图片去处理大图片,android加载大图片的时候,我们曾创建一个Options对象,该对象把解析图片需要的参数都封装了起来,这样我们可以把图片的长宽进行压缩.记住bitmap用完后使用bm.describeContents();把他的内存给回收掉。
垃圾回收,没有引用的对象,在某个时刻被系统gc掉
与windows内存区别
在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然。这是Linux内存管理的一个优秀特性,在这方面,区别于 Windows的内存管理。主要特点是,无论物理内存有多大,Linux都将其充份利用,将一些程序调用过的硬盘数据读入内存,利用内存读写的高速特性来提高Linux系统的数据访问性能。而Windows是只在需要内存时,才为应用程序分配内存,并不能充分利用大容量的内存空间。换句话说,每增加一些物理内存,Linux都将能充分利用起来,发挥了硬件投资带来的好处,而Windows只将其做为摆设,即使增加8GB甚至更大。
android内存的意义
其实我们在用安卓手机的时候不用太在意剩余内存,Android上的应用是java,当然需要虚拟机,而android上的应用是带有独立虚拟机的,也就是每开一个应用就会打开一个独立的虚拟机。其实和java的垃圾回收机制类似,系统有一个规则来回收内存。进行内存调度有个阀值,只有低于这个值系统才会按一个列表来关闭用户不需要的东西。当然这个值默认设置得很小,所以你会看到内存老在很少的数值徘徊。但事实上他并不影响速度。相反加快了下次启动应用的速度。这本来就是 android标榜的优势之一,如果人为去关闭进程,没有太大必要。特别是使用自动关进程的软件。为什么内存少的时候运行大型程序会慢呢,原因是:在内存剩余不多时打开大型程序时会触发系统自身的调进程调度策略,这是十分消耗系统资源的操作,特别是在一个程序频繁向系统申请内存的时候。这种情况下系统并不会关闭所有打开的进程,而是选择性关闭,频繁的调度自然会拖慢系统。
Android的内存管理
Android的程序由Java语言编写,所以Android的内存管理与Java的内存管理相似。程序员通过new为对象分配内存,所有对象在java堆内分配空间;然而对象的释放是由垃圾回收器来完成的。C/C++中的内存机制是“谁污染,谁治理”,java的就比较人性化了,给我们请了一个专门的清洁工(GC)。
GC
GC是垃圾收集的意思(GabageCollection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。
垃圾回收的优点和原理
Java语言中一个显著的特点就是引入了垃圾回收机制,使得Java程序员在编写程序的时候不再需要考虑内存管理。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。
对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是"可达的",哪些对象是"不可达的"。当GC确定一些对象为"不可达"时,GC就有责任回收这些内存空间。程序员可以手动执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。
² Android系统中GC出现内存泄露
导致内存泄漏主要的原因是,先前申请了内存空间而忘记了释放。如果程序中存在对无用对象的引用,那么这些对象就会驻留内存,消耗内存,因为无法让垃圾回收器GC验证这些对象是否不再需要。如果存在对象的引用,这个对象就被定义为"有效的活动",同时不会被释放。要确定对象所占内存将被回收,我们就要务必确认该对象不再会被使用。典型的做法就是把对象数据成员设为null或者从集合中移除该对象。但当局部变量不需要时,不需明显的设为null,因为一个方法执行完毕时,这些引用会自动被清理。Java 内存泄露的根本原因就是 保存了不可能再被访问的变量类型的引用。
Android的内存溢出
因为系统为每一个dalvik虚拟机分配的内存是有限的,它的最大堆大小一般是16M,有的机器为24M。也就是说我们所能利用的内存空间是有限的。如果我们的内存占用超过了一定的水平就会出现OutOfMemory的错误。
内存不够用的原因
由于我们程序的失误,长期保持某些资源(如Context)的引用,造成内存泄露,资源造成得不到释放。保存了多个耗用内存过大的对象(如Bitmap),造成内存超出限制
35.Frameword工作方式及原理,activity是如何生成一个view的,机制是什么
反射+配置文件.
我们可以把我们做的每一个android应用理解成一个容器,而每一个activity里面都有window.callback(窗口的回调事件)和keyevent.callback(键盘的回调事件).一些回调的接口或函数把,framework把activity创建出来就会调用里面的这些回调方法,会调用activity生命周期的相关方法,比如说你在activity按了某个按钮的点击事件,在这之前,我们把应用打包成apk发送到手机上,apk会启动一个dvm,dvm把apk解压,找到一AndroidManifest.xml,然后dvm看你的清单文件中有哪些组件,一旦发现用户做了点击操作,就去找这些组件做出对应的操作
activity里面的view是通过ondraw画出来的,在ondraw方法之前还会调用onmeasure方法来计算显示的大小.
36.android本身的一些限制,比如apk包大小限制,读取大文件时的时间限制.
这个问题问的真有问题,apk包大小限制不好说.极品飞车100m还是能安装到手机上呢.这个大小呢和安装有关系,你100mb的apk读取到手机上的时候,可能手机的性能问题等等,会出现读取中断了的问题.
读取大文件的时间限制和你读取大文件的子线程在什么组件下有关系,比如在activty里面不要好过5秒,在service里面不要超过20秒.
37.加载音乐信息,如果改善其效率.
android提供了mediascanner,mediaStore等接口,音乐文件的信息都会存放到系统的数据库表中,可以通过content provider获取.
改善效率可以从分批加载,延时加载,合理使用缓存等去改善.
38.lisview如何提高其效率?
复用convertview,历史的view对象
减少子view查询的次数,用用viewholder
然后就是异步加载数据,分页加载数据,使用静态的view对象,避免创建过多的view.
1.在adapter中的getview方法中尽量少使用逻辑
比如你在getview里面判断子view的显示隐藏,我们可以放到创建viewholder里面去做.
2.尽最大的可能避免对象被gc
当你创建了大量的对象的时候,GC就会频繁的执行,所以在getView()方法中不要创建很多的对象,最好的优化是,不要在ViewHolder以外创建任何对象,如果你的你的log里面发现“GC has freed some memory”频繁出现的话,那你的程序肯定有问题了。你可以检查一下:
a) item布局的层级是否太深
b) getView()方法中是否有大量对象存在
c) ListView的布局属性
3.滑动的时候不要加载图片
如果你的ListView中需要显示从网络上下载的图片的话,我们不要在ListView滑动的时候加载图片,那样会使ListView变得卡顿,所以我们需要再监听器里面监听ListView的状态,如果滑动的时候,停止加载图片,如果没有滑动,则开始加载图片
listView.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView listView, int scrollState) {
//停止加载图片
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
imageLoader.stopProcessingQueue();
} else {
//开始加载图片
imageLoader.startProcessingQueue();
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
}
});
4.将ListView的scrollingCache和animateCache设置为false
scrollingCache: scrollingCache本质上是drawing cache,你可以让一个View将他自己的drawing保存在cache中(保存为一个bitmap),这样下次再显示View的时候就不用重画了,而是从cache中取出。默认情况下drawing cahce是禁用的,因为它太耗内存了,但是它确实比重画来的更加平滑。而在ListView中,scrollingCache是默认开启的,我们可以手动将它关闭。
animateCache: ListView默认开启了animateCache,这会消耗大量的内存,因此会频繁调用GC,我们可以手动将它关闭掉
5.item的布局层级越少越好
我们应该尽量减少item布局深度,因为当滑动ListView的时候,这回直接导致测量与绘制,因此会浪费大量的时间,所以我们应该将一些不必要的布局嵌套关系去掉。减少item布局深度
6.使用ViewHolder
1.在adapter中的getView方法中尽量少使用逻辑
39.启动应用后,改变系统语言,应用的语言会改变吗?
40.启动一个程序,可以从主界面点击图标进入,也可以从一个程序跳转过去,二者的区别是什么?
其实也没有什么不同,只不过写startActivity的位置不一样而已.
是因为启动程序(主界面也是一个app),发现了在这个程序中存在一个设置为<category android:name="android.intent.category.LAUNCHER" />的activity,
所以这个launcher会把icon提出来,放在主界面上。当用户点击icon的时候,发出一个Intent:
Intent intent = mActivity.getPackageManager().getLaunchIntentForPackage(packageName);
mActivity.startActivity(intent);
跳过去可以跳到任意允许的页面,如一个程序可以下载,那么真正下载的页面可能不是首页(也有可能是首页),这时还是构造一个Intent,startActivity.
这个intent中的action可能有多种view,download都有可能。系统会根据第三方程序向系统注册的功能,为你的Intent选择可以打开的程序或者页面。所以唯一的一点
不同的是从icon的点击启动的intent的action是相对单一的,从程序中跳转或者启动可能样式更多一些。本质是相同的
41.Android程序和java程序的区别?
Android程序用android sdk开发,java程序用javasdk开发.
Android SDK引用了大部分的Java SDK,少数部分被Android SDK抛弃,比如说界面部分,java.awt swing package除了java.awt.font被引用外,其他都被抛弃,在Android平台开发中不能使用。 android sdk 添加工具jar httpclient , pull opengl
将Java 游戏或者j2me程序移植到Android平台的过程中,
Android SDK 与Java SDK的区别是很需要注意的地方。
sampledataadpter()
java文件在android的后缀为dex,在java中是.class
42.Androdi中Task任务栈的分配
首先我们来看下Task的定义,Google是这样定义Task的:a task is what the user experiences as an "application." It's a group of related activities, arranged in a stack. A task is a stack of activities, not a class or an element in the manifest file. 这意思就是说Task实际上是一个Activity栈,通常用户感受的一个Application 它只是针对Activity而言的。
Activity有不同的启动模式, 可以影响到task的分配
Task,简单的说,就是一组以栈的模式聚集在一起的Activity组件集合。它们有潜在的前后驱关联,新加入的Activity组件,位于栈顶,并仅有在栈顶的Activity,才会有机会与用户进行交互。而当栈顶的Activity完成使命退出的时候,Task会将其退栈,并让下一个将跑到栈顶的Activity来于用户面对面,直至栈中再无更多Activity,Task结束。
事件 Task栈 (粗体为栈顶组件)
点开Email应用,进入收件箱(Activity A) A
选中一封邮件,点击查看详情(Activity B) AB
点击回复,开始写新邮件(Activity C) ABC
写了几行字,点击选择联系人,进入选择联系 ABCD
人界面(Activity D)
选择好了联系人,继续写邮件 ABC
写好邮件,发送完成,回到原始邮件 AB
点击返回,回到收件箱 A
退出Email程序 null
如上表所示,是一个实例。从用户从进入邮箱开始,到回复完成,退出应用整个过程的Task栈变化。这是一个标准的栈模式,对于大部分的状况,这样的Task模型,足以应付,但是,涉及到实际的性能、开销等问题,就会变得残酷许多。
比如,启动一个浏览器,在Android中是一个比较沉重的过程,它需要做很多初始化的工作,并且会有不小的内存开销。但与此同时,用浏览器打开一些内容,又是一般应用都会有的一个需求。设想一下,如果同时有十个运行着的应用(就会对应着是多个Task),都需要启动浏览器,这将是一个多么残酷的场面,十个Task栈都堆积着很雷同的浏览器Activity,
是多么华丽的一种浪费啊。
于是你会有这样一种设想,浏览器Activity,可不可以作为一个单独的Task而存在,不管是来自那个Task的请求,浏览器的Task,都不会归并过去。这样,虽然浏览器Activity本身需要维系的状态更多了,但整体的开销将大大的减少,这种舍小家为大家的行为,还是很值得歌颂的
standard", "singleTop", "singleTask", "singleInstance"。
standard模式, 是默认的也是标准的Task模式,在没有其他因素的影响下,使用此模式的Activity,会构造一个Activity的实例,加入到调用者的Task栈中去,对于使用频度一般开销一般什么都一般的Activity而言,standard模式无疑是最合适的,因为它逻辑简单条理清晰,所以是默认的选择。
而singleTop模式,基本上于standard一致,仅在请求的Activity正好位于栈顶时,有所区别。此时,配置成singleTop的Activity,不再会构造新的实例加入到Task栈中,而是将新来的Intent发送到栈顶Activity中,栈顶的Activity可以通过重载onNewIntent来
处理新的Intent(当然,也可以无视...)。这个模式,降低了位于栈顶时的一些重复开销,更避免了一些奇异的行为(想象一下,如果在栈顶连续几个都是同样的Activity,再一级级退出的时候,这是怎么样的用户体验...),很适合一些会有更新的列表Activity展示。一个活生生的实例是,在Android默认提供的应用中,浏览器(Browser)的书签Activity(BrowserBookmarkPage),就用的是singleTop。
singleTask,和singleInstance,则都采取的另辟Task的蹊径。
标志为singleTask的Activity,最多仅有一个实例存在,并且,位于以它为根的Task中。所有对该Activity的请求,都会跳到该Activity的Task中展开进行。singleTask,很象概念中的单件模式,所有的修改都是基于一个实例,这通常用在构造成本很大,但切换成本较小的Activity中。最典型的例子,还是浏览器应用的主Activity(名为Browser...),它是展示当前tab,当前页面内容的窗口。它的构造成本大,但页面的切换还是较快的,于singleTask相配,还是挺天作之合的。
singleInstance显得更为极端一些。在大部分时候singleInstance与singleTask完全一致,唯一的不同在于,singleInstance的Activity,是它所在栈中仅有的一个Activity,如果涉及到的其他Activity,都移交到其他Task中进行。这使得singleInstance的Activity,像一座孤岛,彻底的黑盒,它不关注请求来自何方,也不计较后续由谁执行。在Android默认的各个应用中,很少有这样的Activity,在我个人的工程实践中,曾尝试在有道词典的快速取词Activity中采用过,
是因为我觉得快速取词入口足够方便(从notification中点选进入),并且会在各个场合使用,应该做得完全独立。
大的apk 拆成 很多小的apk
●Activity的android:affinity属性
1.配置后 当启动这个activity时就先去找有没有activity的亲和力属性相同 有就加入这个
activity所在的任务中没有就新开任务
2.affinity起作用需要的条件二者具备一个:
1.intent包含FLAG_ACTIVITY_NEW_TASK标记
2.activity元素启用了allowTaskReparenting属性.
43.在Android中,怎么节省内存的使用,怎么主动回收内存?
回收已经使用的资源
比如你创建了一个list,你用完之后,确定以后不需要再用他的,及时的list.clear(),就不会造成内存泄露
合理的使用缓存
比如我们listview设置图片的时候,第一次加载会吧图片从网络加载,然后在加载到本地,从本地加载到内存.
合理设置变量的作用范围… application 对象
//未来的某一段时间执行
System.gc();
44.不同的工程的方法是否可以相互调用?
可以,比如aidl.
45.在Android中是如何实现判断区分电话的状态,去电,来电,未接来电?
46.dvm的进程和linux的进程,应用程序的进程是否为同一概念?
Dvm的进程是dalivk虚拟机进程,每个android程序都运行在自己的进程里面,
每个android程序系统都会给他分配一个单独的liunx uid(user id),
每个dvm都是linux里面的一个进程.所以说这两个进程是一个进程.
47.sim卡的ef文件有何作用?
没有接触过,ef是做存储用的.我研究研究就会了.
sim卡的文件系统有自己规范,主要是为了和手机通讯,sim本 身可以有自己的操作系统,EF就是作存储并和手机通讯用的
48.如何判断是否有sd卡?
配置文件中有sd卡的权限,通过environment的静态方法
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
49.嵌入式操作系统内存管理有哪几种,各有什么特性?
页式,比如有一个2g的内存,如何把2g的内存分成很多份,一页就打2mb吧,如果你有一个文件小于2mb,就分一页给文件,如果大于2mb,就多分一页给他.页式有一个缺点,如果是0.2mb的,就会造成内存浪费.
段式,是随机的分,比如1mb,2mb,或者更小,分完以后,他把段式的地址保存起来,类似于hashmap的,然后就去匹配.段式的缺点是你比如一个5mb的文件,要把相邻的内存地址加起来,直到匹配,这是一个复杂的过程.
段页,把所有的内存,分成很多页,然后每一页分成很多段的
50.什么是嵌入式实时操作系统,Android操作系统属于实时操作系统吗?
实时操作系统是指当外界事件或数据产生时,能够接受并以足够快的速度予以处理,其处理的结果又能在规定的时间之内来控制生产过程或对处理系统作出快速响应,并控制所有实时任务协调一致运行的嵌入式操作系统。主要用于工业控制、军事设备、航空航天等领域对系统的响应时间有苛刻的要求,这就需要使用实时系统。
简单来说实时操作系统就是你在系统干一件事,然后你突然想干另外一件事了,系统说好,我保存一个这件事的状态,然后就去干另外一件事了.
又可分为软实时和硬实时两种,而android是基于linux内核的,因此属于软实时。软实时就是通过软件去中断,硬实时就是通过邮件去实时.硬实时比软实时更加快速.
嵌入式指的就是对cpu,内存要求非常低,只需要一个cpu和几mb的内存,就能启动一个程序.
51.一条最长的短信息约占多少byte?
标准的是中文70(包括标点),英文160,160个字节,这个说法不是很准确,要跟手机制式运营商等信息有关.
做个试验就知道了
SmsManager sm=SmsManager.getDefault();
ArrayList<String> msgs=sm.divideMessage("信息");
sm.sendTextMessage(phone,null, s, null, null);
52.Linux中跨进程通信的几种方式.
Linux
# 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
# 有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
# 信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
# 消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
# 信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
# 共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。
# 套接字( socket ) : 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。
53. 谈谈对Android NDK的理解。
native develop kit 只是一个交叉编译的工具 .so
1.什么时候用ndk, 实时性要求高,游戏,图形渲染, opencv (人脸识别) , ffmpeg , rmvb mp5 avi 高清解码. ffmpeg, opencore.
2.为什么用ndk,ndk的优点,效率高
缺点 ,出现了bug很难解决
NDK是一些列工具的集合,
NDK提供了一系列的工具,帮助开发者迅速的开发C/C++的动态库,并能自动将so和java 应用打成apk包。
NDK集成了交叉编译器,并提供了相应的mk文件和隔离cpu、平台等的差异,开发人员只需简单的修改mk文件就可以创建出so
54.谈谈android的优点和不足之处
1、开放性,开源 ophone 阿里云( 完全兼容android)
2、挣脱运营商束缚
3、丰富的硬件选择 mtk android
4、不受任何限制的开发商
5、无缝结合的Google应用
缺点也有5处:
1、安全问题、隐私问题
2、卖手机的不是最大运营商
3、运营商对Android手机仍然有影响
4、山寨化严重
5、过分依赖开发商,缺乏标准配置
55.Android系统中GC什么情况会出现内存泄露?
视频编解码/内存泄露
检测内存泄露 工具
mat
C:\Users\lenovo\Desktop\prof>hprof-conv com.example.testmat.hprof convert-com.ex
ample.testmat.hprof
导致内存泄漏主要的原因是,先前申请了内存空间而忘记了释放。如果程序中存在对无用对象的引用,那么这些对象就会驻留内存,消耗内存,因为无法让垃圾回收器GC验证这些对象是否不再需要。如果存在对象的引用,这个对象就被定义为"有效的活动",同时不会被释放。要确定对象所占内存将被回收,我们就要务必确认该对象不再会被使用。典型的做法就是把对象数据成员设为null或者从集合中移除该对象。但当局部变量不需要时,不需明显的设为null,因为一个方法执行完毕时,这些引用会自动被清理。
Java带垃圾回收的机制,为什么还会内存泄露呢?
Vector v = new Vector(10);
for (int i = 1; i < 100; i++){
Object o = new Object();
v.add(o);
o = null;
}//此时,所有的Object对象都没有被释放,因为变量v引用这些对象。
Java 内存泄露的根本原因就是 保存了不可能再被访问的变量类型的引用
56. Android UI中的View如何刷新。
在主线程中 拿到view调用Invalide()方法,查看画画板里面更新imageview的方法
在子线程里面可以通过postInvalide()方法;
View view;
view.invalidate();//主线程
view.postInvalidate();//子线程
57. 简单描述下Android 数字签名。
Android 数字签名
在Android系统中,所有安装到系统的应用程序都必有一个数字证书,此数字证书用于标识应用程序的作者和在应用程序之间建立信任关系
Android系统要求每一个安装进系统的应用程序都是经过数字证书签名的,数字证书的私钥则保存在程序开发者的手中。Android将数字证书用来标识应用程序的作者和在应用程序之间建立信任关系,不是用来决定最终用户可以安装哪些应用程序。
这个数字证书并不需要权威的数字证书签名机构认证(CA),它只是用来让应用程序包自我认证的。
同一个开发者的多个程序尽可能使用同一个数字证书,这可以带来以下好处。
(1)有利于程序升级,当新版程序和旧版程序的数字证书相同时,Android系统才会认为这两个程序是同一个程序的不同版本。如果新版程序和旧版程序的数字证书不相同,则Android系统认为他们是不同的程序,并产生冲突,会要求新程序更改包名。
(2)有利于程序的模块化设计和开发。Android系统允许拥有同一个数字签名的程序运行在一个进程中,Android程序会将他们视为同一个程序。所以开发者可以将自己的程序分模块开发,而用户只需要在需要的时候下载适当的模块。
在签名时,需要考虑数字证书的有效期:
(1)数字证书的有效期要包含程序的预计生命周期,一旦数字证书失效,持有改数字证书的程序将不能正常升级。
(2)如果多个程序使用同一个数字证书,则该数字证书的有效期要包含所有程序的预计生命周期。
(3)Android Market强制要求所有应用程序数字证书的有效期要持续到2033年10月22日以后。
Android数字证书包含以下几个要点:
(1)所有的应用程序都必须有数字证书,Android系统不会安装一个没有数字证书的应用程序
(2)Android程序包使用的数字证书可以是自签名的,不需要一个权威的数字证书机构签名
58. 什么是ANR 如何避免它?
在Android上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框称作应用程序无响应(ANR:Application Not Responding)对话框。用户可以选择让程序继续运行,但是,他们在使用你的应用程序时,并不希望每次都要处理这个对话框。因此,在程序里对响应性能的设计很重要,这样,系统不会显示ANR给用户。
Activity 5秒 broadcast10秒
耗时的操作 worker thread里面完成, handler message…AsynTask , intentservice.等…
59. android中的动画有哪几类,它们的特点和区别是什么?
两种,一种是Tween动画、还有一种是Frame动画。
Tween动画,这种实现方式可以使视图组件移动、放大、缩小以及产生透明度的变化;
可以通过布局文件,可以通过代码
1、控制View的动画
a) alpha(AlphaAnimation)渐变透明
b) scale(ScaleAnimation) 渐变尺寸伸缩
c) translate(TranslateAnimation)画面转换、位置移动
d) rotate(RotateAnimation)画面转移,旋转动画
2、 控制一个Layout里面子View的动画效果
a) layoutAnimation(LayoutAnimationController)
b) gridAnimation(GridLayoutAnimationController)
另一种Frame动画,传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影。
属性动画 ObjectAnimator
Tween和Frame动画是把view显示的位置改变的,但是view原生的位置是不变的,
属性动画是真正的把view的位置改变了
63. 通过点击一个网页上的url 就可以完成程序的自动安装,描述下原理
通过javascript,用过webview的都知道,可以在网页中,用js调用java方法,我们就可以通过这种形式去搞定
64,Service和Activity在同一个线程吗
默认情况同一线程 main主线程 ui线程
65,java中的soft reference是个什么东西
StrongReference 是 Java 的默认引用实现(软引用), 它会尽可能长时间的存活于 JVM 内, 当没有任何对象指向它时 GC 执行后将会被回收
SoftReference 会尽可能长的保留引用直到 JVM 内存不足时才会被回收(虚拟机保证), 这一特性使得 SoftReference 非常适合缓存
在android2.3以上的系统,会更倾向于回收软引用和弱引用,因此使用它们不在变得可靠,
鉴于此,谷歌推出了新的缓存
LruCache
least recentlly use最少最近使用算法
会将内存控制在一点的大小内,超出最大值时会自动回收,这个最大值开发者自己定
应用详细见客户端图片的缓存
66,udp连接和TCP的不同之处
tcp/滑动窗口协议. 拥塞控制. 面向连接 流
udp 不关心数据是否达到,是否阻塞 面向无连接
画面优先. tcp
流畅优先 udp
简单的说TCP与UDP的区别是有无连接状态。
TCP是有连接状态的,而UDP没有,所以TCP是一种比较安全的通讯协议,而UDP则比较方便
TCP 127.0.0.1:1026 0.0.0.0:0 LISTENING
TCP 是传输协议 TCP是主动连接 网页什么的用TCP(貌似)
UDP也是传输协议 UDP迂回连接 QQ就用UDP (貌似)
127.0.0.1 是本地回环地址
1026 是端口
LISTENING 是监听
TCP 127.0.0.1:1026 0.0.0.0:0 LISTENING
全意是 监听 TCP 1026端口
0.0.0.0 是没有东西 为零
0 端口就是没有。。。ING
TCP是面向连接的
UDP是面向无连接的
就是这种关系了
TCP(Transmission Control Protocol,传输控制协议)
UDP(User Datagram Protocol,用户数据包协议)
当IP包通过路由将数据传输到目的地时,会根据TCP或UDP包头中的源端口和目的端口信息,请求和获取不同的应用。也就是说,不管TCP还是UDP,都含有网络服务必须的源端口和目的端口信息,以建立和实现网络传输服务。这时,你的疑问就来了:既然都用于传输,为何要搞两个不同的协议呢?这就需要从网络中不同服务的需求来谈起。
在网络中,有些服务,如HTTP、FTP等,对数据的可靠性要求较高,在使用这些服务时,必须保证数据包能够完整无误的送达;而另外一些服务,如DNS、即时聊天工具等,并不需要这么高的可靠性,高效率和实时性才是它们所关心的。根据这两种服务不同的需求,也就诞生了面向连接的TCP协议,以及面向无连接的UDP协议。
这里的连接(Connection)和无连接(Connectionless)是网络传输中常用的术语,它们的关系可以用一个形象地比喻来说明,就是打电话和写信。
打电话时,一个人首先必须拨号(发出连接请求),等待对方响应,接听电话(建立了连接)后,才能够相互传递信息。通话完成后,还需要挂断电话(断开连接),才算完成了整个通话过程。写信则不同,你只需填写好收信人的地址信息,然后将信投入邮局,就算完成了任务。此时,邮局会根据收信人的地址信息,将信件送达指定目的地。
我们可以看到,这两者之间有很大不同。打电话时,通话双方必须建立一个连接,才能够传递信息。连接也保证了信息传递的可靠性,因此,面向连接的协议必然是可靠的。无连接就没有这么多讲究,它不管对方是否有响应,是否有回馈,只管将信息发送出去。就像信件一旦进了邮箱,在它到达目的地之前,你没法追踪这封信的下落;接收者即使收到了信件,也不会通知你信件何时到达。在整个通讯过程中,没有任何保障。因此我们常说,面向无连接的协议也是不可靠的。当然,邮局会尽力将右键送到目的地,99%的情况信件会安全到达,但在少数情况下也有例外。
面向连接的协议比面向无连接的协议在可靠性上有着显著的优势,但建立连接前必须等待接收方响应,传输信息过程中必须确认信息是否传到,断开连接时需要发出响应信号等,无形中加大了面向连接协议的资源开销。具体到TCP和UDP协议来说,除了源端口和目的端口,TCP还包括序号、确认信号、数据偏移、控制标志(通常说的URG、ACK、PSH、RST、SYN、FIN)、窗口、校验和、紧急指针、选项等信息,UDP则只包含长度和校验和信息。UDP数据报比TCP小许多,这意味着更小的负载和更有效的使用带宽。许多即时聊天软件采用UDP协议,与此有莫大的关系。
TCP---传输控制协议,提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。 UDP---用户数据报协议,是一个简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。 用TCP还是UDP,那要看你的程序注重哪一个方面?可靠还是快速?
TCP UDP是两个协议,简单的说,TCP连接要对方确认的,而UDP却不需要对方确认收到包,所以TCP连接更加安全,但是一般播放网络流媒体使用UDP协议
传输层协议一般有TCP和UDP,TCP为可靠传输,协议本身会保证数据传输的可靠,但为此会付出很多额外的网络开销。UDP为不可靠传输,所以传输效率比较高,本端只负责发送数据,不保证对端能否收到。对于UDP,可靠性可以在应用层实现
http是基于tcp的,udp我们一般用于视频开发
67, android开发中怎么去调试bug
逻辑错误
1.断点 debug
2. logcat(Threads:能检测你执行到哪个方法了),
3. traceview:检测每块代码执行的时间,对代码进行优化
如何在百万代码中快速定位错误的代码:
如果有错误,肯定会在界面显示,然后我们在tools/hierarchyviewer.bat
68.service里面可以弹土司么
可以.
69.写10个简单的linux命令
70 JNI调用常用的两个参数
JNIEnv *env, jobject javaThis
71. 书写出android工程的目录结构
src
android. jar
asset
res
gen
manifest
72. ddms 和traceview的区别.
DDMS透视图包含了多个视图,例如,File Explorer(用于浏览移动设备目录中的目录和文件)Logcat(查看调试信息),Emulator Control(用于控制模拟器)等,也就是谁DDMS是一个集调试,浏览,控制等操作为一体的工具集.而Traceview只是一个性能调试工具.开发人员可以利用该TraceView查看程序中方法的执行效率
72.1TraceView的使用方法
TraceView是一个性能调优的图形化工具,在使用TraceView之前,使用下面的代码生成一个trace文件
Debug.startMethodTracing("test")
其中activity_trace是跟踪文件名,执行上面的代码后,会在sdcard目录生成一个test.trace文件,字节数为0,一般在activity.ondestroy方法中执行如下的代码将跟踪结果写入activity_trace.trace文件
Debug.stopMethodTracing();
将sdcard目录中的test.trace文件复制到pc上的相应目录(假设复制到了D:\sdcard目录),然后在windows控制台输入如下的命令启动TraceView图形化的跟踪界面
Traceview d:\sdcard\test.trace
执行该命令会启动traceview的图形界面,在该界面显示了从跟踪开始到跟踪结束的所有方法的调用事件,执行事件,被调用次数等信息,可以利用这些信息对程序进行调优
73. 如何将SQLite数据库(dictionary.db文件)与apk文件一起发布?
任何文件(包括sqlite数据库文件)与apk程序一同发布都必须将该文件嵌入到apk文件中.对于sqlite数据库来说,androdi程序不能打开和操作嵌入在apk程序中的数据库文件.因此需要想办法在程序第一次启动时将sqlite数据库文件复制到手机内存或sd卡,然后在操作sqlite熟客.
由于android程序不能打开嵌入apk文件中的sqlite数据库,因此将sqlite数据库放在androdi应用程序的assets或res/raw目录中.因为只有这2个目录中的资源文件不会被编译.在程序第一次启动时将使用下面的代码将sqlite数据库文件赋值到手机内或sd卡
String databaseFilename="";
try {
databaseFilename="/sdcard/test.db";
//当test.db文件不存在时,将res/raw目录中的数据文件复制到sd卡
if(!(new File(databaseFilename).exists())){
InputStream is=getResources().openRawResource(R.raw.test);
//写文件
FileOutputStream fos=new FileOutputStream(databaseFilename);
byte[] buffer=new byte[1024];
int count=0;
while ((count=is.read(buffer))>0) {
fos.write(buffer,0,count);
}
fos.close();
is.close();
}
} catch (Exception e) {
// TODO: handle exception
}
//打开数据库
SQLiteDatabase database=SQLiteDatabase.openOrCreateDatabase(databaseFilename,
null);
74. 如何将打开res aw目录中的数据库文件?
解答:在Android中不能直接打开res aw目录中的数据库文件,而需要在程序第一次启动时将该文件复制到手机内存或SD卡的某个目录中,然后再打开该数据库文件。复制的基本方法是使用getResources().openRawResource方法获得res aw目录中资源的 InputStream对象,然后将该InputStream对象中的数据写入其他的目录中相应文件中。在Android SDK中可以使用SQLiteDatabase.openOrCreateDatabase方法来打开任意目录中的SQLite数据库文件。
75. Android引入广播机制的用意?
答:a:从MVC的角度考虑(应用程序内)
其实回答这个问题的时候还可以这样问,android为什么要有那4大组件,现在的移动开发模型基本上也是照搬的web那一套MVC架构,只不过 是改了点嫁妆而已。android的四大组件本质上就是为了实现移动或者说嵌入式设备上的MVC架构,它们之间有时候是一种相互依存的关系,有时候又是一 种补充关系,引入广播机制可以方便几大组件的信息和数据交互。
b:程序间互通消息(例如在自己的应用程序内监听系统来电)
c:效率上(参考UDP的广播协议在局域网的方便性)
d:设计模式上(反转控制的一种应用,类似监听者模式)
76.android 中有哪几种解析xml的类?官方推荐哪种?以及它们的原理和区别。
XML解析主要有三种方式,SAX、DOM、PULL。常规在PC上开发我们使用Dom相对轻松些,但一些性能敏感的数据库或手机上还是主要采用SAX方 式,SAX读取是单向的,优点:不占内存空间、解析属性方便,但缺点就是对于套嵌多个分支来说处理不是很方便。而DOM方式会把整个XML文件加载到内存 中去,这里Android开发网提醒大家该方法在查找方面可以和XPath很好的结合如果数据量不是很大推荐使用,而PULL常常用在J2ME对于节点处 理比较好,类似SAX方式,同样很节省内存,在J2ME中我们经常使用的KXML库来解析。
详细情况请参考 http://blog.csdn.net/Android_Tutor/archive/2010/09/17/5890835.aspx
http://www.linuxidc.com/Linux/2010-11/29768.htm
http://littlefermat.blog.163.com/blog/static/59771167200981853037951/
77 描述一下android的系统架构
android系统架构分从下往上为linux 内核层、运行库、应用程序框架层、和应用程序层
linuxkernel:负责硬件的驱动程序、网络、电源、系统安全以及内存管理等功能。
libraries和 androidruntime:libraries:即c/c++函数库部分,大多数都是开放源代码的函数库,例如webkit,该函数库负责 android网页浏览器的运行,例如标准的c函数库libc、openssl、sqlite等,当然也包括支持游戏开发2dsgl和 3dopengles,在多媒体方面有mediaframework框架来支持各种影音和图形文件的播放与显示,例如mpeg4、h.264、mp3、 aac、amr、jpg和png等众多的多媒体文件格式。android的runtime负责解释和执行生成的dalvik格式的字节码。
applicationframework(应用软件架构),java应用程序开发人员主要是使用该层封装好的api进行快速开发。该层主要由view,通知管理器(notification manager),活动管理器(Activity Manager)等由开发人员直接调用的api组成.
applications:该层是java的应用程序层,android内置的googlemaps、e-mail、即时通信工具、浏览器、mp3播放 器等处于该层,java开发人员开发的程序也处于该层,而且和内置的应用程序具有平等的位置,可以调用内置的应用程序,也可以替换内置的应用程序。
上面的四个层次,下层为上层服务,上层需要下层的支持,调用下层的服务,这种严格分层的方式带来的极大的稳定性、灵活性和可扩展性,使得不同层的开发人员可以按照规范专心特定层的开发。
android应用程序使用框架的api并在框架下运行,这就带来了程序开发的高度一致性,另一方面也告诉我们,要想写出优质高效的程序就必须对整个 applicationframework进行非常深入的理解。精通applicationframework,你就可以真正的理解android的设计 和运行机制,也就更能够驾驭整个应用层的开发。
78.Android的特点
1.Android拥有完善的应用程序框架,支持四大组件,可以在任一层次上进行复用和更换
2.虽然android的主要编程语言是Java,但是Android中java字节码是运行在Dalvi虚拟机上的,传统的JVM是基于堆栈的,而Dalvik虚拟机是基于寄存器的.因此,在Dalvik运行的java程序要比在传统的JVM上运行的Java程序速度更快
3.Android中内置了WEBKIT核心的浏览器,支持HTML5等新的web标准
4.2d和3d绘图功能丰富,支持OpenGl 2.0,如果手机中带有硬件加速器,3d图形的渲染会更加流畅.
5.支持轻量级的SQLite数据库
6.支持众多的硬件传感器(比如方向传感器,重力传感器,光学传感器,压力传感器)和其他一些硬件,比如蓝牙,3g,WIFI,Camera,GPS等
79.搭建Android开发环境需要些什么?
1.jdk(1.6以上)
2.Eclipse(3.4以上版本)
3.Android SDK
4.ADT
80.说说mvc模式的原理,Android sdk有哪些组件使用到了mvc模式,其基本原理是什么?
到现在为止MVC模式已经得到了广泛的应用,各种类型的程序(桌面程序,WEB程序,移动程序)都涉及了mvc模式,著名的java web框架Strtus就是一套不折不扣的mvc框架.mvc的主要目的就是使程序中的数据和界面分离,其中
m表示模型(model),也就是数据
v表示视图(view),界面
c表示控制器(controller),用于处理m和v之间的联系
MVC基本原理就是通过controller连接view和model,也就是说,当view中显示的数据变化时,会通知controller,而不是直接通知model,这是controller接到view的通知,会在model中采取相应的动作,根据用户在view做的动作,ontroller会通知给model做出相应的操作,moder中的变化会通知控制器,然后控制器会通过视图重新更新显示数据.
使用mvc模式可以将显示部分和数据部分分离解耦,这样当更换视图或模型可以不影响对方,更有利于程序的维护.
在Anddroid sdk中使用mv模式的组件非常多,例如所有的列表控制(listview,spinner(下拉列表),Gridview)都采用mvc模式和数据交互.在Android中的mvc的
m就是代表各种数据源以及操作数据库的库.
C则代表Adapter类.而android的adapter分很多程度,但拥有共同的接口.这些Adapter类主要包括BaseAdapter,SimpleAdapter,SimpleCursorAdapter,ArrayAdapter,CursorAdapter等,他们分别对应不同的数据源,例如ArrayAdapter对应list和数组数据源,而cursorAdapter对应Cursor对象(一般从数据库中获取的记录集).这些adapter会调用getView方法用于重新显示组件中的内容.当组件中显示的数据发生变化,例如删除一行,组件会通过adapter中的方法删除model中相应的记录,然后在调用baseAdapter.notofyDataSetChanged方法使组件中显示的数据发生变化,总之一句话,无论是数据变化,还是组件中显示的数据发生变化,都需要adapter作为桥梁来达到view和model之间同步的目的.
81.ADB突然死掉了怎么办?
ADT通过adb服务与模拟器进行通信.由于adb服务并不算稳定,可能在启动时间较长时间或启动多个模拟器时会突然死的,死掉后的ADT就会与模拟器失去联系,例如无非浏览模拟器中的目录,无非向模拟器发短信.在这种情况下,就需要对adb服务进行重启.重启的方式
1.在ddms的devices视图右上菜单中点击reset adb菜单项重启adb服务.
2.关闭模拟器,并重新启动
3.在任何管理器的进程列表结束adb.exe进,任何关闭模拟器,再次重新启动模拟器
4.如果还是不行,只能重启eclipse
82.<LinearLayoutxmlns:android="http:schemas.android.com/apk/res/android"..>中的xmlns:android是什么意思?xmlns:android的值可以任意设置吗?请说明原因.
这道题表面上考查xml命名空间与布局文件的关系,但实际上这个问题可以进一步深入.例如,布局文件的命名空间与自定义组件的关系紧密.可以考查应聘者如何预定义自定义组件的属性?
在自定义组件时,需要使用<declare-styleable>标签定义属性名,然后需要在布局文件的最顶层标签中指定R。java文件的位置.
假设有一个Android程序的package是mobile.android.yd.interview.现在编写一个自定义组件.首先在res\values目录中建立一个attrs.xml文件.
<resources>
<declare-styleable name="EditTextExt">
<attr name="attr1" format="referene">
</declare-styleable>
</resources>
上面的代码会在R.attr类中生成一个attr1变量.如果在布局文件中使用EditTestExt的attr1属性,就需要指定命名空间.
xml:android是xml中的命名空间,为了防止属性冲突.类似于java中的package.xml:android的值不允许任意设置.xml:android的值必须以“http://schemas.android.com/apk/res”开头,后面的部分表示定义属性的R.java文件所在的包名.在R.java文件中包含了属性名的定义.例如,如果使用系统属性,需要指定系统R.java文件的位置.该文件位于res\android目录中.因此,xmlns:android的值的最后是android
83.FrameLayout的主要用途
FrameLayout主要用于进行层次结构的布局.例如想把多个图片叠加到一起形成一张图像的效果就用framelayout.
84.FrameLayout中的view是层叠摆放的,后一个view会覆盖前一个view,这种说法对面?说明原因
不正确,Framelayout中的view只有在所在的view同样大小并且位置一样才会覆盖.否则view是以层叠方式显示的,类似于photoshop的图层,未被上一层view覆盖的部分会显示出来.
85.在relativeLayout中有一个button按钮,请确定该按钮相对于手机屏幕的位置坐标
获取button,使用button.getLocationOnScren方法可以获取当前view相对于屏幕的坐标
86.在relativeLayout不居中可以设置标签的android:layout_toleOf,android:layout_toRightof等属性确定组件的相对位置,那么如何用java代码来完成这些工作.
以button按钮为例
//装载一个布局文件,要向这个布局文件动态添加一个button
RelativeLayout relativeLayout=(RelativeLayout) getLayoutInflater().
inflate(R.layout.activity_main,null);
//装载要动态添加的按钮布局
Button button=(Button)getLayoutInflater().inflate(R.layout.button,null);
//创建一个layoutParams对象
RelativeLayout.LayoutParams layoutParams=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
//R.id.button1是relativelayout中已经存在的一个按钮的id,动态添加的按钮在该按钮的右下方
//设置android:layout_toRightOf属性的值
layoutParams.addRule(RelativeLayout.RIGHT_OF,R.id.button1);
layoutParams.addRule(RelativeLayout.BELOW,R.id.button1);
//更新button按钮中相应属性的值
button.setLayoutParams(layoutParams);
//relativeLyout动态添加一个按钮
relativeLayout.addView(button);
87.TableLayout布局的用法
TableLayout布局使用<TableLayout>来表示,在<TableLayout>中嵌套<TableRow>标签来表示表格布局中的每一条.<TableRow>标签中可以有不定数目的view.因此,每一条中的列数可以不相等.
<TableLayout>
<TableRow>
<TextView android:text="第一行第一列"/>
<TextView android:text="第一行第二列"/>
</TableRow>
<TableRow>
<TextView android:text="第一行第一列"/>
<TextView android:text="第一行第二列"/>
<TextView android:text="第一行第三列"/>
</TableRow>
<TableLayout>
88.TableLayout标签的stretchColumns属性的作用是什么,如何使用stretchColumns属性
strechColumns属性用于要拉伸(所谓的拉伸就是比如是水平方向的你把第一列设置到了strechColumns属性中,他会主动把你第一列的宽度占用了)的列的索引(从0开始),如果指定多个索引,中间用逗号(,)隔开.TableLayout会在设置完未通过strechColumns指定的列宽度后,使用stretchColumns指定的列填充剩余的宽度.如果strehColumns指定了多列,这些列会平分剩余的宽度
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:stretchColumns="1"
>
<TableRow
>
<TextView
android:text="第一行第一列"
android:layout_column="1"
/>
<TextView
android:text="第一行第二列"
/>
</TableRow>
<TableRow
>
<TextView
android:text="第二行第一列"
android:layout_column="1"
/>
<TextView
android:text="第二行第二列"
/>
</TableRow>
</TableLayout>
89.介绍AbsoluteLayout布局的用法
AbsoluteLayout称为绝对布局,也可以称为坐标布局.view可以在absoluteLayout布局中通过坐标定位.
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@android:drawable/btn_default"
android:layout_x="13px"
android:layout_y="24px"/>
</AbsoluteLayout>
90.如何动态都是改变absoluteLayout布局中view的位置?
ImageView view=(ImageView) findViewById(R.id.iv1);
//设置view的坐标(layoutParams构造方法的最后2个参数,
//也可以通过LayoutParams.x和LayoutParams.y设置)
AbsoluteLayout.LayoutParams layoutParams=new AbsoluteLayout
.LayoutParams(android.widget.AbsListView.LayoutParams.WRAP_CONTENT,
android.widget.AbsListView.LayoutParams.WRAP_CONT ENT,300, 300);
view.setLayoutParams(layoutParams);
91.如何将当前界面的可视组件以同样的相对位置和大小写保存成png图像文件中?
本题分2部分回答:截取当前界面的组件和保存成png图像文件.首先要调用view.setDrawingCacheEnabled方法打开图像缓存,然后使用view.getDrawingCache方法获取view的bitmap对象.保存成png图像使用biemap.compress方法即可.
将当前界面的可视化组件以同样的相对位置和大小保存在png图像文件即可
View view=getLayoutInflater().inflate(R.layout.main1,null);
//打开图像缓存
view.setDrawingCacheEnabled(true);
//必须要调用measure和layout方法才能成功保存可视组件的截图到png图像文件
//测量view的大小
view.measure(MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED) ,
MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED));
//发送位置和尺寸到view及其所有的子view
view.layout(0,0,view.getMeasuredWidth(),view.getMeasuredHeight());
try {
//获取可视化组件的截图
Bitmap bitmap=view.getDrawingCache();
//将截图保存在sd卡根目录的test.png图像文件中
File file=new File(getCacheDir(),"/test.png");
FileOutputStream fos=new FileOutputStream(file);
//将bitmap对象中的图像数据压缩成png格式的图像数据,
//并将数据保存在test.png文件中
bitmap.compress(CompressFormat.PNG,100,fos);
fos.close();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
92.使用下面代码可以成功的获取布局的bitmap对象吗?并说明原因
View view=getLayoutInflater().inflate(R.layout.main1,null);
//打开图像缓存
view.setDrawingCacheEnabled(true);
Bitmap bitmap=view.getDrawingCache();
不能,因为在 view.getDrawingCache();方法之前需要先主动调用view的测量和布局方法才能成功的获取布局的bitmap对象
93.如何将Android应用程序窗口的背景色设成渐变颜色?
虽然可以使用渐变色的图像来渲染窗口背景,但是更好的选择是使用GradientDrawable类,因为这样更灵活,可以随时变化背景的渐变色.
//设置从上到下的渐变色,上方是红色,下方是黄色
GradientDrawable gradientDrawable=new GradientDrawable(Orientation.TOP_BOTTOM,
new int[]{Color.RED,Color.YELLOW});
//设置当前窗口的渐变背景色
getWindow().setBackgroundDrawable(gradientDrawable);
94.如何在editText中显示提示文本,在提示文本后面可以输入文本?
在EditTest内部提示文本(前部分被锁,不可删除和修改,文本在后部分输入)一般可以通过android:drawableLeft属性来实现.首先做一个带有提示文本的图像(文字当做图像来显示),并通过android:drawableLeft属性指定该图文件的资源id,但是这种方法并不灵活,如果想换提示文本,需要换图像.当然另外一种就是通过android:paddingLeft属性和Canvas来实现.这种方法可以更灵活的处理提示文本.在回答这类问题时建议采用第二种方法
直接在edittext中绘制文本.首先写一个继承自edittext的类,并覆盖onDraw方法,在该方法中绘制提示文本
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
Paint paint=new Paint();
paint.setTextSize(18);
paint.setColor(Color.GRAY);
canvas.drawText("输入提示文本",2,getHeight()/2+5, paint);
super.onDraw(canvas);
}
绘制完文本以后,需要在提示文本后输入文本,这需要使用到paddingleft属性,根据提示文本的宽度设置开始输入到文本的位置,例如android:paddingLeft=100dp,表示从左侧100个dp开始输入文本
95.android:padding、android:layout_margin、android:layout_width、android:layout_height、android:textSize等属性可以设置哪几种尺寸计量单位
目前android sdk支持的尺寸单位有6个:px(像素),in(英寸),mm(毫米),pt(一个物理点1/72英寸),dp(与密度无关的像素),sp(与比例无关的像素),其中px,in,mm,pt,用来设置绝对尺寸的单位,并不会随着屏幕的分辨率的变化而做出相应的调整,而dp和sp会随着分辨率的变化进行调整,所以除了特殊需要,建议使用dp作为尺寸单位,而使用sp作为字体的尺寸单位.
由于手机屏幕分辨率各有不同而且无法调整手机的分辨率,因此android sdk提供了dp和sp这2个尺寸单位来根据分辨率的调整组件和字体的大小。dp和sp都是相对于160dpi的尺寸单位的.160dp相当于每英寸屏幕上有160个物理像素点,一般320*480或类似大小的分辨率的屏幕都是160dpi.因此如果程序运行在160dpi屏幕的手机上,dp、sp和px的效果是一样的,但如果是更高分辨率从的屏幕,如240dpi(480*800),px依然会根据实际物理像素处理,而dp和sp会用当前值乘以一个系数(240/160=1.5)例如,如果2个按钮的android:layout_width属性值分别设为160px和160dp,在320*480分辨率的屏幕上按钮的宽度是完全相同的,但是在480*800分辨率从的屏幕上的宽度为160dp的按钮的实际宽度为240px,会比宽度在160px的按钮宽50%。在不同分辨率屏幕上显示的效果
sp不仅可以按屏幕密度对尺寸进行调整还可以按着用户设置的不同字体调整文字的尺寸使文字以最好的效果显示.因此建议设置文字大小时使用sp,设置其他尺寸使用dp
96.android:layout_gravity属性和android:gravity属性的区别
android:layout_gravity属性指定了当前view在父view中的位置,而android:gravity属性指定了view内容的位置
97.如何重用布局文件
可以使用include标签引用其他布局文件
98.你觉得直接在布局文件的顶层节点使用framelayout好不好,有没有可能使用其他节点取代framela?
无论布局文件的根节点是什么,系统会在上一层生成一个framelayout标签,因此在布局文件的根节点使用framelayout是多余的,但是xml文件又不能没有根节点,因此使用merge代替framelayout,系统在编译xml布局文件不会喂merge生成任何阶段,相当于一个xml文件的节点占位符.merge的意思实际上也是合并2个framela,所以使用merge代替根节点的framelayout可以大大减少framelayout标签的生成.
99.为了研究修改布局的实现,如何查看apk文件中的布局文件源代码呢?
由于apk的ml布局文件是经过编译处理的,无法直接阅读.因此,需要使用反编译工具处理后在阅读这些文件.例如可以先将apk文件解压,然后使用AXMLPrinter2工具对xml布局文件反编译,为了方便,可以将调用AXMLPrinter2的命令行代码放在axml.cmd文件中
100.android:id属性是必须的吗?
android:id属性在xml布局文件中并不一定要知道,当你需要在java代码中通过xml布局代码创建组件属性,在相对布局中组件通过一些属性确定组件之间的相对位置那么久需要知道android:id属性
101.Android sdk支持哪些方式显示富文本信息(不同颜色、大小、并包含图像的文本信息),并简要说明实现方法
1.使用textView组件可以显示富文本信息.在textview组件中可以使用富文本标签显示富文本信息,这种标签类似于HTML标签,但比html标签简单,支持有限的几种显示富文本的方式.如<font>标签用于设置字体和颜色,<b>用于设置粗体.包含这些标签的文本不能直接作为textview方法的参数值,要先使用Html.fromHtml方法将这些文本转换为CharSequene对象,然后再将该对象作为textview.settext方法的参数值.代码:
TextView tv2=(TextView)findViewById(R.id.tv2);
//通过Html.fromHtml方法设置
CharSequence charSequence=Html.fromHtml("你好",new ImageGetter() {
@Override
public Drawable getDrawable(String source) {
//转载图像资源
Drawable drawable=getResources().getDrawable(R.drawable.ic_launcher);
//设置要显示图像的大小
drawable.setBounds(0,0,
drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight());
return drawable;
}
},null);
tv.setText(charSequence);
2.使用webview组件显示html页面
3.继承view类或子类,并覆盖onDraw方法,在该方法直接绘制富文本或图像
4.上面三种方法都支持图文混排效果,但是第一种方法在显示图像时,需要实现imagegetter接口,并通过imageGetter.getDrawable方法返回封装图像资源的Drawable对象.
5.在textview组件中显示图像还可以使用imageSpan对象,imageSpan对象用于封装bitmap对象,并通过spannableString对象封装imageSpan对象,最后将SpannableString对象作为Textview.settext方法的参数将图像显示在textview组件上
代码:
//使用ImageSpan对象在textview组件显示图像
//根据资源id获取资源图像的bitmap对象
Bitmap bitmap=BitmapFactory.decodeResource(getResources(),
R.drawable.icon);
//根据bitmap对象创建imagespan对象
ImageSpan imageSpan=new ImageSpan(this,bitmap);
/创建一个spannableString对象,以便插入用imagespan对象封装的图像
SpannableString spannableString=new SpannableString("ion");
//用imagespan对象替换icon
spannableString.setSpan(imageSpan, 0,1,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
//将图像显示在textview组件上
tv2.setText(spannableString);
102.TextView组件本身可以显示URL,Email等特殊信息,这些特殊信息都会以链接形式显示,在单机链接时会执行相应的动作,如单机URL链接会打开浏览器显示指定的页面.那么如果想在单机链接后弹出我们自定义的activity,应该怎么做.
使用android.text.style.ClickableSpan.onClick方法编写单机url链接时执行的代码.
String text="显示Activity";
SpannableString spannableString2=new SpannableString(text);
spannableString2.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
// TODO Auto-generated method stub
Intent intent=new Intent(MainActivity.this,ClickActivity.class);
startActivity(intent);
}
}, 0,text.length(),Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
TextView tv3=(TextView) findViewById(R.id.tv3);
//设置内容
tv3.setText(spannableString2);
//在单机链接时必须有要执行的动作
tv3.setMovementMethod(LinkMovementMethod.getInstance());
103.如何为textView组件中显示的文本添加背景色?
使用BackgroundColorSpan对象设置文字背景色
//设置带背景色的文本
TextView tv5=(TextView) findViewById(R.id.tv5);
String text1="带背景色的文本";
//将字符串转换为SpannableString对象
SpannableString spannableString3=new SpannableString(text1);
//确定要设置的字符串的start和end
int start=0;
int end=text1.length();
//创建BackgroundColorSpan对象,指定背景色为黄色
BackgroundColorSpan backgroundColorSpan=new
BackgroundColorSpan(Color.YELLOW);
//使用setSpan方法将指定字符串转换为BackgroundColorSpan对象
spannableString3.setSpan(backgroundColorSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv5.setText(spannableString3);
104.同时设置文字色和背景颜色
实现CharacterStyle,
public class ColorSpan extends CharacterStyle{
private int mTextColor;
private int mBackgrounColor;
public ColorSpan(int textColor,int backgroundColor){
mTextColor=textColor;
mBackgrounColor=backgroundColor;
}
//覆盖characterStyle类中的updateDrawState方法,并设置文字和背景颜色
@Override
public void updateDrawState(TextPaint tp) {
// TODO Auto-generated method stub
tp.bgColor=mBackgrounColor;
tp.setColor(mTextColor);
}
}
TextView tv7=(TextView) findViewById(R.id.tv7);
//定义要显示的字符串
String text2="<没有背景><黄色背景>\n\n<蓝色背景,红色文字>";
//设置黄色背景
SpannableString spannableString4=new SpannableString(text2);
int start1=6;
int end1=12;
BackgroundColorSpan backgroundColorSpan2=new
BackgroundColorSpan(Color.YELLOW);
spannableString4.setSpan(backgroundColorSpan2, start1,
end1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
//设置蓝色背景,红色文字
ColorSpan colorSpan=new ColorSpan(Color.RED,Color.BLUE);
// /将指定文本转换为ColorSpan对象
spannableString4.setSpan(colorSpan,
14,text2.length(),Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv7.setText(spannableString4);
105.在设计电子词典,当用户输入单词时,应显示以当前输入单词开头的单词列表.Android sdk那个组件可以实现这个功能?
这道题考查了AutoCompleteTextView组件的用户以及如何将数据库与该组件放在一起使用.当每次在autoCompleteTextView组件中输入新字符串时都需要查询数据库中与当前输入相匹配的记录,并更新Adapter对象
使用AutoCompleteTextView组件可以在文本输入框下方显示一个列表m,可用于显示当前输入字符开头的单词列表.获取以某些字符串开头的单词列表的代码应该放在textWatcherafterTextChanged方法中,在该方法中会不断更新单词列表.
public void afterTextChanged(Editable e){
//查询以当前输入的字符开头的单词
Cursor cursor=database.rawQuery("sql语句");
DictionaryAdapter adapter=new DictionaryAdapter(this,cursor,true);
autoCompleteTextView.setAdapter(dictionaryAdapter);
}
106.在按钮上显示图像的方式有哪些?
Android sdk支持在Button imageButton以及radioButton上显示图像
107.如何用代码动态改变button的大小和位置?
由于button是view的子类,因此可以使用button.layout方法动态改变button的大小和位置.layout方法有4个参数,分别表示button的左上角定点位置和右下角顶点位置.
108.如果想让一个显示图像的按钮在不同的状态显示不同的图像,应该这怎么做?
使用drawable资源可以很容易的实现按钮图像切换的功能.如果只是简单的切换图像状态(如按下,焦点,正常状态)可以使用状态资源,然后通过button按钮的android:background属性指定该状态资源文件的id即可.状态资源文件需要在drawable目录建立一个xml文件,并在select标签指定各种状态对应的状态图像
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- 按钮按下的状态 -->
<item
android:state_pressed="true"
android:drawable=""></item>
<!-- 按钮处于焦点的状态 -->
<item android:state_focused="true">
</item>
<!-- 正常状态 -->
<item android:drawable=""></item>
drawable目录不进可以存储普通的图像资源,还可以存储xml图像资源,图像状态资源就是其中之一.与图像状态资源类似的还有淡入淡出资源和图像基本资源.其中淡入淡出资源只允许在更多的图像定义级别,单需要使用代码进行控制.
淡入淡出
<transition xmlns:android="">
<item android:drawable="">
<item android:drawable="">
</transition>
图像级别资源文件
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/button" android:minLevel="6"
android:maxLevel="10"></item>
<item android:drawable="@drawable/st" android:minLevel="12"
android:maxLevel="20"></item>
</layer-list>
其中图像级别资源中的某一个item标签表示一个级别区间.级别区间用android:minLevel和android:maxLevel属性设置.setImageLevel或setLevel方法设置的级别的某个区间内(android:minLevel<=level<=android:maxLevel)系统就会先用那个区间对应的图像
imageView=(ImageView)findViewById(R.id.imageview_lamp);
//设置level为8
imageView.setImageLevel(8);
109.如何实现图像的半透明度?
可以采用2种实现图像半透明的方法
1.使用Paint.setAlpha方法设置图像的透明度.基本原理是先使用bitmap对象装载图像,然后在view.onDraw方法使用Canvas.drawBitmap方法将bitmap对象绘制在当前的view上
InputStream is=getResources().openRawResource(R.drawable.icon);
//装载图像
Bitmap bitmap = BitmapFactory.decodeStream(is);
proteted void onDraw(Canvas canvas){
Paint paint=new Paint();
paint.setAlpha(180);//0-255
//绘制半透明的图像
canvas.drawBitmap(bitmap,new Ret(0,0,bitmap.getWidth(),bitmap.getHeightr()),new Rect(0,0,bitmap.getWidth(),bitmap.getHeight()),paint);
}
2.可以在不透明的图像上覆盖一层半透明的膜(可以用半透明的imageview实现)
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<!-- 不透明的图像,将被半透明薄膜覆盖 -->
<ImageView
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:src="@drawable/icon"/>
<!-- 半透明的薄膜 -->
<ImageView
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:background="#EFFF"/>
</FrameLayout>
110.如何在imageview组件中显示图像的一部分?
在imageview中显示图像的一部分最直接的方法就是截取图像的一部分显示.当然,使用图像剪切资源也可以实现截取图像的效果
如果想任意截取图像,可以使用biemap.createBitmap方法在原图像的基础上截获某一部分,并创建这部分图像的bitmap对象
Bitmap bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.icon);
//截取(10,10,100,100)范围的图像
Bitmap createBitmap = Bitmap.createBitmap(bitmap,20,20,100,100);
//将截取后的图像显示在imageview组件中
ImageView iv1=(ImageView) findViewById(R.id.iv1);
iv1.setImageBitmap(createBitmap);
如果只想从图像的一端(上,下,左,右)截取图像,也可以使用图像剪切资源.这种资源需要在res/drawable目录中建立一个xml文件,并使用下面的代码从图像左侧开始截取图像,然后需要将图像剪切资源当中普通图像资源使用即可.
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/icon"
将android:clipOrientation设置为vertival,可以从上下方向截取图像
android:clipOrientation="horizontal"
android:gravity="left">
</clip>
只使用图像剪切资源还无法获得图像剪切效果,最后需要使用ClipDraw方法设置截取的百分百
ImageView iv=(ImageView) findViewById(R.id.iv1);
获取imageview的背景图
ClipDrawable drawable=(ClipDrawable)iv.getDrawable();
//从图像左侧截取图像30%
drawable.setLevel(300);
111.如何为图像加上边框?
首先做一个透明的带边框的nine-patch格式图像,如何通过<imageView>标签的android:background属性指定这个图像就可以为图像加上边框.
112.请描述如何使用Matrix对象旋转和缩放图像
使用Matrix.setTotate方法可以旋转图像
Bitmap bitmap=((BitmapDrawable)getResources()
.getDrawable(R.drawable.icon)).getBitmap();
Matrix matrix=new Matrix();
//顺时针旋转45度
matrix.setRotate(45);
//旋转图像,并为旋转后的图像创建新的bitmap对象
bitmap=Bitmap.createBitmap(bitmap,0,0,
bitmap.getWidth(),bitmap.getHeight(),matrix,true);
//在imageview组件中显示旋转后的图像
iv.setImageBitmap(bitmap);
使用Matrix.setScale(0.5f,0.5f)缩放图像
Bitmap bitmap=((BitmapDrawable)getResources()
.getDrawable(R.drawable.icon)).getBitmap();
Matrix matrix=new Matrix();
//图像等比例缩小50%
matrix.setScale((float)0.5,(float)0.5);
//旋转图像,并为旋转后的图像创建新的bitmap对象
bitmap=Bitmap.createBitmap(bitmap,0,0,
bitmap.getWidth(),bitmap.getHeight(),matrix,true);
iv2.setImageBitmap(bitmap);
113.ProgressBar的进度条颜色是否可以修改?如果可以修改,请写出具体的实现代码?
可以改变progressBar的进度条颜色.ProgressBar有三种颜色:背景颜色,第一级进度条颜色,第二季进度条颜色.可以使用图层列表(layer-list)资源修改这三种颜色.首先需要准备3个纯色的图像,然后在res/drawable目录中建立一个progressbar.xml文件,并输入下面的内容
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- 设置背景色图像资源 -->
<item android:id="@android:id/background"
android:drawable="@drawable/icon"></item>
<!-- 设置第二级进度条颜色图像资源 -->
<item android:id="@android:id/secondaryProgress"
android:drawable="@drawable/ic_launcher"></item>
<!-- 设置第一级进度条颜色图像资源 -->
<item android:id="@android:id/progress"
android:drawable="@drawable/sy"></item>
</layer-list>
最后在progressbar标签中使用android:progressDrawable属性指定progressbar.xml文件的资源id.
114.如何实现垂直进度条
Android SDK并没有提供垂直进度条组件,因此,我们可以自己绘制垂直进度条
垂直进度条绘制可以有很多种方法,最简单的方法是使用图像剪切资源.
115.将数据显示在listview组件可以使用baseAdapter的子类,请描述如何使用baseadapter的抽象方法
BaseAdapter有4个抽象方法:getItem,getItemId,getCount,getView,前2个方法分别用于返回object对象和long类型的值.不一定要在这2个方法中编写具体的代码.一般用这2个方法返回与当前列表项相关的对象和列表项的id
116.如何对gridview,listview等列表组件中的数据进行增删改查?
由于列表组件采用mvc模式,因此不能直接通过列表组件对数据进行操作,必须在修改数据后使用notifyDataSetInvalidated方法通知列表组件刷新数据.
首先对数据源的数据进行操作,然后调用baseadapter.notifyDataSetInvalidated方法通知列表组件更新数据.在调用该方法后,系统会调用当前列表的getview方法获取当前的列表项的view镀锡,这样更新当前列表.
117.在listview组件中显示数据库的数据应该如何做?
如果数据简单,可以用simpleCurorAdapter.如果复杂,可以编写一个继承自usorAdapter的类,并在newview方法中创建新的列表项view对象,在bingview方法中为相应的组件赋值.
118.如何改变listview列表项的背景色?
改变列表项选中状态的背景色可以在listview标签的android:listSelector属性,也可以使用listview.setSelector方法.
119.如果要做一个文件管理器,使用gridview组件显示文件列表,有的文件需要显示缩略图(如图像文件,视频文件,apk程序文件)
有很多没有经验的开发人员在.显示文件缩略图都是直接选择装载图像,这样做当然没有问题.但是当图像比较大时,在baseAdapter.getVIew方法中直接装载图像会用GridView组件列表上下滑动时出现卡顿的现象.最好的做法是使用任务队列中然后使用另外一个线程不断的扫描任务队列,并处理未完成的任务.当狐狸完 某个任务,可以刷新gridView组件来表示该图像文件的缩略图.如果列表中的数据来自网络,也可以使用这种方法装载数据.例如微博客户端显示微博列表时会异步从网络下载头像.
如果在BaseAdapter.getView方法中执行耗时澳洲,需要进行异步处理,否则会使队列出现卡顿的现象,可以使用数组或list对象建立任务队列和数据缓冲,getview方法中一旦遇到比较耗时的操作(如显示文件图像缩略图,从网络下载图像)需要将这些操作加入到任务队列中,然后在使用另外一个线程从任务队列取得相应任务,并执行当前的任务.最后需要调用BaseAdapter.notifyDataSetChanged方法刷新列表中的数据(会再次调用BaseAdapter。getviw方法)如果再次显示当前列表项,需要直接从数据缓冲中获取数据.线程可以通过不断你扫描任务队列的方法获取任务.
120.如何为listview组件加上快速滑块,是否可以修改快速滑动图像?
所谓的列表快速滑块就是当你快速滑动列表右侧会出现小方块,这就是列表的快速滑块,如果停止一秒,快速滑块就会消失.
使用布局文件需要将android:fastScrollEnabled属性设置为true,使用java代码需要调用listview.setFastScrollEnabled(true)方法
ListView组件并没有提供修改快速滑块图像的api,因此不能直接修改快速滑块图像,但是可以通过反射技术修改快速滑块图像.
ListView listView=(ListView) findViewById(R.id.lv);
listView.setFastScrollEnabled(true);
listView.setAdapter(new MyAdapter());
//FastScroller.mThumbDrawable变量保存了快速滑块图像,首先通过
//AbsListView.mFastScroller变了获取fastScroller对象
try {
Field field = AbsListView.class
.getDeclaredField("mFastScroller");
field.setAccessible(true);
Object obj=field.get(listView);
//获取fastScroller.mThumbDrawable变量的field对象
field = field.getType().getDeclaredField("mThumbDrawable");
field.setAccessible(true);
//获取fastScroller.mThumbDrawable变量的值
Drawable drawable=(Drawable)field.get(obj);
//装载新的快速滑块图像
drawable=getResources().getDrawable(R.drawable.sy);
//重新设置快速滑块的图像
field.set(obj, drawable);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
121.请尽可能的说出android sdk支持的容器组件
只有是viewGroup的子类
五大布局组件,GridView,Gallery,listView
122.如何使容器内的组件可以水平和垂直滑动?
将scrollView和HorizontalScrollView组件结合视图,就可以实现绘制和水平滑动的效果.所谓的结合就是在srollview组件里面使用HorizontalSrollView,或者在HorizontalScrollview使用scrollView标签
123.如何使Gallery循环显示图像?例如,通过一个数组(长度为10)保存图像文件路径,用gallery组件显示数组中的路径对应的图像.当gallery组件显示到第10个图像后,第11个图像显示第10个图像.
本题实际上是靠BaseAdapter.getview和getcount方法的应用技巧.原则上getcount方法返回小于等于数据源中的个数,但为了产生循环效果需要改变主人公规则.时BaseAdapter.getCount返回一个较大的值(Integer.Max_Value)当baseadapter.getview方法不能直接通过position参数获得的数据的位置,需要将position参数对10取余,并将余数作为新的数据位置
124.Android可以动态引用组件吗?如果可以,请尽可能的说出android支持哪些可动态引用的组件类型
引用组件分为静态和动态.静态引用就是将组件连同主程序一起封装在编译后的目标文件中,如vc的lib文件.动态引用就是指主程序和组件是分离的组件可以单独升级和卸载.
可以动态引用组件,android应用程序可以动态引用的组件类型包括未安装的apk文件,包含classes.dex文件的jar文件,JavaScript脚本,四大应用程序租金
125.请描述如何将可视化组件封装在jar文件中以及如何通过java代码适应不同的屏幕分辨率
jar文件可以封装很多类型的组件,如可视化组件(对androidsdk原生组件的扩展),四大组件.每种组件在使用时都有一些注意事项这在使用被封装在jar文件里面的组件一定要注意.可以直接将可视组件的lass文件放到jar文件中,不过组件使用的资源文件要放到主工程的res目录的相关子目录.在xml布局文件中使用组件要指定全名
虽然组件中可以引用R类中的资源,但是不建议这么做.因为这样做了在使用组件时主程序必须包含这些资源,使用和发布组件比较麻烦,也不灵活如果组件中确实要使用一些资源,最好提高一些属性,由使用者负责指定这些资源.
自定义可视组件还要考虑屏幕分辨率的问题.虽然不建议使用资源文件,也不能用dp或sp设置与分辨率无关的单位.因此需要使用下面的java代码将dp或sp转换为实际的像素点
DisplayMetrics displayMetrics=new DisplayMetrics();
displayMetrics.setToDefaults();
//根据像素分辨率将dp转换成像素点
Int pixel=(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dip,displayMetrics);
126.如果想编写一个自定义可视组件,你打算怎么做?
开发自定义可视组件一般可使用三种模式
1.扩展现有的组件.如组件类可以直接继承textview
2.组合多种组件。如组件类可以直接继承自容器可将多个组件添加到组件类中
3.直接从view继承.此类从0开始编写
127.Android支持的四大应用程序组件可以封装在jar文件中吗?使用时应该注意什么?
四大应用程序组件可以放在jar文件中,并在android工程中静态引用jar文件虽然四大应用程序组件相关的class文件都封装在jar文件,但是使用这些组件仍然要注册在清单文件中,否则无法使用这些组件.
128如何动态装载apk文件(未安装)中的类?
要注意的是本题要求动态装载未安装的apk文件.由于android程序运行在Dalivk虚拟机上,而不是传统的jvm上,因此android程序不能动态装载传统的jar文件,而apk文件已经编译成dalivk虚拟机格式因此可以被动态装载
动态装载未安装的apk文件中的类的java代码
//my.apk表示要动态装载的apk文件,my_temp.apk表示为了优化
//临时产生的apk文件(系统处理)
DexFile dexFile=dalvik.system.DexFile
.loadDex("/sdcard/my.apk","/sdard/my_temp.apk",0);
//装载apk文件中的类,并创造该类的对象实例
Object object=dexFile
.loadClass("mobile.android.file.explorer.width.Test",null).newInstance();
//使用java反射技术获取getname方法的method对象
Method method=object.getClass().getDeclaredMethod("getName",null);
//调用类中的方法,并获取方法返回值
String result=String.valueOf(method.invoke(object,null));
129.下面的代码是包含在mywidget.apk文件中的java接口和java类
package mobile.android.file.explorer.widget;
//java接口代码
public interface MyInterface {
String getName();
}
package mobile.android.file.explorer.widget;
//java类代码
public class MyClass implements MyInterface{
public String getName() {
// TODO Auto-generated method stub
return "我的名字是Jobs";
}使用下面的代码可以成功调用getname方法吗?为什么?
DexFile dexFile=dalvik.system.DexFile.loadDex("/sdcard/mywidget.apk",
"/sdcard/mywidget_temp.apk",0);
Object obj=dexFile.loadClass("mobile.android.file.explorer.widget.TestAPK",
null).newInstance();
Method method=obj.getClass().getDeclaredMethod("getName",null);
String result=String.valueOf(method.invoke(obj, null));
如果apk文件中的类实现了接口,或继承了其他的类,必须同时装载这些接口和类,否则无法成功创建该类的对象.不能成功调用getName方法.因为没有装载MyInterface接口,可按下面的代码调用getname方法
DexFile dexFile=dalvik.system.DexFile.loadDex("/sdcard/mywidget.apk",
"/sdcard/mywidget_temp.apk",0);
//装载接口
dexFile.loadClass("mobile.android.file.explorer.widget.MyInterface",
null);
Object obj=dexFile.loadClass("mobile.android.file.explorer.widget.TestAPK",
null).newInstance();
//object对象强转为MyInterfae
MyInterface interface1=(MyInterface)obj;
//使用强类型调用getname方法
String name=interface1.getName();
130.android应用程序是否可以动态引用jar文件?
该jar文件是属于哪类的jar.传统jar文件(包含.class)由于是基于jvm格式的,因此无法由android应用查询调用.不过jar文件中只要包含dalivk虚拟机格式的二进制代码就可以被android应用程序动态调用.apk文件中的classes.dex就是dalivk虚拟机格式的二进制文件.
jvm格式的jar文件不能被androi应用程序动态调用,但包含了classes.dex文件的jar文件可以被android应用程序动态调用.可以使用下面的命令将lasses.dex文件打包成jar文件.
jar cvf my.jar classes.dex
131.如何判断包含某个activity action的android应用程序是否安装?
将包含activity ation的应用程序作为组件使用时,首先需要判断该应用程序是否被安装.如果未被安装改应用程序,应先要求用户安装改应用程序.如何在调用应用程序的activity.
调用manager.queryIntentActivities方法可以查询系统中是否注册了某个activity ation,如果未返回任何结果,说明该系统没有安装包含指定activity ation的apk。
PackageManager manager=getPackageManager();
//指定要查找的activity action:com.android.phone.action.TOUCH_DIALER
Intent intent=new Intent("com.android.phone.action.TOUCH_DIALER");
//在系统中查询指定的activityu ation
List<ResolveInfo> infos=manager.
queryIntentActivities(intent, PackageManager.GET_INTENT_FILTERS);
//如果没有返回任何结果,表明系统中没有指定的activity action
if(infos.size()==0){
Log.d("Ativity Action", "activity action不存在");
}
不仅Activity可以作为组件使用,servie,Broadast reeiver和Content provider同样也可以作为组件使用.因此,除了activity外,其他三个应用程序组件也需要判断他们是否已经安装
BroadastReceiver
PackageManager manager=getPackageManager();
//指定要查找的boradcast action
Intent intent=new Intent("mobile.android.MYBROADCAST");
//在系统中查询指定的 broadcast action
List<ResolveInfo> infos=manager.
queryBroadcastReceivers(intent, PackageManager.GET_INTENT_FILTERS);
//如果没有返回任何结果,表明系统中没有指定的activity action
if(infos.size()==0){
Log.d("broadcast Action", "broadcasr action不存在");
}
service指的是aidl service,也就是一个允许android应用程序访问另外一个应用程序中的类,aidl servie在调用时需要使用bindservice方法进行绑定.如果aidl service不存在,则绑定失败,也就是说bingservice方法会返回false。因此通过bindservie方法可以判断指定的aidl servie是否存在
//返回true,表示绑定成功,否则返回失败
if(!bindService(new Intent("mobile.android.IMyservice"),
serviceConnection,Context.BIND_AUTO_CREATE)){
Log.d("aidl servie","不存在");
}
判断指定的Content provider是否存在只需要根据ContentResolver对象的相应方法的返回值进行判断即可.
//返回true,表示绑定成功,否则返回失败
if(!bindService(new Intent("mobile.android.IMyservice"),
serviceConnection,Context.BIND_AUTO_CREATE)){
Log.d("aidl servie","不存在");
}
132.在android应用程序中java与JavaScript如何交互?
在android应用程序中可以使Java代码和JavaScript脚本进行交互,所谓的交互就是互相调用以及传送数据.这项技术的核心就是webview组件,该组件不进可以执行javascript脚本,也允许在js脚本中执行java代码.由于android可动态执行,并且执行java代码,所在在JavaScript也常被当做android的动态组件使用.
WebView webView=new WebView(this);
WebSettings webSettings=webView.getSettings();
//必须执行下面的语句,否则webview无法执行js脚本
webSettings.setJavaScriptEnabled(true);
webView.setWebChromeClient(new WebChromeClient());
String s="";
//s为string类型变量,保存javascript脚本
webView.loadDataWithBaseURL(null,s,"text/html","utf-8",null);
//在java代码和js脚本之间传递数据以及使用js脚
//本执行java代码需要使用webview.addJavascriptInterfae方法添加
//在js中调用的java代码
webView.addJavascriptInterface(new Object(){
//可在js脚本中调用的java方法
public void move(int x,int y){
//java代码
}
},"demo");//demo为js中可访问的对象,通过该对象调用move
在js脚本中调用move方法
window.demo.move(20,100);
133.请描述ndk方法的命名规则,并描述ndk方法中前2个参数的作用
假设调用ndk方法的java类是mobile.android.HelloWorldJNI,在该类型中实际访问的本地方法名是process,返回值是String,没有参数m那么ndk方法的定义如下
jstring Java_mobile_android_HelloWroldJNI_proess(JNIEnv *env,jobjet obj){
}
NDK方法必须以java开头后面跟调用NDK方法的java全类名(package+lass)最后才是实际的方法名.各部分之间用下划线分隔.所有的你的看方法的前2个参数类型必须是JNIEnv*和jobjet.JNIEnv*表示当前ndk环境的对象指针,可以通过该参数访问ndk中的内置成员.jobject表示调用当前ndk方法的java对象,可以用该参数值访问调用当前ndk方法的java对象的成员.
134.如何用java代码让android market显示指定的程序以使用用户下载?
如果使用四大应用程序组件作为动态组件,当这些组件未安装时需要提示用户下载太慢.包含这些组件的apk程序被发布到android market上时可以用程序直接调用内置在手机上的android market程序进行下载.本题是考查我们是否了解如何用java代码访问android market.在android系统中很多内置的应用汇包含若干个activity action。因此,可以通过ativity ation直接调用其他应用程序的窗口,访问android market就采用了这样一种方式.
让android market直接显示我们所期望的程序以供用户下载可以通过应用程序名称或id进行查询
Uri uri=Uri.parse("market://searh:q=应用名称");
Intent intent=new Intent(Intent.ACTION_VIEW,uri);
startActivity(intent);
根据应用程序id(也就是应用程序的package name)查找应用程序的代码
//mobile.android.library为应用程序的package name
Uri uri=Uri.parse("market://details?id=mobile.android.library");
Intent intent=new Intent(Intent.ACTION_VIEW,uri);
startActivity(intent);
135.请写出安装apk程序的代码
Intent intent=new Intent(Intent.ACTION_VIEW);
//指定apk文件的路径
String filepath="/sdcard/FileExplorer.apk";
//指定文件类型
intent.setDataAndType(Uri.parse("file://"+filepath),
"application/vnd.android.package-archive");
//执行这条语句弹出安装界面
startActivity(intent);
136.如何配置Activity才能让程序启动时将该activity作为启动窗口?
Android系统在启动一个应用程序时会调用该应用程序中可接收的MAIN动作(一个系统的activity action)的activity,因此,只要在定义activity时指定MAIN动作就可以使该Ativity在应用程序时被调用.但要注意,如果androidManifest.xml文件中如果有多个可接收MAIN动作的activity,系统只会启动第一个可接收main动作的activity
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
定义MAIN动作
<action android:name="android.intent.action.MAIN" />
必须指定ategory,否则无法启动该activity
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
137.如何将Activity变成半透明的对话框
在定义activity时指定Theme.Dialog主题可以将Ativity设置成对话框风格.通过修改Theme.Dialog主题的android:windowsBackground属性值可以改变activity的背景图像.如果背景图像使用半透明的图像,则activity就会变成半透明的对话框.为了修改android:windowsBackground属性,可以定义一个新的主题,该主题继承自Theme.dialog
<style name="MyTheme" parent="@android:style/Theme.Dialog">
<item name="android:windowBackground">@drawable/ic_launcher</item>
</style>
然后在定义activiy时直接指定MyTheme即可
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/MyTheme"
138.如何设置activity显示和关闭时的动画效果
通过overridePendingTransition方法可以设置activity显示和关闭的动画效果.首先在res/anim目录建立相应的动画资源文件,然后使用下面的代码在显示和关闭activity时添加动画效果.
Intent intent=new Intent(this,MainActivity.class);
startActivity(intent);
//通过淡入淡出小郭显示和关闭activity
overridePendingTransition(R.anim.fade_in,R.anim.fade_out);
139.请描述Content provider url有哪几部分组件
Content provider url和http url类似.
有4部分:
1.content://相当于http url的http://
2.authority:相当于httpURL中的域名
3.路径(path)
4.参数(param)
假如有如下的ontent provider URL其中最后面的数字可以任意编号
content://mobile.android.mydata/product/20
其中authority是mobile.android.mydata,path是produt,param是20
请描述开发一个Content provider的步骤
开发ontent provider的步骤
1.编写一个类,继承contentProvider
2.实现contentProvider的所有抽象方法
3.定义content Provider的URl。URL的形式为content://android/path/param.一般情况下authority建议使用域名因为域名是唯一的不会重复
Android的标准对话框最多可以有几个按钮,并写出显示对话框按钮的方法
Android的标准对话框最多可以有3个按钮.AlertDialog类显示这3个按钮的方法是setButton、setButton2、setButton3.另外AlertDialog.Builder类也提供了另外3个更直观的显示按钮方法:setPositiveButton、setNeutralButton和setNegativeButton.AlertDialog和AlertDialog.Builder提供的3个显示按钮方法的调用顺序是可以任意的,但是无论调用顺序是什么,使用setPositiveButton方法设置的按钮总会排在左起第一位,使用setNeutralButton的方法设置总会排在第二位,使用setNegativeButton方法设置的按钮排在第三位.
如何响应android标准对应的按钮单击事件?
通过AlertDialog.Builder.setPositiveButton、setNeutralButton和setNegativeButton方法可以设置按钮单击事件监听对象.
请描述以下进度条对话框(ProgressDialog)的使用方法
进度条对话框通过ProgressDialog类实现,该类是AlertDialog的子类,但是与AlertDialog不同,我们可以直接使用new关键字创建ProgressDialog对象
ProgressDialog dialog=new ProgressDialog(this);
dialog.setIcon(android.R.drawable.progress_horizontal);
dialog.setTitle("正在处理数据...");
dialog.setMessage("请稍后");
//设置进度条对话框的风格
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
//设置进度条对话框的最大值
dialog.setMax(100);
//设置进度条的当前进度
dialog.setProgress(20);
dialog.setButton("暂停",new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
dialog.setButton2("取消",new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
dialog.show();
如果想将进度条样式改为圆环可以将setProgressStyle方法的参数值改为ProgressDialog.STYLE_SPINNER.但是要注意圆形进度条只是一个不断旋转的动画并没有实际的进度,一般会用在无法准确的获取进度条的情况下因此,setMax和setProgress方法对于圆形进度条没有任何意义.
默认情况下对话框都是屏幕中心显示,这个位置是否可以改变,如果可以改变,应该怎么做?
使用setGravity方法可以设置对话框的位置
AlertDialog alertDialog=new AlertDialog
.Builder(this).setMessage("在顶端显示对话框")
.setPositiveButton("确定",null).create();
Window window=alertDialog.getWindow();
//调用setGravity方法使对话狂在屏幕左上角
window.setGravity(Gravity.TOP| Gravity.LEFT);
alertDialog.show();
请描述一下在状态栏上显示notification(通知)的实现步骤,并写出相应的java代码.
1.通过getSysteSERVICE方法获取一个Notification对象
2.创建一个Notification对象.每一个Notification对应一个Notification对象.在这一步需要设置显示在屏幕上方状态栏的通知信息、通知消息前方的图像资源id和发出通知的时间,一般为当前时间
3.由于notification可以与应用程序脱离,也就是即使应用程序关闭了,notification任然会显示在状态栏.当应用程序再次启动后,又快又重新控制这些notification,如清楚或替换他们。因此需要创建一个pendingIntent对象。该对象由android系统负责维护,因此,在应用程序关闭,该对象不会被释放.
4.使用notification的setLatestEventinfo方法设置notification的详细信息.
5.使用notificationManager的notifi方法显示notification信息.在这一步需要指定标识notification的唯一id。这id必须相对于notification对象是唯一的,否则就会覆盖相同id的notification
//第一步
NotificationManager notificationManager=(NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
//第二步
Notification notification=new Notification(android.R.drawable.ic_delete,
"您有新消息了",System.currentTimeMillis());
//第三步
PendingIntent intent=PendingIntent.getActivity(this,0,getIntent(),0);
//第四步
notification.setLatestEventInfo(this, "天气预报","晴转多云",
intent);
//第五步
notificationManager.notify(R.drawable.ic_launcher,notification);
点击通知(notifiation)弹出activity
PendingIntent intent=PendingIntent.getActivity(this,0,new Intent(this,Main.class),0);
notification.setLatestEventInfo(this, "天气预报","晴转多云",
intent);
notificationManager.notify(R.drawable.ic_launcher,notification);
点击通知不仅仅可以发生activity,广播和服务也可以发送
android支持哪几种菜单
选项菜单,上下文菜单,子菜单
哪些android支持的菜单项可以显示图像
只有选项菜单项可以显示图像,上下文菜单和子菜单的菜单条可以显示图像,但菜单项不能显示图像
请描述如何为1个activity添加选项菜单
实现activity.onCreateOptionsMenu方法,并利用menu对象添加菜单
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
menu.add(1,1,1,"菜单项1");
menu.add(1,2,2,"菜单项2");
menu.add(1,3,3,"菜单项3");
return true;
}
添加上下文菜单
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
// TODO Auto-generated method stub
menu.add(1,1,1,"上下文菜单项1");
menu.add(1,2,2,"上下文菜单项2");
menu.add(1,3,3,"上下文菜单项3");
super.onCreateContextMenu(menu, v, menuInfo);
}然后使用registerforContentMenu方法将上下文菜单与可视组件绑定
Button button=(Button)findViewById(R.id.bt_id);
registerForContextMenu(button);长按button就会弹出在oncreateContentmenu方法中创建的上下文菜单
在单击菜单项时,除了使用java代码显示一个activity外,还可以用什么方法显示activity
本题考查了我们是否了解一个activity可以与菜单项关联,从而单击该菜单项会自动显示与其绑定的activity,但是要注意,如果设置了菜单项的单击事件,并且单击事件返回true,则与菜单项关联的activity将失效,
可以将一个activity与某个菜单项关联,在单机该的会自动显示activity
MenuItem add = menu.add(1,1,1,"上下文菜单项1");
add.setIntent(new Intent(this,MenuActivity.class));
响应菜单项目单击事件有哪些方法
有如下3个方法可以响应菜单项的单击事件
onOptionsItemSelected
onMenuItemSelected
add.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
// TODO Auto-generated method stub
return false;
}
});
既然有3个响应菜单单击事件的方法,就会产生一个问题:如果同时使用这三种方法,他们都会起作用吗?实际上当onMenuItemClick方法返回true时,另外2种方法就失效了。如果未设置菜单项的单击事件,而同时使用另外2种方法响应单击事件的方式,系统会根据在onMenuItemSelected方法调用父类activity类的onmenuitemselected方法的位置来决定先调用onoptionsitemselected方法还是先调用onmenuitemselected方法
android支持哪些文件存储技术?
使用sharedPreferecees保存key-value对类型的数据,流文件存储(使用openFileoutput和openFileinput方法或fileinputstream和fileoutputstream对象),xml半结构化存储,用json保存数组或对象,用数据库保存结构化数据,用第三方的面向对象数据库直接保存java对象.
sharedPreferences是否可以将数据文件保存在sd卡上?
SharedPreferences原则上只能保存在当前应用程序的私有的shared_prefs目录,不过不是绝对的。可以利用反射技术改变系统内定的文件保存路径
可以将数据文件保存在sd卡上,但由于sharedPreferences未提供改变文件保存路径的aoi,
sharedPreferenes文件可以保存图像数据吗?
原则上不能保存,但可以采用编码的方式将任何二进制数据换成字符串形式,从而可以将二进制数据保存在sharedPrefrecesces中.将二进制的数据转换成字符串的编码格式采用了Base64
如何通过PrefereneActivity类实现一个设置界面.
PreferenceActivity是activity的子类,可以方便的实现设置界面,preferenceActivity会通过一个xml配置文件来描述设置界面的设置项,并且系统会自动保存当前设置项的最后状态.通过一个xml配置文件来描述设置界面的设置项,并且系统会自动保存当前设置项的最后状态.preferenceActivity预定意了一些专用组件,可以实现常用的设置项目
CheckBoxPreference:对应checkboxPreference标签,单击该设置会创建一个checkbox组件
EdittextPreference
listPreference:listview
首先需要编写一个继承自preferenceActivity的子类,然后在xml目录建议一个用于描述设置界面的xml文件
preferene_setting.xml,并且在该文件中使用preferenceactivity预定义的组件对设置界面布局
请说出prefereneactivity保存数据文件的路径m文件的命名规则。默认的文件名是否可以更改
由于preferenceActivity内部使用了sharedpreferences对象保存数据,因此在默认情况下仍然会将数据保存在手机内存中的shared_prefs目录.默认文件名为packagename_preferences.xml.如果当前窗口属于net.blogjava.mobile包,则默认文件名为net.blogjava.moblie_preferences.xml.可以通过preferenceManager.setSharedPreferencesName方法修改默认的文件名
getPreferenceManager().setSharedPreferencesName("setting");
如何使用imageview组件装载sd卡中图像文件?
ImageView imageView=new ImageView(this);
imageView.setImageDrawable(Drawable.createFromPath("/sdcard/face.png"));
androidsdl支持读取xml吗?
只支持采用sax技术读取xml.
请描述sax引擎分析xml文档的过程
sax引擎需要处理如下5个分析点,也可称为分析事件
开始分析xml文件.该分析点表示sax引擎刚开始处理xml文件,还没有读取xml文件的内容.该分析点对应于
DefaultHandler.startDocument方法,可以在该方法做一些初始化的工作
开始处理每一个xml元素,也就是遇到<product>、<item>这样的起始标记.sax引擎每次扫描到新的xml元素的起始标记会触发这个分析事件,对应的事件方法是startElement。在该方法可以获得当前元素的名称、元素属性的相关信息.
处理完一个xml元素,也就是遇到</product>、</item>这样的结束标记。该分析点对应的事件方法是endElement。在该事件中可以获得当前处理完的元素的全部信息
处理完xml文件。如果sax引擎将整个xml文件的内容扫描完了,就到了这个分析点,该分析点对应的事件方法是endDocument。该事件方法可能不是必需的,如果最后还有一些收尾工作,如释放一些资源,可以在该方法完成.
读取字符串分析.这是最重要的环境.虽然读取了xml文件中的所有内容,但是没有保存这些内容.而这个分析点所对应的haracters事件方法的主要作用就是保存sax引擎读取的xml文件中的内容.更准确的是保存xml元素的文本,也就是product节点中的内容
描述json文档的格式
json是一种轻量型的数据存储和传输方式,可以使用自动重形式保存数组和对象属性值。数组使用中括号[]对象使用大括号
[{'name':'地球','satellite_count':'1','satellite_names':'moon'},
{'name':'火星','satellite_count':'2','satellite_names':'moon1'}
]
写出解析下面json格式文档的java代码,并将对象的属性值输出到logcat视图中
如何管理sqlite数据库
sqlite官方提供了一个命令行工具.在这个命令行工具中可以执行2种命令:sql命令和控制台命令.其实sql命令必须以;号为结尾,在控制台命令必须以实心点(.)开头,如.help.
为了更方便的管理,也可以使用第三方的可视化数据库管理工具,如sqliteExpertProfessional就是一种比较流行的基于windows平台的sqlite数据库管理工具。
sqllite数据库如何查询表table的第2条到第30条记录
sqlite和mysql一样,select语句也支持limit字句
select * from table limit 19,11
假设有一个table表,该表中有id和name字段,要在table表中插入一条id=1,name=nill的记录.如果id=1不存在,则正常插入.如果存在,则更新name字段的值
本题使用insert语句肯定不行,insert语句当遇到约束冲突后会抛异常.在sqlite提供了replace语句,可以使用replae来替换insert
replace into table(id,name) value(1,'bill');
如何将table表结构和数据复制到table2上
create table table2 as select * from table
写出创建视图的sql语句
create view if not exists view as select * from table1
请说出sqlite函数abs(X)函数的返回值有几种情况?
由于abs函数会尝试将当前字段值转换成整型,再取绝对值.因此只要当前字段值可以转换成数值型的值,abs函数就可以成功返回正确的结果.但是要考虑abs函数抛异常的情况
X为正值和0,abs(x)函数返回x本身
x为负值,abs(x)函数返回x的绝对值,也就是-x
x为null,返回null
x为字符串、blob等不能转换为数值的类型,abs(X)函数返回0,
如果x值超出64位整数值范围,abs(x)函数会抛出一个溢出错误
如何获取最近一次执行sql语句所影响的记录行数,并写出相应的sql语句.
changes函数的用法
insert into table values(1,'bill');
--返回insert语句影响的记录行数
select changes();
如何使用一条sql语句查询不为null的字段值
通过coalesce函数可以返回第一个不为null的字段值
select coalesce(name,id) as value from table
ifnull函数与coalesce函数的功能相同,只是ifnull函数只有2个参数,相当于有2个参数的coalesce函数
select ifnull(name,id)as value from table
请说出length(X)函数在以下几种情况返回怎样的值?
1.X是字符串 2.x是bolb类型的值 3.X为null 4.x为数值型
返回字符串中包含的字符数 返回二进制数据中包含的字节数
返回null length会将x作为字符串处理.例如length(123)的值就是3
请分别使用like字句和like函数查询table中name字段值包含null的记录
使用like函数的sql
select * from table where like('%bill%',name);
使用like子句的sql
select * from table1 where name like '%bill%'
请描述nullif(X,Y)函数的用法
当x和y不同时,nulluif返回x。如果x和y相同,nullif返回null
select nullif(20,30)
select nullif(20,20)
请描述substr函数的用法
substr函数用于截取字符串的子字符串.substr有substr(X,Y)和substr(X,Y,Z)两种形式.
其中x是原字符串,y是要截取的字符串的第一个字符在原字符串的位置,z表示要截取的子字符串的毒.如果不指定z,substr会截取y以后的所有字符串.如果y为正值,表示的起始位置从原字符串的左侧开始,如果是负值,表示的起始位置从原字符串的右侧开始.如果z为负值,会取z的绝对值
select substr('abcdefg',2):bcdefg
select substr('abcdefg',2,3)bcd
select substr('abdefg',-2):fg
select substr('abdefg',-4,2):de
如何知道当前字段属于什么类型?
select typeof(fieldl)from table1
sqlite支持哪几个日期和时间函数
date,time,datetime,julianday和strftime
如果当前日期是2012-11-01将年-1,月+1输出日期是2011-12-01
本题考查我们是否了解日期和时间函数经常遇到的调节器(Modifier)调节器可以在日期和时间上进行微调,可以通过调节器很容易的对年,月,日,时,分,秒进行加减操作
select data('2012-11-01','-1 years','+1 months');
使用date函数输出当前日期和当前时间
select date('now')
请描述一下SQLiteOpenHelper.onCreate和SqliteOpenHelper.onUpgrade在说明情况下执行?
sqliteopenHelper类实际上是一个数据库框架,主要用于操作数据库和升级数据库.其实oncreate和onUpgrade是该类的2个抽象方法,一般负责数据库的创建和升级
如果数据库文件不存在调用oncrete方法,在该方法中创建数据库表,视图等组件
如果数据库文件存在,调用onUpgrade方法,调用该方法,会更新数据库版本号
请解释一下什么是db40数据库
db40(database for ibjects)是一个嵌入式的开源面向对象数据库,可以使用在java和.net平台上.不同于其他对象持久化框架,db40是基于对象的数据库,操作的数据本身是对象.而对象持久化框架需要一个映射文件将关系型数据库与对象进行关系,这样不仅使用麻烦,而且也无法处理更复杂的问题
db40的特点
存储时不改变类特征,使之易于存储
与java,。net无缝绑定
自动数据绑定
使用简单,只需要一个jar或dll文件
一个数据库文件
直接通过对象实例查询
创建scoket对象至少要指定哪些信息?
创建Scoket对象至少需要知道ip(域名)和端口号
Socket socket=new Socket("www.microsoft.com",80);
请写出使用scoket连接服务器(ip:192.168.17.100,端口号:8080)以及与服务端交互的java代码
本题考查我们是否了解socket的用法。与服务器交互实际上就是从服务器读取数据以及向服务器写数据.
Socket socket=new Socket("192.168.17.100",8080);
OutputStream os=socket.getOutputStream();
OutputStreamWriter osw=new OutputStreamWriter(os);
BufferedWriter bw=new BufferedWriter(osw);
//向数据库写数据
bw.write("hello world\r\n\r\n");
bw.flush();
InputStream is=socket.getInputStream();
InputStreamReader isr=new InputStreamReader(is);
BufferedReader br=new BufferedReader(isr);
String s="";
//从服务器读数据
while((s=br.readLine())!=null){
Log.d("line", s);
}
os.close();
is.close();
socket.close();
除了直接调用Socket.close方法会使网络连接关闭,还会有其他情况可以是网络连接关闭
1.直接调用Socket.close
2.只要InputStream和OutputStream有一个关闭,则网络连接自动关闭
3.在程序退出时网络连接自动关闭
4.将Socket对象设为null或在Socket对象未被是否的情况下将新的socket对象覆盖,有dalivk虚拟机垃圾回收器回收为socket对象分配的内存空间时自动关闭网络连接
虽然这4种方法都可以达到同样的目的,但一个健壮的网络程序关闭最好使用第一种和第二种.这是因为第三四种一般不会马上关闭网络连接.如果是这样的话,对于某些应用程序,将会遗留大量无用的网络连接,这些网络连接会占用大量的系统资源.
判断socket是否关闭
Socket socket=new Socket("192.168.17.100",8080);
socket.isClosed();判断是否关闭
socket.isConnected();判断socket对象是否连接成功
其实isConnected方法判断的并不是当前socket对象连接状态,而是socket对象是否曾经成功连接过,也就是说要socket.isClosed()=false且socket.isConnected()=true,socket对象才处于连接状态
如何使用Soket.connet方法连接服务器
Socket socket=new Socket();
socket.connect(new InetSocketAddress("192.168.18.100",8080));
如何设置Socket连接的超时时间
通过socket.connect方法可以设置超时
Socket socket=new Socket();
socket.connect(new InetSocketAddress("192.168.18.100",8080),2000);
客户端Socket的超时是指客户端通过socket和服务器进行通信的过程中,由于网络延迟,网络阻塞等原因,造成服务器未及时响应客户端的一种现象.在一段时间后,客户端由于未收到服务器的响应而抛出一个超时错误,其中客户端所等待的时间就是超时时间.
对于客户端来说,只有2个地方涉及到超时:一个是在连接服务器时,另外一个是在连接服务器成功后,接收服务器发过来的数据.因此客户端超时也分为2种类型:连接超时和读取超时.
1.连接超时:只有通过Socket.connect方法才能指定连接超时的世界,由于使用该方法必须指定ip和端口,因此无效的端口和ip将会抛超时错误.
2.读取数据超时
Socket.setSoTimeout(5000);
使用socket成功连接服务器后,如何让获取服务器的ip和域名
Socket socket=new Socket("192.168.10.1",80);
//获取服务器的id
socket.getInetAddress().getHostAddress();
//获取服务器的域名
socket.getInetAddress().getHostName();
除了Socket.getInerAddress方法,Socket类还有很多的getter方法,通过这些getter方法可以获取各种信息
public SocketAddress getRemoteSoketAddress()
该方法是将getInetAddress和getPort合在一起,利用这个方法可以同时得到服务器的ip和端口号.但是这个方法返回了一个socketAddress对象,这个对象只能作为connect方法的参数用于连接服务器,而要想获得服务器的ip和端口号,必须将socketAddress转换为他的子类inetSocketAddress
Socket socket=new Socket("192.168.10.1",80);
((InetSocketAddress)socket.getRemoteSocketAddress()).getHostName();
((InetSocketAddress)socket.getRemoteSocketAddress()).getPort();
public InetAddress getLoalAddress():
这个方法返回了本机的inetAddress对象.通过这个方法可以得到本机的ip和机器名,当本机绑定了多个ip时,socket对象使用哪一个ip连接服务器,就返回哪个ip.如果本机使用adsl上网,并且通过socket对象连接到intenrnet上的某一个ip或域名商,则getLocaladdress将返还adsl连接临时绑定的ip
Socket socket=new Socket();
socket.connect(new InetSocketAddress("www.microsoft.com",80));
String hostAddress = socket.getLocalAddress().getHostAddress();
String hostName = socket.getLocalAddress().getHostName();
public int getLocalPort()
通过这个方法可以得到socket对象绑定的本机的一个端口号.如果未绑定端口号,则返回一个从1024到65535之间的随机数.因此使用这个方法可能每次得到的端口号不一样
如果在调用Socket.close方法时还有未发出的数据,这些数据将被丢失,为了尽量保证在调用Socket.close方法后将所有的数据都发往服务端,应该如何做?
当调用socket.close方法时会立即返回,所有未发送的数据将被丢失,为了避免这类事情发送,可以使用Socket选项设置关闭延迟时间,这样可以留出足够的时间用来发送数据
设置调用Socket.close方法30秒后关闭socket连接
socket.setSoLinger(true,30);
请写出创建服务端Socket的java代码
ServerSocket socket=new ServerSocket(1234);
如何设置服务端Socket的请求队列长度
ServerSocket socket=new ServerSocket(1234,100);
在编写服务端程序时,一般会通过多线程来同时处理多个客户端请求.也就是说,使用一个线程来接收客户端请求当接到一个请求后(一个socket对象),就会创建一个新的线程,将这个客户端请求交给这个新线程狐狸.而那个接收客户端请求的线程继续接收客户端请求.
请说出android支持哪些访问http资源的方法
一般可以使用http api直接访问http资源,但是也可以使用Socket发送http请求.
Android sdk支持2种直接访问http资源的方式:DefaultHttpClient和HttpUrlConection.这2种方式都封装了http请求.其中DefaultHttpClient通过httpget和httppost分别封装了get和post去.httpurlconnection通过url的构造方法指定hhtp资源地址,然后通过URL.openConnection方法获取httpURLConnection对象.
转载请注明地址。谢谢~~