Download presentation
Presentation is loading. Please wait.
1
第9章 使用意圖啟動活動與內建應用程式 9-1 意圖的基礎 9-2 使用意圖啟動活動
9-3 再談AndroidManifest.xml與權限管理 9-4 使用意圖啟動內建應用程式 9-5 建立多國語系的Android應用程式
2
9-1 意圖的基礎 – 說明 意圖(Intents)是一個啟動其他Android活動、服務和廣播接收器的系統訊息,一種抽象描述希望執行的操作,可以告訴Android作業系統我想作什麼?執行什麼動作?例如:啟動其他活動、告訴指定服務可以啟動或停止與送出廣播。
3
9-1 意圖的基礎 – 意圖與意圖篩選 Android應用程式送出意圖的訊息需要經過Android作業系統來判斷接收者是誰,它是使用意圖篩選(Intent Filters)找出有能力處理的活動或內建應用程式,然後才將訊息送給接收者,如右圖所示:
4
9-1 意圖的基礎 – 意圖的種類 Android作業系統的意圖分為兩種,如下所示:
明確意圖(Explicit Intent):指明目標活動接收者名稱,即明確指明是送給誰,通常是使用在連接同一個應用程式內部的多個活動,如同活動之間的結合劑,前述啟動Activity2和第9-2節是明確意圖。 隱含意圖(Implicit Intent):意圖只有指出執行的動作、型態和目錄,並沒有目標接收者的確實名稱,Android作業系統任何可以完成此工作的應用程式都可以是接收者,即前述寄送郵件,在第9-4節是隱含意圖。
5
9-2 使用意圖啟動活動 9-2-1 使用意圖啟動其他活動 9-2-2 傳遞資料給其他活動 9-2-3 取得活動的回傳資料
9-2-4 使用意圖篩選啟動活動 9-2-5 使用動作列圖示返回父活動
6
9-2 使用意圖啟動活動 Android應用程式的活動是一個佔滿行動裝置螢幕的視窗,一個應用程式可以擁有多個活動,在活動中是一至多個介面元件建立的使用介面。基本上,Android應用程式的活動可以分成兩大類型,如下所示: 獨立的活動:這是一種沒有資料交換的活動,單純只是從一個螢幕的視窗轉換至下一個螢幕的視窗,在第9-2-1節說明的是這種活動。 相依的活動:這是一種類似Web網頁之間資料傳遞的活動,在活動之間有資料交換,我們需要將資料傳遞至下一個活動,和取得傳回資料,在第9-2-2和9-2-3節說明的是這種活動。
7
9-2-1 使用意圖啟動其他活動 – 說明 通常啟動同一應用程式的其他活動是使用明確意圖,當Android應用程式擁有多個活動時,我們需要使用意圖來啟動其他活動,其主要工作有三項,如下所示: 定義繼承Activity、FragmentActivity或AppCompatActivity等類別的新活動類別,即建立新活動。 在AndroidManifest.xml註冊新活動(Android Studio使用活動範本新增活動,預設就會自動註冊新活動的<activity>標籤)。 建立意圖啟動新活動,如果需要可以在之間傳遞資料,詳見第9-2-2和9-2-3節。
8
9-2-1 使用意圖啟動其他活動 – 說明 在Android應用程式擁有兩個活動,按下第1個活動的按鈕,可以開啟第2個活動,關閉第2個活動可以回到第1個活動,其執行結果如下圖所示:
9
9-2-1 使用意圖啟動其他活動 – 步驟一:建立主活動版面配置的使用介面
請啟動Android Studio新增名為【Ch19_2_1】的空白專案(Empty Activity)後,就可以修改使用介面activity_main.xml,如下圖所示:
10
9-2-1 使用意圖啟動其他活動 – 步驟二:建立第2個活動類別和版面配置1
執行「New/Activity/Empty Activity」命令,使用範本來新增空白活動,可以看到精靈畫面 ,如下圖所示:
11
9-2-1 使用意圖啟動其他活動 – 步驟二:建立第2個活動類別和版面配置2
請切換至activity_second.xml,新增一個TextView元件,將【text】屬性值改為【第2個活動】;【id】屬性輸入【textView】。
12
9-2-1 使用意圖啟動其他活動 – 步驟二:建立第2個活動類別和版面配置3
在TextView下方新增Button元件button2,【text】屬性值是【關閉第2個活動】,和指定【onClick】屬性值為【button2_Click】。
13
9-2-1 使用意圖啟動其他活動 – 步驟二:建立第2個活動類別和版面配置4
開啟SecondActivity.java,建立button2_Click()事件處理方法來關閉活動,即呼叫finish()方法,如下所示: public void button2_Click(View view) { finish(); }
14
9-2-1 使用意圖啟動其他活動 – 步驟三:在AndroidManifest.xml註冊第2個活動
<application android:allowBackup="true" android:supportsRtl="true" <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".SecondActivity"></activity> </application>
15
9-2-1 使用意圖啟動其他活動 – 步驟四:在主活動建立意圖啟動第2個活動
在MainActivity.java建立button_Click()事件處理方法,可以建立Intent意圖物件來啟動第2個活動,請開啟【MainActivity.java】類別檔,建立button_Click()事件處理方法,其內容如下所示: public void button_Click(View view) { Intent intent = new Intent(this, SecondActivity.class); startActivity(intent); }
16
9-2-2 傳遞資料給其他活動 – 說明 Intent物件可以攜帶額外資料,並且將這些資料一併傳遞給目標活動,例如:在一個活動輸入身高和體重,然後將輸入值作為傳遞資料傳至目標活動來計算和顯示BMI值。
17
9-2-2 傳遞資料給其他活動 – 建立Intent物件攜帶Bundle物件的傳遞資料
在Intent物件攜帶傳遞資料是使用Bundle物件,一種目錄物件(Dictionary Object,儲存鍵與值的對應資料),可以儲存字串型態鍵值對應的各種資料型態資料,如下所示: Intent myIntent = new Intent(); myIntent.setClass(MainActivity.this, BMIActivity.class); Bundle bundle = new Bundle(); bundle.putString("HEIGHT", height.getText().toString()); bundle.putString("WEIGHT", weight.getText().toString()); myIntent.putExtras(bundle); startActivity(myIntent);
18
9-2-2 傳遞資料給其他活動 – 取出Intent物件攜帶傳遞的Bundle物件資料
在目標活動可以呼叫Activity物件的getIntent()方法取得Intent物件,然後呼叫Intent物件的getExtras()方法取得攜帶的Bundle物件,如下所示: Bundle bundle = this.getIntent().getExtras(); if (bundle != null) { height = Double.parseDouble( bundle.getString("HEIGHT")); weight = Double.parseDouble( bundle.getString("WEIGHT")); …… }
19
9-2-3 取得活動的回傳資料 – 說明 在之前範例是使用startActivity()方法啟動其他活動,不過,它並不能取得活動的回傳資料,我們需要使用startActivityForResult()方法來啟動活動,如此才能取得回傳資料。 回傳資料
20
9-2-3 取得活動的回傳資料 – 雙向資料交換活動的程式架構
9-2-3 取得活動的回傳資料 – 雙向資料交換活動的程式架構 在本節星座查詢的Android應用程式有2個活動,使用的是雙向資料交換,所以架構比較複雜,如下圖所示:
21
9-2-3 取得活動的回傳資料 – 傳遞資料給回傳的目標活動
9-2-3 取得活動的回傳資料 – 傳遞資料給回傳的目標活動 如同第9-2-2節,我們需要建立Intent物件來傳遞資料給回傳的目標活動,如下所示: Intent myIntent=new Intent(this, HoroscopeActivity.class); myIntent.putExtra("MONTH", month); myIntent.putExtra("DAY", day); 上述程式碼在建立Intent物件後,使用Intent物件的putExtra()過載方法來附加傳遞的月和日。在建立Intent物件後,就可以啟動需要回傳的活動,如下所示: startActivityForResult(myIntent, SET_HOROSCOPE);
22
9-2-3 取得活動的回傳資料 – 在目標活動取得資料
9-2-3 取得活動的回傳資料 – 在目標活動取得資料 在目標活動呼叫getIntent()方法取得Intent物件後,就可以取出傳遞資料,如下所示: Intent myIntent = this.getIntent(); month = myIntent.getIntExtra("MONTH", 1); day = myIntent.getIntExtra("DAY", 1);
23
9-2-3 取得活動的回傳資料 – 在目標活動建立回傳資料
9-2-3 取得活動的回傳資料 – 在目標活動建立回傳資料 在目標活動結束前,因為是回傳資料的活動,所以需要建立回傳資料,筆者改用Bundle物件來建立回傳資料,如下所示: Intent replyIntent = new Intent(); Bundle bundle = new Bundle(); bundle.putString("HOROSCOPE", horoscope); replyIntent.putExtras(bundle); 然後設定結果碼(Result Code)來回傳資料,如下所示: setResult(RESULT_OK, replyIntent);
24
9-2-3 取得活動的回傳資料 – 取得活動的回傳資料
9-2-3 取得活動的回傳資料 – 取得活動的回傳資料 在呼叫活動是覆寫onActivityResult()方法來取得回傳資料,3個參數依序是請求碼、結果碼和Intent物件,如下所示: protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode,resultCode,data); switch(requestCode) { case SET_HOROSCOPE: if (resultCode == RESULT_OK) { // 取得回傳值 } break;
25
9-2-4 使用意圖篩選啟動活動 - 使用意圖篩選來啟動活動1
9-2-4 使用意圖篩選啟動活動 - 使用意圖篩選來啟動活動1 Android Studio專案Ch9_2_4的執行結果和第9-2-1節相同,只是改用意圖篩選來啟動活動。在MainActivity活動類別的button_Click()方法是使用startActivity()方法啟動SecondActivity類別,如下所示: public void button_Click(View view) { startActivity(new Intent("ch09.ch9_2_4.SecondActivity")); }
26
9-2-4 使用意圖篩選啟動活動 - 使用意圖篩選來啟動活動2
9-2-4 使用意圖篩選啟動活動 - 使用意圖篩選來啟動活動2 Intent物件的建構子參數是元件名稱,此名稱是對應AndroidManifest.xml檔案意圖篩選指定的動作名稱,如下所示: <activity android:name=".SecondActivity"> <intent-filter> <action android:name="ch09.ch9_2_4.SecondActivity"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity>
27
9-2-4 使用意圖篩選啟動活動 - 意圖篩選的名稱衝突1
9-2-4 使用意圖篩選啟動活動 - 意圖篩選的名稱衝突1 在intent-filter元素定義可以讓其他活動啟動的元件名稱,這種作法可能會有一個問題就是名稱相同的衝突問題。 在執行Android Studio專案Ch9_2_4,按下按鈕啟動活動,因為同名活動有2個,所以Android作業系統會顯示一個選單來讓使用者選擇啟動的活動,如右圖所示:
28
9-2-4 使用意圖篩選啟動活動 - 意圖篩選的名稱衝突2
9-2-4 使用意圖篩選啟動活動 - 意圖篩選的名稱衝突2 …... <activity android:name=".SecondActivity" android:label="第2個活動"> <intent-filter> <action android:name="ch09.ch9_2_4.SecondActivity"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity> <activity android:name=".ThirdActivity" android:label="第3個活動"> ......
29
9-2-5 使用動作列圖示返回父活動-說明 在Android應用程式的動作列(Action Bar)可以在標題文字前顯示應用程式圖示,稱為首頁圖示(Home Icon)。我們可以指定此圖示如同上一層按鈕(Up Button),可以回到目前活動的父活動,不同於按下行動裝置的【返回】鍵,永遠是回到上一個活動。 讀者可能會懷疑上一個活動和父活動到底有何差異,筆者準備使用GMail郵件工具來說明,當在首頁畫面上方顯示有新郵件的通知提醒時,點選項目可以檢視這封郵件的內容,如果按【返回】鍵是回到上一個首頁畫面;按上一層鈕是回到GMail工具的郵件清單。
30
9-2-5 使用動作列圖示返回父活動-範例 Android Studio專案Ch9_2_5是修改自第9-2-1節,當在第1個活動按【啟動第2個活動】鈕切換至第2個活動,因為此活動有指定動作列的上一層圖示,可以看到位在活動名稱前的箭頭圖示,如下圖所示:
31
9-2-5 使用動作列圖示返回父活動- 顯示上一層圖示
首先在SecondActivity活動類別的onCreate()覆寫方法顯示上一層圖示,如下所示: public class SecondActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); ActionBar actionBar = getSupportActionBar(); actionBar.setDisplayHomeAsUpEnabled(true); }
32
9-2-5 使用動作列圖示返回父活動- AndroidManifest.xml檔案
我們需要在AndroidManifest.xml檔案指定SecondActivity活動的父活動是誰,以便上一層圖示可以正確的返回父活動。請開啟AndroidManifest.xml檔案找到第2個活動的<activity>標籤,新增android:parentActivityName屬性,屬性值是父活動類別名稱.MainActivity(支援Android 4.1之後版本)。如下所示: <activity android:name=".SecondActivity" android:label="第二個活動" android:parentActivityName=".MainActivity"> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".MainActivity"/> </activity>
33
9-3 再談AndroidManifest.xml與權限管理
34
9-3-1 再談AndroidManifest.xml檔案 –說明
Android Studio專案的AndroidManifest.xml檔是告知Android作業系統此應用程式擁有哪些元件,和相關資訊,這些資訊可以讓Android作業系統知道需要使用哪一種版本、權限或意圖篩選等來執行此Android應用程式。
35
9-3-1 再談AndroidManifest.xml檔案– 基本結構1
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android=" package="com.example.joe.ch9_2_1"> <application android:allowBackup="true" android:supportsRtl="true"
36
9-3-1 再談AndroidManifest.xml檔案– 基本結構2
<activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".SecondActivity"></activity> </application> <uses-permission android:name="android.permission.INTERNET"/> </manifest>
37
9-3-1 再談AndroidManifest.xml檔案– manifest根元素1
AndroidManifest.xml檔案是一份XML文件,manifest標籤的常用屬性如下表所示: 屬性 說明 package 應用程式Java類別所屬的套件名稱 android:versionCode 應用程式內部開發的版號,預設值為1,每次改版都需增加值,以便Android巿集判斷程式是否有更新(因為如果巿集的版號大於安裝的版號,就表示有更新) android:versionName 應用程式的版號,即我們常見的1.0、2.0、3.0版等,主要是給使用者了解的版本編號
38
9-3-1 再談AndroidManifest.xml檔案– manifest根元素2
versionCode和versionName屬性在Android Studio專案預設建立的AndroidManifest.xml檔案並看不到,因為是在Gradle Script檔指定,請展開專案結構下方【Gradle Scripts】,開啟第2個Module:app(即app模組)的【build.gradle】,可以看到defaultConfig區塊,如下所示: defaultConfig { applicationId "com.example.joe.ch9_2_1" minSdkVersion 15 targetSdkVersion 24 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" }
39
9-3-1 再談AndroidManifest.xml檔案– uses-sdk元素
uses-sdk元素是用來宣告Android應用程式使用的SDK版本,標籤的常用屬性如下表所示: 屬性 說明 android:minSdkVersion 執行應用程式所需的最低SDK版本,屬性值是Android平台套件的API層級 android:targetSdkVersion 執行應用程式的目標SDK版本,屬性值是Android平台套件的API層級,沒有指明,就是和minSdkVersion屬性相同 android:maxSdkVersion 執行應用程式所需最高SDK版本,屬性值是Android平台套件的API層級
40
9-3-1 再談AndroidManifest.xml檔案– application元素
application元素是宣告Android應用程式擁有的元件,application標籤的常用屬性,如下表所示: 屬性 說明 android:allowBackup 是否允許備份和還原應用程式 android:icon 應用程式顯示的圖示,值是圖形資源索引 android:label 顯示在首頁畫面的捷徑名稱 android:theme 應用程式套用的佈景,值是樣式資源索引
41
9-3-1 再談AndroidManifest.xml檔案– activity元素
在activity元素宣告應用程式擁有的活動,每一個活動都需要宣告一個activity元素,換句話說,application元素擁有1~多個activity元素,標籤的常用屬性如下表所示: 屬性 說明 android:name 活動類別的完整名稱,之前已經指定套件名稱,所以名稱為「.Ch9_3Activity」,再加上套件後就是活動類別的完整類別名稱「android_Examples.ch09.ch9_3.Ch9_3Activity」 android:label 顯示在標題列的名稱
42
9-3-1 再談AndroidManifest.xml檔案– intent-filter元素
intent-filter元素是activity元素的子元素,它是用來定義此活動需要回應哪些意圖的動作,即意圖篩選,換句話說,意圖和意圖篩選如同是鑰匙和鎖,只有正確的鑰匙才能打開門上的鎖。 Android作業系統是將Intent物件包含的訊息和intent-filter元素定義的三種資訊作比較,以便找出可以處理的活動,即action、category和data三個子元素。
43
9-3-1 再談AndroidManifest.xml檔案– use-permission元素
Android平台是使用Linux核心,所以內建有應用程式的權限管理,Andtroid應用程式如果存取私人檔案或資料庫,就不需要任何權限,如果是存取共享或一些敏感資源,我們需要使用<use-permission>標籤來宣告所需的權限,例如:存取Internet,如下所示: <uses-permission android:name="android.permission.INTERNET"/>
44
9-3-2 Android 6.0以上版本的權限管理- 權限種類
正常權限(Normal Permissions):Android 6.0之前版本使用的權限管理,我們需要在AndroidManifest.xml使用<use-permission>標籤宣告權限,當在裝置Google Play下載安裝應用程式時,Google Play會顯示對話方塊要求使用者授予這些權限,簡單的說,正常權限是在安裝時授予的權限。 危險權限(Dangerous Permissions):對於執行Android 6.0以上版本的行動裝置,部分比較危險的權限,除了安裝時需要使用者授予權限,在第一次啟動時,還需要再次要求使用者授權使用,換句話說,危險權限不只安裝時需授予,在第1次啟動時需要再次確認授予來雙重確認,如下圖所示:
45
9-3-2 Android 6.0以上版本的權限管理- checkSelfPermission()方法
Android應用程式如果是在Android 6.0以上版本的裝置執行,而且需要使用危險權限時,我們需要額外撰寫程式碼在執行期請求權限,首先呼叫checkSelfPermission()方法檢查是否已經取得授權,例如:READ_CONTACTS讀取聯絡人權限,如下所示: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { ...... }
46
9-3-2 Android 6.0以上版本的權限管理- requestPermissions()方法
requestPermissions(new String[] { Manifest.permission.READ_CONTACTS }, PERMISSIONS_REQUEST_READ_CONTACTS);
47
9-4 使用意圖啟動內建應用程式 9-4-1 意圖物件和URI 9-4-2 使用意圖啟動內建應用程式
48
9-4-1 意圖物件和URI – 說明 在第9-2節的意圖是明確意圖,其中第9-2-1~9-2-3節使用類別名稱啟動活動,第9-2-4~9-2-5節是在意圖篩選intent-filter元素指定元件名稱來啟動活動,在startActivity()方法參數的Intent物件需要指明目標活動的類別或元件名稱。 基本上,使用意圖啟動內建應用程式都是使用隱含意圖,此時Intent物件提供的目標活動不是明確的類別或元件名稱,而是系統預先定義的一些動作,例如:ACTION_VIEW等。
49
9-4-1 意圖物件和URI – 意圖物件包含的資訊1
動作(Action):一些預先定義的動作類型,例如:ACTION_VIEW,這是使用在隱含意圖。在Intent物件是使用setAction()方法來指定,活動常用的動作類型。 資料(Data):動作操作的資料,例如:聯絡人或資料庫等,它是使用URI(Universal Resource Identifier)字串來指明資料所在的位置,Intent物件是使用setData()方法來指定。 元件名稱(Component Name):目標活動的名稱,如果是明確意圖,就需指明此資訊,Intent物件是使用setClass()或setComponent()方法來指定,一般來說,指定動作就不會同時指定元件名稱。
50
9-4-1 意圖物件和URI – 意圖物件包含的資訊2
目錄分類(Category):提供執行動作所需的一些額外資訊,CATEGORY_LAUNCHER是指位在安裝程式清單的程式;CATEGORY_HOME是首頁畫面,例如:ACTION_MAIN加上CATEGORY_HOME就是回到首頁。 類型(Type):指定動作操作資料的MIME類型,Intent物件是使用setType()方法來指定。
51
9-4-1 意圖物件和URI – URI(Universal Resource Identifier)
萬用資源識別URI可以用來定位Android系統的資源,幫助Intent意圖物件的動作取得或找到操作的資料。Android常用的URI,如下所示: URL網址:URI可以直接使用URL網址,如下所示: 地圖位置:GPS定位的座標值(GeoPoint格式),如下所示: geo: , 電話號碼:指定撥打的電話號碼,如下所示: tel: 寄送郵件:寄送郵件至指定的電子郵件地址,如下所示:
52
9-4-2 使用意圖啟動內建應用程式 – 啟動瀏覽器
在活動啟動內建瀏覽器是建立ACTION_VIEW動作,和URI為URL網址的Intent物件,如下所示: Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(" startActivity(i); Intent類別建構子的第1個參數是動作,第2個參數是Uri物件,我們是呼叫Uri類別的parse()方法將字串剖析成Uri物件。
53
9-4-2 使用意圖啟動內建應用程式 – 啟動地圖 在活動啟動內建Google地圖也是使用ACTION_VIEW動作,URI為GPS座標值,如下所示: Intent i = new Intent(Intent.ACTION_VIEW,Uri.parse( "geo: , ")); startActivity(i);
54
9-4-2 使用意圖啟動內建應用程式 – 打電話 在活動啟動內建撥號程式是使用ACTION_DIAL動作,URI為電話號碼,如下所示:
Intent i = new Intent(Intent.ACTION_DIAL, Uri.parse("tel: ")); startActivity(i);
55
9-4-2 使用意圖啟動內建應用程式 – 選取聯絡人資料
在活動選取聯絡人後,再次建立Intent物件顯示選取聯絡人的詳細資料,首先使用ACTION_PICK動作建立Intent物件,如下所示: Intent i = new Intent(Intent.ACTION_PICK); i.setType(ContactsContract.Contacts.CONTENT_TYPE); startActivityForResult(i, GET_CONTACT); 程式碼使用Intent物件的setType()方法指定MIME型態, CONTENT_TYPE常數字串就是CONTENT_URI,可以提供聯絡人清單來執行選取動作。
56
9-4-2 使用意圖啟動內建應用程式 – Web搜尋
在活動可以啟動內建瀏覽器來執行Web搜尋,它是使用ACTION_WEB_SEARCH動作,如下所示: Intent i = new Intent(Intent.ACTION_WEB_SEARCH); i.putExtra(SearchManager.QUERY, "Android"); startActivity(i); 程式碼沒有URI,而是使用pubExtra()方法在Intent物件附加搜尋關鍵字,第1個參數是SearchManager.QUERY字串常數,第2個參數是關鍵字的字串。
57
9-4-2 使用意圖啟動內建應用程式 – 寄送電子郵件
在活動可以啟動內建電子郵件工具來寄送郵件,它是使用ACTION_SENDTO動作,URI為收件者的電子郵件地址,如下所示: Intent i = new Intent(Intent.ACTION_SENDTO, startActivity(i);
58
9-5 建立多國語系的Android應用程式 Android作業系統本身就支援多國語系,所以,我們建立的Android應用程式也可以支援多國語系,在作法上,我們只需抽出字串至strings.xml檔建立成字串資源,就可以將它翻譯成多國語系的字串資源檔,讓使用介面依作業系統的設定來顯示其他語系的文字內容。 步驟一:抽出字串成為字串資源 步驟二:新增支援多國語系的字串資源 步驟三:切換顯示不同的語系
59
End
Similar presentations