編輯:關於Android編程
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" />
下圖是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。
onPause,onstop, onDestroy,三種狀態下 activity都有可能被系統kill掉
Activity有四種狀態分別是:
Running狀態 Stopped狀態 Paused狀態 Destroyed狀態生命周期方法在各個狀態被調用時機如下圖:
由上圖可以看出:
當Running狀態的時候,調用onPause方法可以切換到Pauseed狀態。 當在Paused狀態的時候,調用onResume方法可以切換到Running狀態,調用onStop方法可以切換到Stopped狀態,如果應用被退出就切換到Destroyed狀態。 當處在Stopped狀態時候,調用onRestart方法、onStart方法、onResume方法會切換到Running狀態,調用onDestroy方法或者應用被退出就會切換到Destroyed狀態。在 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 方式。
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文件配置:
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();
}
第一種:顯示啟動
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) ;
以下是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);
兩種方法:
第一種:寫一個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
在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文件中設置:
在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);中將數據取出。
注意:取出數據的時候要進行判空操作。
小米聯合中國聯通推出了新機——紅米3X,具備4100mAh超大電池,售價899元。現在,這款手機已經在中國聯通官網開啟預約,只需輸入
Android在4.0版本之後同時按電源鍵和音量鍵可以截取當前屏幕,截圖後會有一個過渡動畫效果,這裡提取了將效果這部分提取出來,可以用於應用截圖分享功能。 截圖功能在源碼
1,如何修改主菜單圖標的位置?[DESCRIPTION]默認主菜單圖標在中間,如何修改它的位置? Launcher3:DynamicGrid.java文件hotseatA
智能語音技術如今越來越多的app用到了語音播報功能,例如地圖導航、天氣預報、文字閱讀、口語訓練等等。語音技術主要分兩塊,一塊是語音轉文字,即語音識別;另一塊是文字轉語音,