Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android學習筆記四之Activity

Android學習筆記四之Activity

編輯:關於Android編程

1、什麼是Activity

Activity是Android四大組件之一,用於顯示View。Activity是一個應用程序組件,提供一個用戶交互的接口,其本身是沒有界面的,Activity類創建一個窗口,在上面可以繪制用戶接口。窗口通常充滿屏幕,也可以小於屏幕而懸浮於其他窗口之上。

開發者可以通過Activity類提供的setContentView(View)接口將View放到Activity創建的窗口上。一個程序一般由多個Activity組成,他們通常是松耦合關系。一個Activity可以啟動另外一個Activity。每次一個Activity啟動,前一個Activity就停止,但是Android系統會保留Activity在一個棧上,當用戶完成當前Activity然後點擊back按鈕時,它就會被彈出棧並被銷毀。所有的Activity類必須在AndroidManifest.xml文件中注冊,不注冊會報錯。例如:

<activity android:name=".BaseActivity" />
<activity android:name=".activity.AboutCSDNActivity" />
<activity android:name=".activity.BlogOsphereActivity" />
<activity android:name=".activity.FeedBackActivity" />
<activity android:name=".activity.WebActivity" />
<activity android:name=".activity.AllBloggerActivity" />
<activity android:name=".activity.BlogDetailActivity" />

2、activity的生命周期方法

下圖是Android api中所提供的Activity生命周期圖

\

由圖可以看出,Activity有如下生命周期方法,分別是:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;"> public class Activity extends ApplicationContext { protected void onCreate(Bundle savedInstanceState); protected void onStart(); protected void onResume(); protected void onPause(); protected void onStop(); protected void onDestroy();  }

一個Activity啟動,執行生命周期方法順序是:onCreate -> onStart -> onResume;當一個Activity被Kill掉時候,執行生命周期方法順序是:onPause -> onStop -> onDestroy。這是一個完整的生命周期循環。當一個應用正在運行,由於其它應用中斷,比如電話來了等,執行的生命周期方法是onPause -> onStop,掛斷電話恢復到當前應用,執行的生命周期方法是onStart -> onResume;如果當前應用的Activity是Theme為Translucent(半透明)或者Dialog時,那麼中斷就是onPause ,恢復的時候onResume。

2.1、各種生命周期方法在系統中的作用

onCreate方法:在這裡創建界面,可以實現一些界面的初始化工作 onStart方法:在onCreate方法之後被調用,或者Activity從stop狀態轉換為Active狀態被調用,可以實現數據的請求 onResume方法:在 Activity 從 Pause 狀態轉換到 Active 狀態時被調用。 onPause方法:在 Activity 從 Active 狀態轉換到 Pause 狀態時被調用。在這裡可以保存一些數據,在onResume方法中可以讀取這裡保存的數據。 onStop方法:在 Activity 從 Active 狀態轉換到 Stop 狀態時被調用。一般我們在這裡保存 Activity 的狀態信息。 onDestroy方法:在 Activity 被結束時調用,它是被結束時調用的最後一個方法,在這裡一般做些釋放資源,清理內存等工作。

onPause,onstop, onDestroy,三種狀態下 activity都有可能被系統kill掉

2.2、Activity的四種狀態

Activity有四種狀態分別是:

Running狀態 Stopped狀態 Paused狀態 Destroyed狀態

生命周期方法在各個狀態被調用時機如下圖:

\

由上圖可以看出:

當Running狀態的時候,調用onPause方法可以切換到Pauseed狀態。 當在Paused狀態的時候,調用onResume方法可以切換到Running狀態,調用onStop方法可以切換到Stopped狀態,如果應用被退出就切換到Destroyed狀態。 當處在Stopped狀態時候,調用onRestart方法、onStart方法、onResume方法會切換到Running狀態,調用onDestroy方法或者應用被退出就會切換到Destroyed狀態。

3、Activity之間的通信

在 Android 中,不同的 Activity 實例可能運行在一個進程中,也可能運行在不同的進程中。因此我們需要一種特別的機制幫助我們在 Activity 之間傳遞消息。Android 中通過 Intent 對象來表示一條消息,一個 Intent 對象不僅包含有這個消息的目的地,還可以包含消息的內容,這好比一封 Email,其中不僅應該包含收件地址,還可以包含具體的內容。對於一個 Intent 對象,消息“目的地”是必須的,而內容則是可選項。

Intent負責對操作的動作、動作涉及數據、附加數據進行描述,Android則根據此Intent的描述,負責找到對應的組件,將 Intent傳遞給調用的組件,並完成組件的調用。因此,Intent在這裡起著一個媒體中介的作用,專門提供組件互相調用的相關信息,實現調用者與被調用者之間的解耦。

在應用中,我們可以通過兩種形式來使用Intent:

直接Intent:指定了component屬性的Intent(setClass(Context, Class)來指定)。通過指定具體的組件類,通知應用啟動對應的組件。

間接Intent:沒有指定comonent屬性的Intent。這些Intent需要包含足夠的信息,這樣系統才能根據這些信息,在在所有的可用組件中,確定滿足此Intent的組件。
對於直接Intent,Android不需要去做解析,因為目標組件已經很明確。

Android需要解析的是那些間接Intent,通過解析,將 Intent映射給可以處理此Intent的Activity、IntentReceiver或Service。Intent解析機制主要是通過查找已注冊在AndroidManifest.xml中的所有IntentFilter及其中定義的Intent,最終找到匹配的Intent。

通過setClass傳遞消息:

 Intent intent =new Intent(CurrentActivity.this,OtherActivity.class);
 Bundle bundle =new Bundle();
 bundle.putBoolean("boolean_key", true);
 bundle.putString("string_key", "string_value"); 
 intent.putExtra("key", bundle);
 startActivity(intent);

另一個Activity解析消息:

Intent intent =getIntent(); 
 Bundle bundle =intent.getBundleExtra("key"); 
 bundle.getBoolean("boolean_key");
 bundle.getString("string_key");

除了使用intent之外還可以使用sharedpreference傳遞消息:

 // 寫入 SharedPreferences 
 SharedPreferences preferences = getSharedPreferences("name", MODE_PRIVATE); 
 Editor editor = preferences.edit(); 
 editor.putBoolean("boolean_key", true); 
 editor.putString("string_key", "string_value"); 
 editor.commit(); 

 // 讀取 SharedPreferences 
 SharedPreferences preferences = getSharedPreferences("name", MODE_PRIVATE); 
 preferences.getBoolean("boolean_key", false); 
 preferences.getString("string_key", "default_value");

一個Activity向另外一個Activity傳遞消息,後一個Activity傳回給前一個

例如:A.Activity向B.Activity傳遞一些消息,當B.Activity關閉的時候回傳一些消息給A.Activity

//在A.Activity中加入:

button.setOnClickListener(new OnClickListener(){
   @Override
   public void onClick(View arg0) {
  Intent intent = new Intent();
  intent.setClass(a.this, b.class);
  Bundle bundle = new Bundle();
  bundle.putString("v_id",i_id);
  intent.putExtras(bundle);
  startActivityForResult(intent,0);
  overridePendingTransition(R.anim.zoomin, R.anim.zoomout);
   }

 });

//在B.Activity中加入:
String v_id = this.getIntent().getExtras().getString("v_id");



//在B.Activity 中加入。當關閉b時,傳遞數據name給a:

   b_close.setOnClickListener(new OnClickListener(){
   @Override
   public void onClick(View arg0) {
   Intent intent = getIntent();
   Bundle bundle = new Bundle();
   bundle.putString("name",name);
   intent.putExtras(bundle);
   setResult(RESULT_OK,intent);
   finish();
   }
});



//在A.Activity中加入,接受回調信息name
 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data_intent){
super.onActivityResult(requestCode, resultCode, data_intent);
 if(resultCode == RESULT_CANCELED)
setTitle("cancel");
 else if (resultCode == RESULT_OK){
Bundle bundle = data_intent.getExtras();
if(bundle != null){
//獲取b傳送的數據
  String name = bundle.getString("name");  
}
   }
}

Android 提供了包括 SharedPreferences 在內的很多種數據存貯方式,比如 SQLite,文件等,程序員可以通過這些 API 實現 Activity 之間的數據交換。如果必要,我們還可以使用 IPC 方式。

4、Activity的四種加載模式

Activity有四種加載模式,分別是:standard模式、singleTop模式、singleTask模式、singleInstance模式(其中standard模式和singleTop模式是一組、singleTask模式和singleInstance模式是一組),默認加載模式是standard模式。

四種加載模式的區別:

1、standard:標准模式(默認模式),一旦調用startActivity()方法就會產生一個新的Activity實例。 不需要在launchMode屬性配置

/**
 * 默認(standard)加載模式
 * 
 */
public class ActivityOne extends Activity implements OnClickListener
{
private TextView textView;// 顯示文本
private Button button;

@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    textView = (TextView) findViewById(R.id.textView);
    button = (Button) findViewById(R.id.button);
    button.setText("go to ActivityOne");
    button.setOnClickListener(this);
    textView.setText(this + "");
}

@Override
public void onClick(View v)
{
    Intent intent = new Intent();
    intent.setClass(ActivityOne.this, ActivityOne.class);// 跳轉
    startActivity(intent);
}
}

AndroidManifset.xml文件配置:


    
   
   
   

2、singleTop:如果Activity實例位於棧頂,就不產生新的實例,直接使用棧頂的實例,否則,就會產生一個新的實例。
例如:現在Task棧元素為A-B-C-D(D在棧頂),這時候給D發一個啟動Intent,如果D是 “standard”模式的,則生成D的一個新實例,棧狀態為A-B-C-D-D。如果D是singleTop模式的話,則不會生成D的新實例,棧狀態仍為A-B-C-D。如果這時候給B發Intent的話,不管B的launchMode是“standard”還是“singleTop”,都會生成B的新實例,棧狀態變為A-B-C-D-B。

/**
 * singleTop模式
 */
public class ActivityOne extends Activity implements OnClickListener
{
private TextView textView;// 顯示文本
private Button button;

@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    textView = (TextView) findViewById(R.id.textView);
    button = (Button) findViewById(R.id.button);
    button.setText("go to ActivityOne");
    button.setOnClickListener(this);
    textView.setText(this + "");
}

@Override
public void onClick(View v)
{
    Intent intent = new Intent();
    intent.setClass(ActivityOne.this, ActivityOne.class);// 跳轉
    startActivity(intent);
}
}

AndroidManifset.xml文件配置:







3、singleTask:每次調用都會使用這個實例,不會去產生新的實例了。

AndroidManifset.xml文件配置:









4、singleInstance:跟singleTask模式基本上是一樣,只有一個區別:在這個模式下的Activity實例與其他Activity處在不同的Task中,此實例所處的Task中只能有這個Activity實例,不能有其他的實例。

AndroidManifaset.xml文件配置:









5、Activity的創建和啟動

5.1、Activity的創建流程

Activity創建需要經歷如下的步驟:

(1) 自定義Activity類名,繼承Activity類或者其子類,使用AS開發,一般繼承AppCompatActivity類

public class BaseActivity extends AppCompatActivity {}

(2) 重寫onCreate方法,並在該方法中調用setContentView方法

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(View);
}

(3) 在AndroidManiFest.xml文件中注冊Activity,必須要注冊,不注冊會報錯

  
    
        
            

            
        

    
    
    
    
    
    
    
    
    

(4) 啟動Activity,通過調用startActivity(Intent)啟動。

Intent intent = new Intent(getApplicationContext(), BlogDetailActivity.class);
   intent.putExtra("username", blogOspheres.get(position).getUserName());
   intent.putExtra("name", blogOspheres.get(position).getName());
   startActivity(intent);

(5) 銷毀Activity,通過調用Finish()方法

        @Override
        public void onClick(View v) {
            finish();
        }

5.2、Activity啟動的幾種方式

第一種:顯示啟動

startActivity(new Intent(當前Activity,要啟動的Activity.class));

//通過intent的ComponentName啟動
ComponentName componentName = new ComponentName("當前Activity的全限定類名","啟動Activity的全限定類名") ;
Intent intent = new Intent() ;
intent.setComponent(componentName) ;
startActivity(intent) ;

Intent intent = new Intent("android.intent.action.MAIN");
intent.setClassName("當前Activity的全限定類名","啟動Activity的全限定類名");
startActivity(intent);

第二種:隱式啟動

 
 
 
 
 

Intent intent=new Intent("com.example.android.tst.SecondActivity"); 
startActivity(intent);

第三種:啟動APK

Intent intent = getPackageManager().getLaunchIntentForPackage
("apk第一個啟動的Activity的全限定類名") ;
if(intent != null) startActivity(intent) ;

6、系統給我們提供的Activity

以下是Android系統給我們提供的常用的Activity

撥打電話

Uri uri = Uri.parse("tel:10010");
Intent intent = new Intent(Intent.ACTION_DIAL, uri);
startActivity(intent);

發送短信

Uri uri = Uri.parse("smsto:10010");
Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
intent.putExtra("sms_content", "Hello");
startActivity(intent);

發送彩信

Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra("sms_body", "Hello");
Uri uri = Uri.parse("content://media/external/images/media/23");
intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.setType("image/png");
startActivity(intent);

打開浏覽器:

Uri uri = Uri.parse("http://www.baidu.com");
Intent intent  = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);

發送電子郵件

Uri uri = Uri.parse("mailto:[email protected]");
Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
startActivity(intent);

// 給[email protected]發郵件發送內容為“Hello”的郵件
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, "[email protected]");
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
intent.putExtra(Intent.EXTRA_TEXT, "Hello");
intent.setType("text/plain");
startActivity(intent);
// 給多人發郵件
Intent intent=new Intent(Intent.ACTION_SEND);
String[] mailTos = {"[email protected]", "[email protected]"}; // 收件人
String[] copyTos = {"[email protected]", "[email protected]"}; // 抄送
String[] secretTos = {"[email protected]", "[email protected]"}; // 密送
intent.putExtra(Intent.EXTRA_EMAIL, mailTos);
intent.putExtra(Intent.EXTRA_CC, copyTos);
intent.putExtra(Intent.EXTRA_BCC, secretTos);
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
intent.putExtra(Intent.EXTRA_TEXT, "Hello");
intent.setType("message/rfc822");
startActivity(intent);

顯示地圖:

Uri uri = Uri.parse("geo:23.20,113.30");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);

多媒體播放:

Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse("file:///sdcard/music.mp3");
intent.setDataAndType(uri, "audio/mp3");
startActivity(intent);

獲取SD卡下所有音頻文件,然後播放第一首

Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);

打開攝像頭拍照:

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
startActivityForResult(intent, 0);

// 取出照片數據
Bundle extras = intent.getExtras(); 
Bitmap bitmap = (Bitmap) extras.get("data");

另一種:
調用系統相機應用程序,並存儲拍下來的照片
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
time = Calendar.getInstance().getTimeInMillis();
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment
.getExternalStorageDirectory().getAbsolutePath()+"/tucue", time + ".jpg")));
startActivityForResult(intent, ACTIVITY_GET_CAMERA_IMAGE);

獲取並剪切圖片

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
intent.putExtra("crop", "true"); // 開啟剪切
intent.putExtra("aspectX", 1); // 剪切的寬高比為1:2
intent.putExtra("aspectY", 2);
intent.putExtra("outputX", 20); // 保存圖片的寬和高
intent.putExtra("outputY", 40); 
intent.putExtra("output", Uri.fromFile(new File("/mnt/sdcard/temp"))); // 保存路徑
intent.putExtra("outputFormat", "JPEG");// 返回格式
startActivityForResult(intent, 0);

剪切特定圖片

Intent intent = new Intent("com.android.camera.action.CROP"); 
intent.setClassName("com.android.camera", "com.android.camera.CropImage"); 
intent.setData(Uri.fromFile(new File("/mnt/sdcard/temp"))); 
intent.putExtra("outputX", 1); // 剪切的寬高比為1:2
intent.putExtra("outputY", 2);
intent.putExtra("aspectX", 20); // 保存圖片的寬和高
intent.putExtra("aspectY", 40);
intent.putExtra("scale", true);
intent.putExtra("noFaceDetection", true); 
intent.putExtra("output", Uri.parse("file:///mnt/sdcard/temp")); 
startActivityForResult(intent, 0);

進入手機設置界面:

Intent intent = new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS);  
startActivityForResult(intent, 0);

安裝apk應用:

Uri installUri = Uri.fromParts("package", "xxx", null);   
returnIt = new Intent(Intent.ACTION_PACKAGE_ADDED, installUri);

卸載apk應用:

Uri uri = Uri.fromParts("package", packageName, null);  
Intent it = new Intent(Intent.ACTION_DELETE, uri);  
startActivity(it); 

打開聯系人:

Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(People.CONTENT_URI);
startActivity(intent);

查看指定聯系人:

Uri personUri = ContentUris.withAppendedId(People.CONTENT_URI, info.id);//info.id聯系人ID
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(personUri);
startActivity(intent);

7、Activity的安全退出

兩種方法:

第一種:寫一個BaseActivity,項目中所有的Activity都繼承於這個BaseActivity,在BaseActivity中記錄每一個Activity,退出應用的時候將所有的Activity銷毀

 //用一個集合管理所有的activity
public final static LinkedList mBaseActivities = new LinkedList();
public static BaseActivity mBaseActivity;

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    synchronized (mBaseActivities) {
        mBaseActivities.add(this);
    }
}

 @Override
protected void onResume() {
super.onResume();
mBaseActivity = this;
}

@Override
protected void onPause() {
super.onPause();
mBaseActivity = null;
}

@Override
protected void onDestroy() {
    super.onDestroy();
    synchronized (mBaseActivities) {
        mBaseActivities.remove(this);
    }
}

//安全退出程序
public static void exitApp() {
    LinkedList activityCopy;
    //復制一份activity
    synchronized (mBaseActivities) {
        activityCopy = new LinkedList(mBaseActivities);
    }
    for (BaseActivity baseActivity : activityCopy) {
        baseActivity.finish();
    }
    //殺死當前進程
    android.os.Process.killProcess(android.os.Process.myPid());
}

第二種方法:退出的時候發送廣播,銷毀所有的Activity

8、Activity切換動畫設置

在Activity切換的時候設置切換動畫有兩種方式:

第一種:在Activity跳轉的時候設置,即是在startActivity方法之後設置,代碼如下:

A.Activity跳轉到B.Activity時,在startActivity()方法後面設置

 //第一個參數是activity離開時的動畫,第二個參數是activity進入時的動畫
 overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out);

B.Activity回轉到A.Activity時,在Finish()方法後面設置

finish();
overridePendingTransition(R.anim.push_left_in, R.anim.push_left_out);

優化思路:可以將整個應用裡面Activity相同的操作抽取到一個類裡面,在BaseActivity中實例化,每一次設置動畫或者進行Activity相關操作(比如,Activity跳轉、傳遞參數等),直接調用方法即可,代碼如下:

public class Opration {

private Intent mIntent = new Intent();
private Activity mContext = null;
private BaseApplication application = null;

public Opration(Activity mContext) {
    this.mContext = mContext;
    application = (BaseApplication) this.mContext.getApplicationContext();
}

/**
 * 跳轉Activity
 *
 * @param activity 需要跳轉至的Activity
 */
public void forward(Class activity) {
    mIntent.setClass(mContext, activity);
    mContext.startActivity(mIntent);
    mContext.overridePendingTransition(R.anim.base_slide_right_in, R.anim.base_slide_remain);
}

/**
 * 設置傳遞參數
 *
 * @param key   參數key
 * @param value 數據傳輸對象
 */
public void addParameter(String key, Bundle value) {
    mIntent.putExtra(key, value);
}

/**
 * 設置傳遞參數
 *
 * @param key   參數key
 * @param value 數據傳輸對象
 */
public void addParameter(String key, String value) {
    mIntent.putExtra(key, value);
}
}

第二種設置切換動畫的方法:在樣式文件裡面設置


修改Theme


最後在AndroidManifest.xml文件中設置:


9、Activity其他設置

9.1、橫豎屏切換問題

在Android中,默認狀態下APP橫豎屏切換的時候會銷毀當前的Activity實例,然後重新創建Activity實例,橫豎屏切換時Activity的生命周期方法順序是:onPause-> onStop-> onDestory-> onCreate->onStart->onResume。在一些特殊情況下,我們需要對橫豎屏切換進行一些處理,以下是常用的處理:

禁止屏幕橫豎屏切換

在AndroidManifest.xml中為Activity添加一個屬性:android:screenOrientation, 這個屬性有下述可選值:

unspecified:默認值 由系統來判斷顯示方向.判定的策略是和設備相關的,所以不同的設備會有不同的顯示方向。 landscape:橫屏顯示(寬比高要長) portrait:豎屏顯示(高比寬要長) user:用戶當前首選的方向 behind:和該Activity下面的那個Activity的方向一致(在Activity堆棧中的) sensor:有物理的感應器來決定。如果用戶旋轉設備這屏幕會橫豎屏切換。 nosensor:忽略物理感應器,這樣就不會隨著用戶旋轉設備而更改了(”unspecified”設置除外)。
橫豎屏切換的時候加載不同的布局

1)准備兩套不同的布局,Android會自己根據橫豎屏加載不同布局: 創建兩個布局文件夾:layout-land橫屏,layout-port豎屏 然後把這兩套布局文件放在這兩個文件夾裡,文件名一樣,Android就會自行判斷,然後加載相應布局了!

2 )自己在代碼中進行判斷
我們一般是在onCreate()方法中加載布局文件的,我們可以在這裡對橫豎屏的狀態做下判斷,關鍵代碼如下:

if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){  
 setContentView(R.layout.橫屏);
}  

else if (this.getResources().getConfiguration().orientation ==Configuration.ORIENTATION_PORTRAIT) {  
setContentView(R.layout.豎屏);
}
狀態保存問題

通過一個Bundle savedInstanceState參數即可完成,有三個核心方法:

onCreate(Bundle savedInstanceState);
onSaveInstanceState(Bundle outState);
onRestoreInstanceState(Bundle savedInstanceState);

在onSaveInstanceState(Bundle outState);裡面將需要保存的數據放入到Bundle裡面,然後在 onCreate(Bundle savedInstanceState);或者onRestoreInstanceState(Bundle savedInstanceState);中將數據取出。

注意:取出數據的時候要進行判空操作。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved