四大應用程序組件
Android中的窗口:Activity
- 如何配置Activity才能讓程序啟動時將該Activity作為啟動窗口揖曾?
在AndroidManifest.xml文件中指定MAIN動作赡盘。
<action android:name="android.intent.action.MAIN" /> - 請闡述Activity有哪幾個生命周期方法以及在Activity現(xiàn)實和銷毀的過程中生命周期方法執(zhí)行的順序扯旷。
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. - 調(diào)用Activity都有哪幾種方法奕塑?
1.顯式調(diào)用:直接指定Activity
2.隱式調(diào)用:通過Activity Action來調(diào)用Activity - 在Activity之間如何傳遞數(shù)據(jù)丰歌?
1.Intent對象:
Intent.putExtra ~ 設置要傳遞的數(shù)據(jù)
Intent.getXxxExtra ~ 獲取傳遞的數(shù)據(jù)
2.靜態(tài)變量:public static
3.剪切板:
數(shù)據(jù)保存:
Intent intent = new Intent(this, MyActivity.class);
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText("數(shù)據(jù)");
startActivity(intent);
獲取數(shù)據(jù):
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();
【拓展】通過剪切板傳遞復雜數(shù)據(jù)
問題提出:高版本中支持剪切板保存Intent支持的類型锡宋,但是低版本中不支持儡湾。
解決辦法:使用字符串傳遞任何二進制數(shù)據(jù)(包括可序列化對象、圖像的等)执俩。
1.將可序列化對象轉(zhuǎn)換成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傳遞的數(shù)據(jù)";
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) {
}
- 請寫出直接撥號、將電話號碼傳入撥號程序衡奥、調(diào)用撥號程序爹袁、調(diào)用系統(tǒng)瀏覽器瀏覽網(wǎng)頁、調(diào)用系統(tǒng)程序查看聯(lián)系人矮固、顯示系統(tǒng)設置界面和現(xiàn)實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);
調(diào)用撥號程序:
Intent touchDialerIntent = new Intent("com.android.phone.action.TOUCH_DIALER");
startActivity(touchDialerIntent);
調(diào)用系統(tǒng)瀏覽器網(wǎng)頁:
Intent webIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://nokiaguy.blogjava.net"));
startActivity(webIntent);
調(diào)用系統(tǒng)程序查看聯(lián)系人:
Intent contactListIntent = new Intent("com.android.contacts.action.LIST_CONTACTS");
startActivity(contactListIntent);
顯示系統(tǒng)設置頁面:
Intent settingIntent = new Intent("android.settings.SETTINGS");
startActivity(settingIntent);
顯示W(wǎng)i-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())) {
...
} - 如何獲取短信內(nèi)容替裆?
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 += "短信內(nèi)容:" = 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的內(nèi)部功能來掛斷電話惠赫。
攔截來電的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可以攔截屏幕休眠和喚醒動作:
休眠狀態(tài):Intent.ACTION_SCREEN_ON
喚醒狀態(tài):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"/>
* 如何發(fā)送廣播怠缸?
sendBroadcast:
public void sendBroadcast(Intent intent);
服務:Service
- 請描述一下Service的生命周期。
3個生命周期钳宪。
public void onCreate(); //創(chuàng)建服務
public void onStart(Intent intent, int startId); //開始服務
public void onDestroy(); //銷毀服務
首次創(chuàng)建:onCreate() -> onStart().
再次調(diào)用startService/使用startService開始一個已經(jīng)停止的服務:onStart().
調(diào)用stopService:onDestroy(). - 請描述一下開發(fā)AIDL服務的步驟揭北。
AIDL:允許一個應用程序訪問另一個應用程序的對象。
建立AIDL服務的步驟:
1.建立aidl文件(Android工程的Java源文件目錄)
2.如果aidl文件內(nèi)容正確 -> 自動生成Java接口文件(*.java)
3.建立一個服務類
4.實現(xiàn)aidl文件生成的java接口
5.在AndroidManifest.xml文件中配置AIDL服務吏颖。[注意]<action>標簽中android:name的屬性值就是客戶端要引用該服務的ID搔体,也就是Intent類構造方法的參數(shù)值。 - AIDL服務支持哪些類型的數(shù)據(jù)半醉?
1.Java的簡單類型(int疚俱,char,boolean等)
2.String和CharSequence
3.List和Map
4.AIDL自動生成的接口類型
5.實現(xiàn)android.os.Parcelable接口的類
內(nèi)容提供者:Content Provider
如何讀取聯(lián)系人信息缩多?
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);如何查詢收發(fā)的短信信息呆奕,以及只查收件箱和發(fā)件箱?
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"
只查發(fā)件箱:"content://sms" -> "content://sms/outbox"請描述Content Provider URI有哪幾部分組件衬吆?
四部分:
1.content:// ~ 相當于HTTP URI的http://
2.authority ~ 相當于HTTP URI的域名
3.路徑(path)
4.參數(shù)(param)
舉例:content://mobile.android.mydata/product/20
分析:authority:mobile.android.mydata
path:product
param:20開發(fā)一個Content Provider的步驟梁钾。
1.編寫一個類,繼承自ContentProvider
2.實現(xiàn)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.根須實際的需要實現(xiàn)相應的方法
6.實現(xiàn)query,insert,delete,update方法時要使用UriMatcher.match方法將URI映射成第4步與URI對應的代碼(addURI方法的最后一個參數(shù)值)
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" />