Android面试简录——组件3

四大应用程序组件


Android中的窗口:Activity

  • 如何配置Activity才能让程序启动时将该Activity作为启动窗口?
    在AndroidManifest.xml文件中指定MAIN动作。
    <action android:name="android.intent.action.MAIN" />
  • 请阐述Activity有哪几个生命周期方法以及在Activity现实和销毁的过程中生命周期方法执行的顺序。
    protected void onCreate(Bundle savedInstanceState)
    protected void onStart()
    protected void onRestart()
    protected void onResume()
    protected void onPause()
    protected void onStop()
    protected void onDestroy()
    Activity显示:onCreate -> onStart ->onResume.
    Activity销毁:onPause -> onStop -> onDestroy.
    onStop时Activity重新获得焦点:onRestart -> onStart -> onResume.
  • 调用Activity都有哪几种方法?
    1.显式调用:直接指定Activity
    2.隐式调用:通过Activity Action来调用Activity
  • 在Activity之间如何传递数据?
    1.Intent对象:
    Intent.putExtra ~ 设置要传递的数据
    Intent.getXxxExtra ~ 获取传递的数据
    2.静态变量:public static
    3.剪切板:
    数据保存:
    Intent intent = new Intent(this, MyActivity.class);
    ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
    clipboard.setText("数据");
    startActivity(intent);
    获取数据:
    ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
    String text = clipboard.getText().toString();
    4.全局对象:继承自android.app.Application类
    package mobile.android.transmit.data;
    import android.app.application;
    public class MyApp extends Application {
    public String country;
    public Data data = new Data();
    }
    需要在AndroidManifest.xml中定义该类。
    获取:
    MyApp myApp = (MyApp) getApplicationContext();

【拓展】通过剪切板传递复杂数据
问题提出:高版本中支持剪切板保存Intent支持的类型,但是低版本中不支持。
解决办法:使用字符串传递任何二进制数据(包括可序列化对象、图像的等)。
1.将可序列化对象转换成Base64编码,然后保存到剪切板中:
Intent intent = new Intent(this, MyActivity3.class);
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
Data clipboardData = new Data();
clipboardData.id = 6666;
clipboardData.name = "通过Clipboard传递的数据";
ByteArrayOutputStream baos = new ByteArrayOutputStream();
String base64Str = "";
try {
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(clipboardData);
base64Str = Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT);
oos.close();
} catch (Exception e) {
}
clipboard.setText(base64Str);
startActivity(intent);
2.从剪切板中获取Base64编码格式的字符串,并进行解码,最后还原成Data对象。
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
String base64Str = clipboard.getText().toString();
byte[] buffer = Base64.decode(base64Str, Base64.DEFAULT);
ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
try {
ObjectInputStream ois = new ObjectInputStream(bais);
Data data = (Data) ois.redObject();
textView.setText(base64Str + "\n\ndata.id:" + data.id + "\ndata.name" + data.name);
} catch (Exception e) {
}

  • 请写出直接拨号、将电话号码传入拨号程序、调用拨号程序、调用系统浏览器浏览网页、调用系统程序查看联系人、显示系统设置界面和现实Wi-Fi设置界面的Java程序。
    拨号代码:
    Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:12345678"));
    startActivity(callIntent);
    将电话号码传入拨号程序:
    Intent dialIntent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:87654321"));
    startActivity(dialIntent);
    调用拨号程序:
    Intent touchDialerIntent = new Intent("com.android.phone.action.TOUCH_DIALER");
    startActivity(touchDialerIntent);
    调用系统浏览器网页:
    Intent webIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://nokiaguy.blogjava.net"));
    startActivity(webIntent);
    调用系统程序查看联系人:
    Intent contactListIntent = new Intent("com.android.contacts.action.LIST_CONTACTS");
    startActivity(contactListIntent);
    显示系统设置页面:
    Intent settingIntent = new Intent("android.settings.SETTINGS");
    startActivity(settingIntent);
    显示Wi-Fi设置界面:
    Intent wifiSettingsIntent = new Intent("android.settings.WIFI_SETTINGS");
    startActivity(wifiSettingsIntent);
  • 如何将Activity变成半透明的对话框?
    对话框:Theme.Dialog
    半透明:android:windowBackground
    1.定义一个新的主题:
    <style name="MyTheme" parent="@android:style/Theme.Dialog">
    <item name="android:windowBackground">@drawable/msg_background</item>
    </style>
    2.指定主题
    <activity android:name=".Main" android:label="@string/appname" android:theme="@style/MyTheme">
  • 如何设置Activity显示和关闭时的动画效果?
    overridePendingTransition方法
    1.在res/anim中建立对应的动画资源文件
    2.在代码中添加动画效果:
    Intent intent = new Intent(this, AnimationActivity.class);
    startActivity(intent);
    overridePendingTransition(R.anim.fade_in, R.anim.fade_out);

广播接收器:Broadcast Receiver

  • 如何接收广播?
    接收单个广播:
    1.编写广播接收类。从BroadcastReceiver或其子类继承。
    2.在BroadcastReceiver.onReceive(Context context, Intent intent)方法中编写处理广播的代码。
    *在AndroidManifest.xml文件中注册。
    接收多个广播:
    使用intent.getAction判断当前接收到的是哪个广播。
    if ("action1".equals(intent.getAction())) {
    ...
    }
    if ("action2".equals(intent.getAction())) {
    ...
    }
  • 如何获取短信内容?
    1.编写广播接收器
    onReceive方法如下:
    public void onReceive(Context context, Intent intent) {
    Bundle bundle = new intent.getExtras();
    if (bundle != null) {
    Object[] objArray = (Object[]) bundle.get("pdus");
    SmsMessage[] messages = new SmsMessage[objArray.length];
    for (int i = 0; i < objArray.length; i ++) {
    messages[i] = SmsMessage.createFromPdu((byte[]) objArray[i]);
    String s = "手机号:" + messages[i].getOriginationAddress() + "\n";
    s += "短信内容:" = messages[i].getDisplayMessageBody();
    Toast.makeText(context, s, Toast.LENGTH_LONG).show();
    }
    }
    }
    2.在AndroidManifest.xml文件中定义该广播接收器时添加短信广播Action。
    <action android:name="android.provider.Telephony.SMS_RECEIVED" />
  • 如何拦截来电,并在检测到某些特定号码时自动挂断电话?
    编写一个广播接收类来拦截来电。
    通过反射技术访问Android SDK的内部功能来挂断电话。
    拦截来电的onReceive方法:
    public void onReceive(final Context context, Intent intent) {
    TelephonyManager tm = (TelephonyManager) context.getSystemService(Service.TELEPHONY_SERVICE);
    switch (tm.getCallState()) {
    case TelephonyManager.CALL_STATE_RINGING:
    String incomingNumber = intent.getStringExtra("incoming_number");
    if ("12345678".equals(incomingNumber)) {
    Class<TelephonyManager> telephonyManagerClass = TelephonyManager.class;
    Method telephonyMethod = telephonyManagerClass.getDeclaredMethod("getITelephony", (Class[]) null);
    telephonyMethod.setAccessible(true);
    Object obj = telephonyMethod.invoke(tm, (Object[], null));
    Method endCallMethod = obj.getCLass().getMethod("endCall", null);
    endCallMethod.setAccessible(true);
    endCallMethod.invoke(obj, null);
    }
    break;
    case TelephonyManager.CALL_STATE_OFFHOOK:
    Log.d("call_state", "offhook");
    break;
    case TelephonyManager.CALL_STATE_IDLE:
    closeToast();
    }
    }
    在AndroidManifest.xml文件中设置定义广播接收器:
    <action android:name="android.intent.action.PHONE_STATE"/>
  • 如何拦截手机屏幕休眠和唤醒动作?
    [注意] 该功能的广播接收器只能通过Java代码注册,不能在AndroidManifest.xml文件中注册。
    通过如下两个Broadcast Action可以拦截屏幕休眠和唤醒动作:
    休眠状态:Intent.ACTION_SCREEN_ON
    唤醒状态:Intent.ACTION_SCREEN_OFF
    注册广播接收器(ScreenOnOffReceiver)的代码如下:
    ScreenOnOffReceiver screenOnOffReceiver = new ScreenOnOffReceiver();
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(Intent.ACTION_SCREEN_ON);
    intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
    registerReceiver(screenOnOffReceiver, intentFilter);
  • 如何让一个Acitivity在开机后自动显示?
    使用广播接收器(StarupReceiver)拦截手机启动广播,然后在onReceive方法中打开Activity。
    public void onReceive(Context context, Intent intent) {
    Intent mainIntent = new Intent(context, Main.class);
    mainIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(mainIntent);
    }
    注册:
    <action android:name="android.intent.action.BOOT_COMPLETED"/>
    * 如何发送广播?
    sendBroadcast:
    public void sendBroadcast(Intent intent);

服务:Service

  • 请描述一下Service的生命周期。
    3个生命周期。
    public void onCreate(); //创建服务
    public void onStart(Intent intent, int startId); //开始服务
    public void onDestroy(); //销毁服务
    首次创建:onCreate() -> onStart().
    再次调用startService/使用startService开始一个已经停止的服务:onStart().
    调用stopService:onDestroy().
  • 请描述一下开发AIDL服务的步骤。
    AIDL:允许一个应用程序访问另一个应用程序的对象。
    建立AIDL服务的步骤:
    1.建立aidl文件(Android工程的Java源文件目录)
    2.如果aidl文件内容正确 -> 自动生成Java接口文件(*.java)
    3.建立一个服务类
    4.实现aidl文件生成的java接口
    5.在AndroidManifest.xml文件中配置AIDL服务。[注意]<action>标签中android:name的属性值就是客户端要引用该服务的ID,也就是Intent类构造方法的参数值。
  • AIDL服务支持哪些类型的数据?
    1.Java的简单类型(int,char,boolean等)
    2.String和CharSequence
    3.List和Map
    4.AIDL自动生成的接口类型
    5.实现android.os.Parcelable接口的类

内容提供者:Content Provider

  • 如何读取联系人信息?
    ListView listView = (ListView) findViewById(R.id.listView);
    Cursor cursor = getContentResolver().query(
    ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
    SimpleCursorAdapter simpleCursorAdapter = new SimpleCursorAdapter(
    this, android.R.layout.simple_list_item_1, cursor,
    new String[] {ContactsContract.Contacts.DISPLAY_NAME},
    new int[] {android.R.id.text1});
    listView.setAdapter(simpleCursorAdapter);

  • 如何查询收发的短信信息,以及只查收件箱和发件箱?
    ListView lvShortMessages = (ListView) findViewById(R.id.lvShortMessages);
    Cursor cursor = getContentResolver().query(
    Uri.parse("content://sms"), null, "address like ?",
    new String[] {"1%"}, null);
    SMSAdapter smsAdapter = new SMSAdapter(this, cursor);
    lvShortMessages.setAdapter(smsAdapter);
    只查收件箱:"content://sms" -> "content://sms/inbox"
    只查发件箱:"content://sms" -> "content://sms/outbox"

  • 请描述Content Provider URI有哪几部分组件?
    四部分:
    1.content:// ~ 相当于HTTP URI的http://
    2.authority ~ 相当于HTTP URI的域名
    3.路径(path)
    4.参数(param)
    举例:content://mobile.android.mydata/product/20
    分析:authority:mobile.android.mydata
    path:product
    param:20

  • 开发一个Content Provider的步骤。
    1.编写一个类,继承自ContentProvider
    2.实现ContentProvider中所有的抽象方法
    3.定义Content Provider的URI
    4.在static块中使用UriMatcher对象映射Uri和返回码
    static {
    uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    uriMatcher.addURI(AUTHORITY, "cities", 1);
    uriMatcher.addURI(AUTHORITY, "code/#", 2);
    uriMatcher.addURI(AUTHORITY, "cities_in_province/*", 3);
    }
    5.根须实际的需要实现相应的方法
    6.实现query,insert,delete,update方法时要使用UriMatcher.match方法将URI映射成第4步与URI对应的代码(addURI方法的最后一个参数值)
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    Cursor cursor = null;
    switch (uriMatcher.match(uri)) {
    case 1:
    ...
    break;
    case 2:
    ...
    break;
    default:
    throw new IllegalArgumentException("<" + uri + ">格式不正确");
    }
    return cursor;
    }
    7.在AndroidManifest.xml文件中使用<provider>标签注册Content Provider。
    <provider android:name="RegionContentProvider"
    android:authorities="mobile.android.mydata" />

  • 如何为Content Provider添加访问权限?
    在AndroidManifest.xml文件中的<provider>设置相应的权限,并定义这个权限。
    只读:readPermission
    只写:wirtePermission
    读写:permission
    1.设置权限:
    <provider
    android:name="RegionContentProvider"
    android:authorities="mobile.android.ch11.permission.regioncontentprovider"

        android:readPermission="mobile.android.ch11.permission.regioncontentprovider.READ_REGION" />
    2.定义权限:
    <permission
        android:name="mobile.android.ch11.permission.regioncontentprovider.READ_REGION"
        android:protectionLevel="normal"
        android:label="@string/label"
        android:description="@string/description"
        />
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容