前言
臨近考試蝶缀,根據(jù)老師發(fā)的考試說明和例題整理出如下的復(fù)習(xí)資料
安卓的平臺(tái)架構(gòu)
由下至上分別是:
- linux內(nèi)核
- 庫(kù)
- Android運(yùn)行時(shí)
- 應(yīng)用程序框架
- 應(yīng)用程序
下面簡(jiǎn)述每層的作用:
linux內(nèi)核
Android 平臺(tái)的基礎(chǔ)是 Linux 內(nèi)核大审。例如,Android Runtime (ART) 依靠 Linux 內(nèi)核來執(zhí)行底層功能,例如線程和低層內(nèi)存管理。
使用 Linux 內(nèi)核可讓 Android 利用主要安全功能,并且允許設(shè)備制造商為著名的內(nèi)核開發(fā)硬件驅(qū)動(dòng)程序。
Android運(yùn)行時(shí)
Android 包括了一個(gè)核心庫(kù)舱呻,該核心庫(kù)提供了JAVA編程語(yǔ)言核心庫(kù)的大多數(shù)功能。
程序庫(kù)
Android包含一些C/C++庫(kù)悠汽,這些庫(kù)能被Android系統(tǒng)中不同的組件使用箱吕。它們通過Android應(yīng)用程序框架為開發(fā)者提供服務(wù)。
應(yīng)用程序框架
Android系統(tǒng)提供給應(yīng)用開發(fā)者的本身就是一個(gè)框架柿冲,所有的應(yīng)用開發(fā)都必須遵守這個(gè)框架的原則茬高。
應(yīng)用程序
所有的應(yīng)用程序都是使用JAVA語(yǔ)言編寫的,每一個(gè)應(yīng)用程序由一個(gè)或者多個(gè)活動(dòng)組成假抄,活動(dòng)必須以Activity類為超類怎栽,活動(dòng)類似于操作系統(tǒng)上的進(jìn)程,但是活動(dòng)比操作系統(tǒng)的進(jìn)程要更為靈活宿饱,與進(jìn)程類似的是熏瞄,活動(dòng)在多種狀態(tài)之間進(jìn)行切換。
安卓的四大組件
- 活動(dòng)----Activity
他是一種可以包含用戶界面的組件谬以,主要用于和用戶進(jìn)行交互
- 服務(wù)----Service
Service是在一段不定的時(shí)間運(yùn)行在后臺(tái)强饮,不和用戶交互應(yīng)用組件。
- 廣播----Broadcast Receiver
- 內(nèi)容提供者----Content Provider
用于在不同的應(yīng)用程序之間實(shí)現(xiàn)數(shù)據(jù)共享的功能为黎。提供了一套完整的機(jī)制邮丰,允許一個(gè)程序訪問倆一個(gè)程序中的數(shù)據(jù),同時(shí)還能保證被訪問數(shù)據(jù)的安全性
安卓清單文件的作用
- 它為應(yīng)用指定Java包铭乾。此包名稱唯一標(biāo)識(shí)應(yīng)用
- 它描述了應(yīng)用的不同組件剪廉。它指定了實(shí)現(xiàn)這些組件并公布它們的功能。這些聲明幫助Android系統(tǒng)識(shí)別和組件及它們可以啟動(dòng)的條件炕檩。
- 它指定應(yīng)用訪問API的受保護(hù)部分和其他應(yīng)用交換所需的權(quán)限斗蒋。
- 它指定應(yīng)用可在其上運(yùn)行的API的最低級(jí)別
- 它指定鏈接應(yīng)用所必須依據(jù)的庫(kù)
常用的布局和控件以及其使用方法
四種最基本的布局
總共有四種最基本的布局,分別是:
線性布局(LinearLayout)
相對(duì)布局(RelativeLayout)
幀布局(FrameLayout)
百分比布局
因?yàn)榭荚囌f明里面只有兩種,所以接下來只介紹兩種
LinearLayout(線性布局)
- 指定各個(gè)節(jié)點(diǎn)的排列方向
android:orientation="horizontal"
- 設(shè)置右對(duì)齊
android:layout_gravity="right"
- 當(dāng)豎直布局時(shí)笛质,只能左右對(duì)齊和水平居中吹泡,頂部底部對(duì)齊豎直居中無(wú)效
- 當(dāng)水平布局時(shí),只能頂部底部對(duì)齊和豎直居中
- 使用match_parent時(shí)注意不要把其他組件頂出去
- 線性布局非常重要的一個(gè)屬性:權(quán)重
android:layout_weight="1"
權(quán)重設(shè)置的是按比例分配剩余的空間
RelativeLayout
- 組件默認(rèn)左對(duì)齊经瓷、頂部對(duì)齊
- 設(shè)置組件在指定組件的右邊
android:layout_toRightOf="@id/tv1"
- 設(shè)置在指定組件的下邊
android:layout_below="@id/tv1"
- 設(shè)置右對(duì)齊父元素
android:layout_alignParentRight="true"
- 設(shè)置與指定組件右對(duì)齊
android:layout_alignRight="@id/tv1"
常用的控件
TextView、EditText洞难、Button舆吮、ImageButton、ToggleButton、RadioButton色冀、RadioGroup潭袱、Checkbox、Spinner锋恬、ListView屯换、ImageView、WebView与学、ScrollView
重要的屬性有:
android:id:指明控件id
android:layout_width::指明控件的寬度
android:layout_height:指明控件的高度
相關(guān)控件及其使用方法可以參考
Android筆記---常用控件以及用法
創(chuàng)建一個(gè)活動(dòng)(Activity)的步驟
- 創(chuàng)建活動(dòng)彤悔,編寫自己的Acivity類,繼承Activity類
- 將UI與活動(dòng)關(guān)聯(lián)索守。調(diào)用setContentView方法
- 在清單文件中注冊(cè)活動(dòng)
活動(dòng)(Activity)的生命周期
活動(dòng)的狀態(tài)
- 運(yùn)行狀態(tài)
當(dāng)一個(gè)活動(dòng)處于返回棧的棧頂晕窑,也就是在屏幕的前臺(tái)顯示時(shí),稱為運(yùn)行狀態(tài)
- 暫停狀態(tài)
如果一個(gè)Activity失去焦點(diǎn)(不在棧頂)卵佛,但是依然可見(一個(gè)新的非全屏的Activity杨赤,例如一個(gè)對(duì)話框形式的活動(dòng),或者一個(gè)透明的Activity 被放置在棧頂)截汪,叫做暫停狀態(tài)(Paused)
- 停止?fàn)顟B(tài)
如果一個(gè)Activity被另外的Activity完全覆蓋掉(不在棧頂且不可見)疾牲,叫做停止?fàn)顟B(tài)(Stopped)
- 銷毀狀態(tài)(了解)
當(dāng)一個(gè)活動(dòng)從返回棧移除之后就變成的銷毀狀態(tài)
活動(dòng)的7個(gè)生命周期的方法
活動(dòng)的生命周期的圖
Intent的使用
- 顯式Intent
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
startActivity(intent);
上述代碼的作用是打開活動(dòng)SecondActivity
- 隱式Intent
相比隱式Intent,隱式Intent并不明確指出想要啟動(dòng)哪一個(gè)活動(dòng)衙解,而是指定了一系列抽象的action和category等信息阳柔,然后交由系統(tǒng)去分析這個(gè)Intent,并找到合適的活動(dòng)去啟動(dòng)
使用隱式Intent
首先打開AndroidManifest.xml丢郊,添加代碼:
<activity android:name=".Main2Activity">
<intent-filter>
<action android:name="com.lyy.intent.ACTION_START" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
指定好當(dāng)前活動(dòng)可以相應(yīng)的action和category
回到MainActivity.java中
Intent intent=new Intent("com.lyy.intent.ACTION_START");
startActivity(intent);
將Intent傳入我們自定義的action字符串即可
-
Intent的系統(tǒng)action
利用Intent傳值的兩種方式
利用Intent直接傳值
MainActivity.java —— 負(fù)責(zé)傳遞數(shù)據(jù)
Intent intent1=new Intent(MainActivity.this,Main2Activity.class);
intent1.putExtra("extra","hello");
startActivity(intent1);
Main2Activity —— 負(fù)責(zé)接收數(shù)據(jù)
Intent intent = getIntent();
String data = intent.getStringExtra("extra");
Log.d(TAG, "onCreate: " + data);
利用Bundle和Intent傳值
MainActivity.java —— 負(fù)責(zé)傳遞數(shù)據(jù)
Intent intent2 = new Intent(MainActivity.this, Main2Activity.class);
Bundle bundle = new Bundle();
bundle.putString("name", "lyy");
bundle.putInt("age", 18);
bundle.putString("address", "China");
intent2.putExtras(bundle);
startActivity(intent2);
Main2Activity —— 負(fù)責(zé)接收數(shù)據(jù)
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
String nameString = bundle.getString("name");
int age = bundle.getInt("age");
String addressString = bundle.getString("address");
原生方法操作SQLite數(shù)據(jù)庫(kù)
創(chuàng)建一個(gè)類用于繼承SQLiteOpenHelper類盔沫,并重寫兩個(gè)方法onCreate()和onUpgrade()方法用于創(chuàng)建和升級(jí)數(shù)據(jù)庫(kù),代碼示例如下:
public class MyDatabaseHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK = "create table Book(" +
"id integer primary key autoincrement," +
"author text," +
"price real," +
"pages integer," +
"name text)";
public static final String CREATE_CATEGORY = "create table Category(" +
"id integer primary key autoincrement," +
"category_name text," +
"category_code integer)";
private Context mContext;
public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
db.execSQL(CREATE_CATEGORY);
Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table if exists Book");
db.execSQL("drop table if exists Category");
onCreate(db);
}
}
對(duì)數(shù)據(jù)庫(kù)的數(shù)據(jù)進(jìn)行增刪改查(CRUD)操作
添加數(shù)據(jù)
先實(shí)例化之前創(chuàng)建的DatabaseHelper對(duì)象枫匾,并調(diào)用其getWritableDatabase()方法架诞,設(shè)置該數(shù)據(jù)庫(kù)可寫
SQLiteDatabase db = databaseHelper.getWritableDatabase();
隨后創(chuàng)建ContentValues對(duì)象,用來添加數(shù)據(jù)
ContentValues values = new ContentValues();
//開始組裝第一組數(shù)據(jù)
values.put("name", "The Da Vinci Code");
values.put("author", "Dan Brown");
values.put("pages", 454);
values.put("price", 16.96);
最后執(zhí)行db數(shù)據(jù)庫(kù)的insert()方法
db.insert("Book", null, values);//插入第一條數(shù)據(jù)
更新數(shù)據(jù)
創(chuàng)建ContentValues對(duì)象干茉,并組裝要更新的數(shù)據(jù)
ContentValues values1 = new ContentValues();
values1.put("price", 10.99);
調(diào)用update()方法
db.update("Book", values1, "name = ?", new String[]{"The Da Vinci Code"});
第一個(gè)參數(shù)指定表名谴忧,第二個(gè)指定要更新的數(shù)據(jù),第三個(gè)指定要更新的行角虫,如果沒有沾谓,則默認(rèn)更新所有行。
刪除數(shù)據(jù)
直接調(diào)用delete方法即可
db.delete("Book", "pages > ?", new String[]{"500"});
查詢數(shù)據(jù)(最復(fù)雜)
通過調(diào)用db的query()方法戳鹅,獲得一個(gè)cursor對(duì)象
//查詢Book表中的所有數(shù)據(jù)
Cursor cursor = db.query("Book", null, null, null, null, null, null);
在這里需要傳入7個(gè)參數(shù)均驶,作用分別如下:
然后在對(duì)cursor對(duì)象進(jìn)行遍歷,獲得查詢到的值
while (cursor.moveToFirst()) {
String name = cursor.getString(cursor.getColumnIndex("name"));
String author = cursor.getString(cursor.getColumnIndex("author"));
int pages = cursor.getInt(cursor.getColumnIndex("pages"));
}
最后枫虏,一定記得要回收cursor對(duì)象
cursor.close();
文件存儲(chǔ)
寫文件
public void save() {
String data = "Data to save";
try {
FileOutputStream fos = openFileOutput("data", Context.MODE_PRIVATE);
fos.write(data.getBytes());
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
讀文件
public void load() {
String fileName = "abc.txt";
try {
FileInputStream fis = openFileInput(fileName);
byte[] reader = new byte[fis.available()];
if (fis.read(reader) != -1) {
String data = new String(reader);
System.out.println(data);
}
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
共享首選項(xiàng)(SharedPreferences)
利用鍵值對(duì)的方式來存儲(chǔ)數(shù)據(jù)妇穴,文件都是存放在/data/data/<packagename>/shared_prefs/目錄下的爬虱,主要提供了三種方式用于得到SharedPreferences對(duì)象
內(nèi)容提供器
主要用于在不同的應(yīng)用程序之間實(shí)現(xiàn)數(shù)據(jù)的共享功能。目前是Android實(shí)現(xiàn)跨程序共享數(shù)據(jù)的標(biāo)準(zhǔn)方式腾它。一般有兩種:
1.使用現(xiàn)有的內(nèi)容提供其來讀取和操作相應(yīng)程序中的數(shù)據(jù)
- 創(chuàng)建自己的內(nèi)容提供器給我們的程序的數(shù)據(jù)提供外部訪問接口
使用本機(jī)內(nèi)容提供者
Android平臺(tái)提供了一些本機(jī)內(nèi)容提供者有:瀏覽器跑筝、聯(lián)系人、通話記錄瞒滴、媒體存儲(chǔ)曲梗、設(shè)置。
聯(lián)系人內(nèi)容提供者的URI各部分:
- content://contacts/people/20
- content:// 指定數(shù)據(jù)受內(nèi)容提供者控制妓忍。它是標(biāo)準(zhǔn)前綴
- contacts:指原生Contacts內(nèi)容提供者
- people指contacts列表可用記錄
- 20指Contacts列表中的第二十條記錄虏两。它是指定記錄的ID
- 使用getContentResolver()方法獲取ContentResolver對(duì)象,通過該對(duì)象的以下方法訪問內(nèi)容提供者
public final Uri insert(Uri url, ContentValues values) public final int delete(Uri url, String where, String[] selectionArgs) public final int update(Uri uri, ContentValues values, String where,String[] selectionArgs) public final Cursor query(Uri uri, String[] projection,String selection, String[] selectionArgs, String sortOrder)
使用自定義內(nèi)容提供器
創(chuàng)建內(nèi)容提供器
新建一個(gè)類去繼承ContentProvider单默,并重寫其6個(gè)方法碘举,代碼如下:
public class MyProvider extends ContentProvider {
@Override
public boolean onCreate() {
return false;
}
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
return null;
}
@Nullable
@Override
public String getType(@NonNull Uri uri) {
return null;
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
return null;
}
@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
}
- onCreate()
初始化內(nèi)容提供器的時(shí)候調(diào)用。通常會(huì)在這里完成對(duì)數(shù)據(jù)庫(kù)的創(chuàng)建和升級(jí)等操作搁廓,
返回 true 表示內(nèi)容提供器初始化成功引颈,返回 false 則表示失敗。注意境蜕,只有當(dāng)存在
ContentResolver 嘗試訪問我們程序中的數(shù)據(jù)時(shí)蝙场,內(nèi)容提供器才會(huì)被初始化。- query()
從內(nèi)容提供器中查詢數(shù)據(jù)粱年。使用 uri 參數(shù)來確定查詢哪張表售滤,projection 參數(shù)用于確
定查詢哪些列,selection 和 selectionArgs 參數(shù)用于約束查詢哪些行台诗,sortOrder 參數(shù)用于
對(duì)結(jié)果進(jìn)行排序完箩,查詢的結(jié)果存放在 Cursor 對(duì)象中返回。- insert()
向內(nèi)容提供器中添加一條數(shù)據(jù)拉队。使用 uri 參數(shù)來確定要添加到的表弊知,待添加的數(shù)據(jù)
保存在 values 參數(shù)中。添加完成后粱快,返回一個(gè)用于表示這條新記錄的 URI秩彤。- update()
更新內(nèi)容提供器中已有的數(shù)據(jù)。使用 uri 參數(shù)來確定更新哪一張表中的數(shù)據(jù)事哭,新數(shù)
據(jù)保存在 values 參數(shù)中漫雷,selection 和 selectionArgs 參數(shù)用于約束更新哪些行,受影響的
行數(shù)將作為返回值返回鳍咱。- delete()
從內(nèi)容提供器中刪除數(shù)據(jù)降盹。使用 uri 參數(shù)來確定刪除哪一張表中的數(shù)據(jù),selection
和 selectionArgs 參數(shù)用于約束刪除哪些行谤辜,被刪除的行數(shù)將作為返回值返回澎现。- getType()
根據(jù)傳入的內(nèi)容 URI 來返回相應(yīng)的 MIME 類型仅胞。
指定內(nèi)容提供者的URI
public class MyProvider extends ContentProvider {
public static final int TABLE1_DIR = 0;
public static final int TABLE1_ITEM = 1;
public static final int TABLE2_DIR = 2;
public static final int TABLE2_ITEM = 3;
private static UriMatcher uriMatcher;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI("com.example.app.provider", "table1", TABLE1_DIR);
uriMatcher.addURI("com.example.app.provider ", "table1/#", TABLE1_ITEM);
uriMatcher.addURI("com.example.app.provider ", "table2", TABLE2_ITEM);
uriMatcher.addURI("com.example.app.provider ", "table2/#", TABLE2_ITEM);
}
..........
}
實(shí)現(xiàn)查詢方法
public class MyProvider extends ContentProvider {
..........
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
switch (uriMatcher.match(uri)) {
case TABLE1_DIR:
// 查詢table1表中的所有數(shù)據(jù)
break;
case TABLE1_ITEM:
// 查詢table1表中的單條數(shù)據(jù)
break;
case TABLE2_DIR:
// 查詢table2表中的所有數(shù)據(jù)
break;
case TABLE2_ITEM:
// 查詢table2表中的單條數(shù)據(jù)
break;
default:
break;
}
return null;
}
....
}
處理對(duì)MINE類型數(shù)據(jù)的請(qǐng)求
public class MyProvider extends ContentProvider {
...........
@Nullable
@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)) {
case TABLE1_DIR:
return "vnd.android.cursor.dir/vnd.com.example.app.provider. table1 ";
case TABLE1_ITEM:
return "vnd.android.cursor.item/vnd.com.example.app.provider. table1 ";
case TABLE2_DIR:
return "vnd.android.cursor.dir/vnd.com.example.app.provider. table2 ";
case TABLE2_ITEM:
return "vnd.android.cursor.item/vnd.com.example.app.provider. table2 ";
default:
break;
}
return null;
}
................
}
注冊(cè)自定義內(nèi)容提供器
<provider
android:name="com.example.databasetest.DatabaseProvider"
android:authorities="com.example.databasetest.provider" >
</provider>
廣播接收者(BroadcastReceiver)
廣播分為兩種:普通廣播和有序廣播
- 普通廣播
完全異步執(zhí)行的廣播,在廣播發(fā)出后剑辫,所有的廣播接收器幾乎在同一時(shí)刻都會(huì)受到這條廣播,沒有先后順序之分渠欺,無(wú)法被截?cái)嗝帽危瘦^高
- 有序廣播
同步執(zhí)行的廣播,在廣播發(fā)出后挠将,同一時(shí)刻只會(huì)有一個(gè)廣播接收器可以收到消息胳岂,且只有當(dāng)該廣播接收器中的邏輯執(zhí)行完畢后,這條廣播才會(huì)繼續(xù)傳遞下去舔稀,有先后順序之分乳丰,可以被截?cái)唷?/p>
注冊(cè)廣播接收器的方式有兩種:
- 動(dòng)態(tài)注冊(cè)
在代碼中注冊(cè),新建一個(gè)類内贮,并讓其繼承BroadcastReceiver類产园,同時(shí)重新其父類中的onReceive()方法即可,這樣當(dāng)有廣播到來的時(shí)候夜郁,onReceive()方法便會(huì)得到執(zhí)行,同時(shí)需要主活動(dòng)中進(jìn)行廣播的注冊(cè)什燕,因?yàn)槿淌窃诖a中運(yùn)行,靈活性強(qiáng)竞端,便被成為動(dòng)態(tài)注冊(cè)屎即,示例如下:
private class NetWorkChangeReceiverextends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// do something......
}
}
在onCreate()方法中執(zhí)行:
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
netWorkChangeReceiver = new NetWorkChangeReceiver();
registerReceiver(netWorkChangeReceiver, intentFilter);
在onDestory()方法中執(zhí)行:
unregisterReceiver(netWorkChangeReceiver);//注銷廣播
- 靜態(tài)注冊(cè)
和動(dòng)態(tài)注冊(cè)相同的是,靜態(tài)注冊(cè)也需要?jiǎng)?chuàng)建一個(gè)類去繼承BroadcastReceiver類并實(shí)現(xiàn)其中的onReceive()方法事富,但是注冊(cè)的過程被放到了AndroidManifest.xml文件中了技俐,示例如下:
MyBroadcastReceiver.java
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "received in MyBroadcastReceiver", Toast.LENGTH_SHORT).show();
}
}
AndroidManifest.xml
<receiver
android:name=".MyBroadcastReceiver"
android:enabled="true"
adroid:exported="true">
<intent-filter>
<action android:name="com.lyy.broadcast.MY_BROADCAST" />
</intent-filter>
</receiver>
動(dòng)態(tài)注冊(cè)和靜態(tài)注冊(cè)的區(qū)別:
動(dòng)態(tài)注冊(cè)不是常駐型廣播,也就是說廣播跟隨程序的生命周期统台。
靜態(tài)注冊(cè)是常駐型雕擂,也就是說當(dāng)應(yīng)用程序關(guān)閉后,如果有信息廣播來饺谬,程序也會(huì)被系統(tǒng)調(diào)用自動(dòng)運(yùn)行
服務(wù)
創(chuàng)建一個(gè)服務(wù)
新建一個(gè)類MyService集成Service捂刺,并重寫其onBind()方法即可
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
當(dāng)然,最為四大組件之一的Service募寨,服務(wù)在創(chuàng)建的時(shí)候需要在AndroidManifest.xml文件中進(jìn)行注冊(cè)才能生效
<service
android:name=".MyService"
android:enabled="true"
android:exported="true">
</service>
啟動(dòng)一個(gè)服務(wù)
調(diào)用startService()方法即可啟動(dòng)服務(wù)族展,傳入一個(gè)intent參數(shù)即可
Intent intent = new Intent(MainActivity.this, MyService.class);
startService(intent);
關(guān)閉一個(gè)服務(wù)
調(diào)用stopService()方法即可
Intent intent = new Intent(MainActivity.this, MyService.class);
stopService(intent);
綁定一個(gè)服務(wù)
- 定義一個(gè)內(nèi)部類,該內(nèi)部類實(shí)現(xiàn)接口”ServiceConnection”拔鹰,同時(shí)實(shí)現(xiàn)接口里的兩個(gè)方法:”onServiceConnection”(在這個(gè)方法方法體里得到Binder對(duì)象仪缸,由該對(duì)象就能得到服務(wù)實(shí)例)、”onServiceDisConnection”(當(dāng)服務(wù)被意外斷開列肢,系統(tǒng)將會(huì)回調(diào)這個(gè)方法)恰画。
- 分別創(chuàng)建服務(wù)類變量宾茂、內(nèi)部類變量(內(nèi)部類變量需要實(shí)例化),在”onServiceConnection”方法里面用得到的服務(wù)實(shí)例將服務(wù)類變量實(shí)例化
- 在需要綁定服務(wù)的地方拴还,調(diào)用bindService()方法跨晴,將內(nèi)部類變量傳入。
public class MainActivity extends Activity implements View.OnClickListener {
//第二步:創(chuàng)建內(nèi)部類變量以及服務(wù)類的變量
//同時(shí)實(shí)例化內(nèi)部類變量
private MService mService = null;
private MServiceConnection mServiceConnection =
new MServiceConnection();
//窗體的初始化方法
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
findViewById(R.id.bt_bind_the_service)
.setOnClickListener(this);
}
//點(diǎn)擊事件響應(yīng)函數(shù)
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.bt_bind_the_service:
Intent intent =
new Intent(MainActivity.this, MService.class);
//第三步:綁定服務(wù)那個(gè)時(shí)候?qū)⒔涌诘膶?shí)例傳入
bindService(intent, mServiceConnection,
Context.BIND_AUTO_CREATE);
break;
}
}
//第一步:定義一個(gè)內(nèi)部類去實(shí)現(xiàn)接口”ServiceConnection”
class MServiceConnection implements ServiceConnection{
//這個(gè)方法里面那個(gè)service
//就是服務(wù)類里面的onBind()方法所返回的IBinder變量了
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//還是第二步:將服務(wù)類的變量實(shí)例化:
//將IBinder向下轉(zhuǎn)型
MService.MyBinder myBinder = (MService.MyBinder)service;
//調(diào)用公有方法就能獲得服務(wù)類的實(shí)例
mService = myBinder.getService();
Log.i("test","連接服務(wù)");
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i("test", "意外斷開");
}
}
}
解綁一個(gè)服務(wù)
相對(duì)于綁定一個(gè)服務(wù)和活動(dòng)來說片林,解除服務(wù)和活動(dòng)之間的綁定就顯得容易很多端盆,只需要執(zhí)行unbindService()方法,并傳入一個(gè)ServiceConnection()對(duì)象即可费封。
unbindService(connection);