SlideShare une entreprise Scribd logo
1  sur  287
第6節: Android動態UI介面設計
Android動態UI介面設計

  Android動態元件設計
     ListView
     Gallery
     GridView
     ImageSwitch
  Adapter元件
     ArrayAdapter
     SimpleAdapter
     自定Adapter




                      226
進階UI控制元件-Adapter使用
• Android 框架只負責應用程式的流程架構,框架設計師並不會知道最
  終使用框架開發出的Application長的是什麼樣子。
• 應用程式設計師並不能直接去修改Android框架的內容,如此會造成
  相容性問題,因此無法直接透過框架修改來決定應用程式的長相.
• 為解決上述兩個問題,在Android裡設計了Adapter類別來做為
  Android框架與應用程式之間的橋樑


• 為應付各種不同的資料數據來源,與不同的View元件,因此發展出各
  式不同的Adapter元件。




為你把關每一道 學習品質                           227
進階UI控制元件-Adapter使用
                                            Adapter
• 常見的Adapter的類別
                        ListAdapter                     SpinnerAdapter

                                         BaseAdapter


                 ArrayAdapter           CursorAdapter                SimpleAdapter

                                 ResourceCursorAdapter


• 常見Adapter對應到UI端的類別                                     SimpleCursorAdapter
                                    ViewGroup

                                    AdapterView

             AbsListView                                AbsSpinner

      ListView           GridView           Gallery                   Spinner
為你把關每一道 學習品質                                                                         228
進階UI控制元件-Adapter使用

• ArrayAdapter用途
  • 作用為陣列與ListView之間的橋梁
  • 可將陣列中定義的資料逐一的對應到ListView之中顯示
  • 一般ArrayAdapter中顯示的ListView每行通常只有一個TextView

     ArrayList                       ListView
                                      Jarey
       Jarey
                                      TextView-Two
       John
                                      John
                   ArrayAdapter
       May                            TextView-Two

       Ken                            May
                                      TextView-Two

                                      Ken
                                      TextView-Two

為你把關每一道 學習品質                                         229
進階UI控制元件-Adapter使用

• SimpleAdapter用途
  • simpleAdapter可以定製每一列ListView中要顯示的內容
  • 一般ListView中每一列的版面配置(Layout)會撰寫在XML檔中,在
    由SimpleAdapter負責將內容(Data)填入Layout中的元件(View)。

    ArrayList                        ListView

   HashMap                            Jarey
                                      09222222
  Name    Jarey
                                      John
  Phone   0922      SimpleAdapter
                                      09333333

   HashMap                            May
                                      09444444
  Name    John
  Phone   0933                        Ken
                                      095555555

為你把關每一道 學習品質                                       230
進階UI控制元件-Adapter使用
• 建構式ArrayAdapter (Context context, int resource, int textViewResourceId, T[]
   objects)
    •   contex:要顯示的Context容器
    •   resource:layout定義,可以使用Android系統內建,或是自定layout.
    •   textViewResourceId:位於layout中的textView,用來顯示data內容.
    •   data:要顯示的資料內容


• 建構式SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int
   resource, String[] from, int[] to)
    •   contex:要顯示的Context容器
    •   data:基於Map的List. Map中包含了ListView每一列所需要的資料
    •   resource:顯示的Layout版型,此layout中至少要包含在to參數中所出現的
        View。可使系統提供的layout,亦可自行定義
    •   from:名稱陣列,每一個名稝都對應Data中的索引鍵。
    •   to:為TextView類形的陣列,必須要在layout中可以被索引到。

為你把關每一道 學習品質                                                                    231
範例練習
           範例專案名: ex05_01_Spinner

  練習目標:
   學習使用Spinner,利用ArrayAdapter提供
    Spinner內容。
  程式撰寫
   建置Spinner元件,其內容資料於XML中利用
    string array xml標籤編寫內容。
   於Activity中讀入string array內容至記憶體,並套
    用ArrayAdapter提供資料給Spiiner元件。
  操作練習
   模擬器練習,分練習XML方式導入靜態資料,與
    使用Adapter方式動態載入資料兩種應用方式。

為你把關每一道 學習品質                            232
進階UI控制元件-ListView

• ListView為Android中用來顯示大量資
  料的一個很重要的UI介面
• 由於手機受限於螢幕大小,當欲顯示
  的資料數量超過一個頁面可以顯示時,
  就可以利用ListView來做資料顯示
• ListView需搭配Adapter使用,
  ListView會自動依顯示控制的需求透
  過Adapter介面取得資料。

• ListView提供OnItemClickListener()
  方法,可以取得用戶的動件事件(例
  如點選了那一個ListView元件)



為你把關每一道 學習品質                        233
進階UI控制元件-ListView

• ListView使用方式
   • set data source to Adapter
   • get ListView from R.layout
   • set adapter to ListView
   • set click listener for each list item

• ListView Event處理函式
   • onItemClick(AdapterView<?> parent, View view, int position, long id)
   • onItemLongClick(AdapterView<?> parent, View view, int position, long id)
   • onItemSelected(AdapterView<?> parent, View view, int position, long id)




為你把關每一道 學習品質                                                                234
範例練習
           範例專案名: ex05_02_Adapter

  練習目標:
   了解各式adapter的使用
   了解ListView與adapter之間的關係與運作
    流程
  程式撰寫
   設計一ListView元件,並練習接上各式不
    同的adapter與不同的資料來源串接
   SimpleAdapter, ArrayAdapter
  操作練習
   透過模擬器操作不同的Activity,每一個
    Activity代表一個不同Adapter的連接範例。
為你把關每一道 學習品質                        235
進階UI控制元件-ListActivity

• ListActivity使用時機
  • 當一個Activity中只有顯示ListView,而且此ListView又會填滿整
    個螢幕,此時可以直接使用ListActivity來代替Activity。
  • ListActivity為一個包含了ListView的Activity,以wrapper的方式將
    ListVIew包裝起來,方便更容易與直接的控制。

• ListActivity 預設ID元件
   • ListActivity使用的layout檔中必須定義一個ListView,且此
      ListView的id必須固定為[ @id/android:list ]

  • 另外可定義一個TextView當ListView裡沒有資料時可以顯示,此
    TextView的id必須固定為[ @id/android:empty]




為你把關每一道 學習品質                                           236
進階UI控制元件-ListView

• ListActivity使用方式
   • Application extended ListActivity
   • set data source to Adapter
   • get ListView from ListActivity
   • set adapter to ListView
   • set click listener for each list item

• ListView Event處理函式
   • 在ListActivity中不用註冊Listener,而是直接以覆寫
      (Override)來進行事件處理
   • 可處理的Event函式與ListView相同

為你把關每一道 學習品質                                 237
範例練習
          範例專案名: ex05_03_ListActivity

  練習目標:
   了解ListActivity的應用
  程式撰寫
   修改前一隻範例程式,試著將其改寫成
    ListActivity
   Activity直接繼承自ListActivity
  操作練習
   透過模擬器操作,注意ListActivity與ListView在對
    於listener event 處理的寫法是否有所不同?


為你把關每一道 學習品質                            238
進階UI控制元件-Adapter使用
• 自行定義Adapter內容
  • 繼承(extended)BaseAdapter
  • 於建構式接收要處理的資料(Data)來源
  • 覆寫(Override)以下四個Method
     •   public int getCount() ;
          •   傳回Data的數量.(ListView的列數)
     •   public Object getItem(int position);
          •   傳回指定的Data元件.
     •   public long getItemId(int position);
          •   傳回Data的識別ID
     •   public View getView(int position, View convertView, ViewGroup
         parent)
          •   傳回Layout與Data組合後的View元件(顯示於畫面上)
  • ※當Data內容有變更時,必須呼叫notifyDataSetChanged才會更新
    ListView中的內容。
                                                                         239
為你把關每一道 學習品質
進階UI控制元件-Adapter使用
• Adapter與Android框架運作流程

Android
                 Activity                AdapterView                   Adapter
 框架


                                                        3.getCount()        4.getView()
Application         2.setContentView()

          1.onCreate()
                                           Map                    MyAdapter
                ListActivity
                                 Array             Data

                                                               Layout
                                    Cursor                                       View

                                                       XML
為你把關每一道 學習品質                                                                            240
範例練習
         範例專案名: ex05_04_ImageAdapter

  練習目標:
   了解如何自行擴充Adapter類別
   學習如何以高效率,最佳化記憶體方式設計
    Adapter
  程式撰寫
   設計一個ImageAdapter類別,繼承至BaseAdapter
    抽像類別
   實作BaseAdapter的四個抽像函式
   利用系統快取與ViewHolder提高Adapter的效能
  操作練習
   透過模擬器操作
為你把關每一道 學習品質                            241
進階UI控制元件-ListView資料快取問題

• ListView為了節省記憶體與提高顯示的效能,會利用快取
 機制,在ListView滑動時會重覆利用己使用過,目前不在
 畫面上的View元件。

               ConvertView


               ConvertView

    重覆利用
               ConvertView   由下往上滑動

               ConvertView


               ConvertView
為你把關每一道 學習品質                          242
進階UI控制元件-ListView內元件如何監聽事件

• ListView本身可以透過註冊setOnItemSelectListener來監
 聽用戶點擊了那一條List Item。

• 若希望能為List Item中的每一個View元件單獨的設置
 Listener事件,那麼需要注意以下二個問題:

  • ListView本身具有快取,List Item是重覆利用的,這將
    導致用戶滑動List後,所點擊的元件可能與你當初註冊
    的Listener元件不一致(如點了第5個Item中的一個
    Button,但實際上第5個Item等同於重覆利用的第1個
    Item)
為你把關每一道 學習品質
                                    243
進階UI控制元件-ListView內元件如何監聽事件

  • 由於Item元件是重覆利用,因此你將無法判斷用戶點
    擊的Button為第幾個Item選項的Button,同時若你在每
    次getView時都為新的Item重新設置新的Listener那麼
    將會造成記憶體大量的浪費,同時也會降低顯示的效
    能。



    重覆利用

                      點擊第4個Item內的checkbox,
                      但呼叫的listener將與第1個
                      item相同。
為你把關每一道 學習品質
                                  244
進階UI控制元件-ListView內元件如何監聽事件

• 解決LIstView 內Item元件的監聽事件的方法,可以透過
  View.setTag方式,為將該List   Item的資料快取在要被監
  聽的View元件身上。如此當用戶點擊了CheckBox後,可
  以在透過getTag的方式取得該List Item的資料做為判斷。
                                            List Data Set
                          setTag(Object);
                                                Profile1

                                                Profile2
   重覆利用
                                                Profile3

                                                Profile4



為你把關每一道 學習品質
                                                245
進階UI控制元件-ListView資料快取問題

• 重覆使用的View元件會造成顯示不一致的問題,由其是當
 View元件中有使用到如CheckBox這類的選單元件。

                  雖然只勾了一個選項。但往
                  上滑動時會造成第五個選項
                  看起來也是被勾選的


  重覆利用
                    由下往上滑動




為你把關每一道 學習品質                     246
進階UI控制元件-ListView資料快取問題

• 解決View元件顯示不一致的狀況,必須將ListView中每一
 條的UI狀態記錄起來,在每次呼叫getView時去重新設定
 UI狀態。                        List Data狀態表

                                     勾選

                     由下往上滑動          未勾選

重覆利用                                 未勾選

                                     未勾選

                                     未勾選

                   在準備顯示到畫面上前,重新將
                   View元件上的UI狀態做更新,將
                   勾選取消掉。
為你把關每一道 學習品質
                               247
範例練習
         範例專案名: ex05_04_ImageAdapter

  練習目標:
   直接修改ImageAdapter範例,加入刪除模式功能
   於刪除模式下顯示CheckBox元件提供用戶勾選。
  程式撰寫
   建置ListData 狀態表記錄每個ListView中每個元件的UI
    狀態。
   將ListView中的Layout所有的元件forcues狀能設為false
    以避免遮避到ListView本身的onItemSelect事件。
   註冊CheckBox的Onclick事件,並將狀態資料帶入至
    Tag中提供供識別所點選的元件。
  操作練習
   透過模擬器操作

為你把關每一道 學習品質                                 248
進階UI控制元件-ImageSwitch&Gallery

• ImageSwitch                  ViewGroup


   • 主要用來做圖片切換與自動播放用.          AdapterView

     可支援不同的進場與退場動畫特效
                               AbsSpinner


• Gallery                        Gallery

  • 提供一個拖拉式圖片瀏覽與選擇介面
  • 僅支援水平擺設方式
  • 通常搭配ImageSwitch可用來做成簡
     易的圖片瀏覽器。




為你把關每一道 學習品質                                 249
進階UI控制元件-ImageSwitch&Gallery

• ImageSwitch元件
   • XML宣告方式



  • 程式碼使用方式
       功能                                程式碼
 package     Import android.widget.ImageSwitch;
 Reference   ImageSwitch sw1 = (ImageSwitch) findViewById(R.id.imsw1);
 set         sw1.setFactory(ViewSwitch.ViewFactory factory)
             sw1.setInAnimation(Animation inAnimation)
             sw1.setOutAnimation(Animation outAnimation)
             sw1.setImageResource (int resid)


為你把關每一道 學習品質                                                             250
進階UI控制元件-ImageSwitch&Gallery

• Gallery元件
  • XML宣告方式




  • 程式碼使用方式
               功能                              程式碼
   package          Import android.widget.Gallery;
   Reference        Gallery gal1 = (Gallery) findViewById(R.id.gallery);
   set              gal1.setAdapter(SpinnerAdapter adapter);
   Call back        gal1.setOnItemSelectedListener(AdapterView.OnItemSelect
                    edListener listener);

為你把關每一道 學習品質                                                               251
範例練習
           範例專案名: ex05_05_Gallery

  練習目標:
   透過Gallery與ImageSwitch設計一個簡易的相片
    瀏覽器
   復習先前教過的Adapter的應用
  程式撰寫
   撰寫一個Activity包含ImageSwitch與Gallery元件。
   撰寫一個ImageAdapter提供給Gallery。
  操作練習
   透過模擬器操作

為你把關每一道 學習品質                               252
進階UI控制元件-GridView


• GridView為網格檢視元件,可以將很很多圖片以         ViewGroup

  固定的大小排列顯示在畫面上可用來做為相簿與圖
  片瀏覽等應用                            AdapterView


• GridView的資料取至於ListAdapter,一般要用做
                                    AbsListView
  相簿使用需要自行實作ImageAdapter(繼承至
  BaseAdapter).                      GridView




為你把關每一道 學習品質                                      253
進階UI控制元件-GridView

• GridView元件
  • XML宣告方式




  • 程式碼使用方式
              功能                            程式碼
  package          Import android.widget.GridView;
  Reference        GridView grid= (GridView ) findViewById(R.id.grid);
  set              grid.setAdapter(BaseAdapter adapter);
  Call back        grid.setOnItemSelectedListener(AdapterView.OnItemSele
                   ctedListener listener);
為你把關每一道 學習品質                                                             254
第7節: Android 通知元件設計
  Android Widget開發
Android 通知元件設計

  Android Menu元件設計
     Option Menu
     Context Menu
  Android通知元件設計
     Dialog
     Toast
     Notification
     Menu
  AppWidget桌面元件設計
     Widget開發上的限制
     Remove View的互動方式



                         256
進階UI控制元件-Menu選單

• Menu選單操作元件
  • Option Menu
    • 按下menu建後顯
      示
  • Context Menu
    • 長時間按下一個視
      窗後顯示
  • Submenu
    • 子選單,可被
      option或context
      Menu所呼叫

為你把關每一道 學習品質           257
進階UI控制元件-Option Menu

• Option Menu
  • 選單位於整體畫面的下方,透過按下手機上的
    Menu按鈕顯示
  • 一個畫面最多可以安置6個選單項目,不支援
    Checkbox及RadioButton
  • 超過6個選單的項目將會以擴充列的方式顯示。
• Option Menu 使用XML宣告




為你把關每一道 學習品質            258
進階UI控制元件-Option Menu

• Inflating Option Menu Resource File
   • 透過MenuInflater.inflate() 協助載入xml資源檔
       • public void inflate (int menuRes, Menu menu)
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
      MenuInflater inflater = getMenuInflater();
      inflater.inflate(R.menu.game_menu, menu);
      return true;
    }




為你把關每一道 學習品質                                            259
進階UI控制元件-Option Menu

• 建立Option Menu 使用MenuItem add函式
   Public boolean onCreateOptionsMenu(Menu menu){
     menu.add(0,MENU_ITEM_ID1, 0 “ MENU_ITEM_1”);
     menu.add(0,MENU_ITEM_ID2, 0 “ MENU_ITEM_2”);
     return true;
   }

• MenuItem add函式
  • public abstract MenuItem add (int groupId, int
    itemId, int order, int titleRes)
     • groupid:群組ID
     • itemid:項目ID
     • order:排序方式
     • titleRes:每一個Item上的標題
為你把關每一道 學習品質                                         260
進階UI控制元件-Option Menu

• 建立Menu




• Call Back
  Function




為你把關每一道 學習品質           261
進階UI控制元件-Context Menu

• Context Menu
  • 與在PC上的滑鼠右鍵功能類似,當按位某一
    個View 2秒鐘,就會出現一個浮動式的
    Context Menu。
  • 較常使用在ListView上。
• 建立Option Menu 使用MenuItem add函式




為你把關每一道 學習品質                       262
進階UI控制元件-Context Menu

• Context Menu的callback函式




為你把關每一道 學習品質                263
進階UI控制元件-Submenu

• Submenu
  • Context Menu與Option Menu可以在內嵌一個
    子選單(Submenu)做為擴充。
  • 子選單(Submenu)不能在擴充子選單
• 建立Submenu 使用xml




為你把關每一道 學習品質                          264
進階UI控制元件-Submenu

 • 建立Submenu 使用SubMenu addSubMenu函式
 @Override
public boolean onCreateOptionsMenu(Menu menu) {
  super.onCreateOptionsMenu(menu);
  SubMenu fileMenu = menu.addSubMenu(GALLERY, SUBMANU01, Menu.NONE, "File");
  SubMenu editMenu = menu.addSubMenu(GALLERY, SUBMANU02, Menu.NONE, "Edit");
  fileMenu.add(GALLERY, MANU01, Menu.NONE, "new");
  fileMenu.add(GALLERY, MANU02, Menu.NONE, "open");
  fileMenu.add(GALLERY, MANU03, Menu.NONE, "save");
  editMenu.add(GALLERY, MANU04, Menu.NONE, "undo");
  editMenu.add(GALLERY, MANU05, Menu.NONE, "redo");
  return true;
}




 為你把關每一道 學習品質                                                                  265
進階UI控制元件-Submenu

      • 處理Callback函式
@Override
 public boolean onOptionsItemSelected(MenuItem item) {
       switch (item.getItemId()) {
            case MANU01:
            case MANU02:
            case MANU03:
            case MANU04:
            case MANU05:
            String itemid = Integer.toString(item.getItemId());
            String title = item.getTitle().toString();
            showAlertDialog("項目ID = " + itemid + "n" +
            "標題 = " + title);
            return true;
       }
       return super.onOptionsItemSelected(item);
 }




 為你把關每一道 學習品質                                                     266
範例練習
        範例專案名: ex06_01_01_OptionsMenu
            ex06_01_02_ContextMenu
             ex06_01_03_Submenu
  練習目標:
   學習各種Menu的應用場合與撰寫方式
  程式撰寫
   透過覆寫onCreateOptionsMenu函式來加入
    Menu選單
   透過覆寫onOptionsItemSelected來接收使用者的
    選擇
  操作練習
   透過模擬器操作,透過按下手機上的Menu鍵來
    呼叫出Menu選單。

為你把關每一道 學習品質                            267
Android通知元件-Notifications
• Android提供三種不同的通知元件
   • Toast
      • 短暫警示與通知,顯示數秒後會
        自動消失                      Toast Notification

   • Dialog
      • 對話窗可與使用者做簡單交談式
        互動,一般用來做進度提示或確
        認使用者的需求。                  Dialog Notification

   • Status Bar Notification
      • 位於訊息列,訊息會長註於狀態
        列,點擊後可啟動Activity。一般
        Services會透過此通知用戶有事件
        發生需返回Activity處理        Status Bar Notification
                                                         268
為你把關每一道 學習品質
Android通知元件-Dialog元件
• Dialog是一切對話框基本類別,並非繼承於View類別.
• Dialog也具有生命週期,其生命週期由Activity來誰護。

• 開發者可主動呼叫的函式                                       Activity

  • showDialog(int id)                        showDialog(int id)
  • dismissDialog(int id)        Andr
                                  oid        onCreateDialog(int id)
                                 框架
                                             onPreparDialog(int id,
                                                Dialog dialog)
• 框架控制Dialog生命週期函式
  • onCreateDialog(int id)
  • onPrepareDialog(int id, Dialog dialog)

                                                                      269
 為你把關每一道 學習品質
Android通知元件-Dialog元件
• Dialog於Activity中的建立流程
  • Step1: 呼叫Activity的showDialog(id)
            Button1.setOnClickListener(new OnClickListener(){
                     public void on click(View v){
                               showDialog(DIALOG1);
                     }
            }
            );

  • Step2: 覆寫(override)onCreateDialog(int id)函式
            Protected Dialog onCreateDialog(int id){
                 switch(id){
                      Case DIALOG1:
                      return buildDialog1(this);
                 }
                 return null;
            }
                                                                270
為你把關每一道 學習品質
Android通知元件-Dialog元件
 • Step3:建立需要的Dialog類別,將其返return回
         Android框架
     Private Dialog buildDialog1(Context context){
           AlertDialog.Builder builder = new AlertDialog.Builder(context);
           builder.setIcon(R.drawable.alert_dialog_icon);
           builder.setTitle(R.string.alert_dialog_two_buttons_title);
           builder.setPositiveButton(R.string.alert_dialog_ok,new
                 DialogInterface.OnClickListener(){
                 public void onClick(DialogInterface dialog, int whichButton){
                             setTitle(“確認鈕”);
                 }
                 });
           return builder.create();
     }

 • Step4:覆寫onPrepareDialog(int id, Dialog dialog)
      protected void onPrepareDialog (int id, Dialog dialog, Bundle args){
               return dialog;
      }
                                                                                 271
為你把關每一道 學習品質
Android通知元件-Dialog元件
• AlertDialog
   • AlertDialog是Dialog的子類別,為最常使用的對話框
   • 一個AlertDialog可以有二個至三個按鈕
   • 不能直接以建構函式來產生AlertDialog物件,必須透過
     AlertDialog.Builder來建構。
private Dialog buildDialog2(Context context) {
      AlertDialog.Builder builder = new AlertDialog.Builder(context);
      builder.setIcon(R.drawable.alert_dialog_icon);
      builder.setTitle(R.string.alert_dialog_two_buttons_msg);
      builder.setMessage(R.string.alert_dialog_two_buttons2_msg);
      builder.setPositiveButton(R.string.alert_dialog_ok,
             new DialogInterface.OnClickListener() {
             public void onClick(DialogInterface dialog, int whichButton) {
                    setTitle("點選了對話框上的確定按鈕");
             }});
      builder.setNeutralButton(略.同上);
      builder.setNegativeButton(略,同上;
      return builder.create();
}
                                                                              272
為你把關每一道 學習品質
Android通知元件-Dialog元件

• 具有View元件的對話框
private Dialog buildDialog3(Context context) {
      LayoutInflater inflater = LayoutInflater.from(this);
      final View textEntryView = inflater.inflate(
      R.layout.alert_dialog_text_entry, null);
                       略
     AlertDialog.Builder builder = new AlertDialog.Builder(context);
     builder.setView(textEntryView);
     builder.setPositiveButton(R.string.alert_dialog_ok,
     new DialogInterface.OnClickListener() {
     public void onClick(DialogInterface dialog, int whichButton) {
           setTitle("點選了對話框上的確定按鈕:"
           + ((TextView) textEntryView.findViewById(R.id.username_edit)).getText());
     }});
     builder.setNegativeButton(略…….);
     return builder.create();
}




為你把關每一道 學習品質                                                                           273
Android通知元件-Dialog元件

• 進度對話框
private Dialog buildDialog4(Context context) {
      ProgressDialog dialog = new ProgressDialog(context);
      dialog.setTitle("正在下載歌曲");
      dialog.setMessage("請稍候……-");
      return dialog;
}




為你把關每一道 學習品質                                                 274
範例練習
               範例專案名: ex06_02_Dialog

  練習目標:
   學習操作Android各種不同的Dialog對話視窗
   學習如何將Dialog改成可以自定Layout元件
    的對訊窗
  程式撰寫
   覆寫onCreateDialog函式,負責管理Activity
    中呼叫的Dialog.
   透過AlertDialog.Builder建立Dialog物件
  操作練習
   透過模擬器操作。


為你把關每一道 學習品質                           275
Android通知元件-Notification

• Notification通知元件
  • 不會打斷目前使用者的操作,訊息會長註於訊
    息列中,待用戶有空時在進行處理,並可直接
    啟動對應的Activity.
  • Notification可加入振動或聲音通知,以加強引
    起用戶的注意。




為你把關每一道 學習品質                      276
Android通知元件-Notification

• 如何撰寫Notification事件
  • Step1:取得NotificationManager管理元件
             mNotificationManager = (NotificationManager)
                        getSystemService(NOTIFICATION_SERVICE);


  • Step2:建構Notification物件
       •   第一個參數:要顯示的圖片ID
       •   第二個參數:要顯示的文字
       •   第三個參數:顯示的時間,System.currentTimeMillis()代表立
           即顯示

            Notification notification = new Notification(drawable,
            tickerText,System.currentTimeMillis());




為你把關每一道 學習品質                                                         277
Android通知元件-Notification

  • Step3:決定Notification如何呈現與處理事件
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
        new Intent(this, ActivityMain.class), 0);

    •   Context:作用於那一個Activity的Context
    •   requestCode:目前無使用到
    •   Intent:要被啟動的Activity Intent
    •   Flags: 細部的Intent操作控制,如 FLAG_CANCEL_CURRENT
        notification.setLatestEventInfo(this, title, content, contentIntent);


  • Step4:設定Notification預設的表現形式
    •   Notification.DEFAULT_VIBRATE 振動
    •   Notification.DEFAULT_SOUND 聲音
    •   Notification.DEFAULT_ALL 聲音+振動
    •   需加入權限才能使用振動功能:Android.permission.VIBRATE
        notification.defaults = Notification.DEFAULT_ALL;
        mNotificationManager.notify(NOTIFICATIONS_ID, notification);
為你把關每一道 學習品質                                                                    278
Android通知元件-Notification

• Notification通知更新
   • 透過notify()函式來更新通知,可以避免一直不斷產生新的
     Notify訊息通知而導致塞滿了用戶的通知視窗
  mNotificationManager.notify(NOTIFICATIONS_ID, notification);

• 加入自定音效
  • 系統預設音效
     • notification.defaults |= Notification.DEFAULT_SOUND;
  • 讀取SD卡的mp3
     • notification.sound =Uri.parse("file:///sdcard/notification/test.mp3");
  • 從MediaStore的ContentProvider取得
     • notification.sound =
       Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6");
為你把關每一道 學習品質                                                              279
Android通知元件-Notification

• Notification相關FLAG設定
  • FLAG_AUTO_CANCEL:
     • 用戶點了該通知後,系統便會自動清除該訊息
  • FLAG_INSISTENT:
     • 重複發出響聲,直到使用者點選該訊息
  • FLAG_ONGOING_EVENT:
     • 將該訊息放置放”進行中”群組,一般用來代表背景
       Service還有在運行中。
  • FLAG_NO_CLEAR:
     • 使用者就算點選了清除訊息,系統也不會把該訊息清
       除,必須待應用程式自己發出清除的指令。

為你把關每一道 學習品質                 280
Android通知元件-Notification

 • 自定Notification顯示UI元件
    • Step1: 利用RemoveView定義元件內容
RemoteViews contentView = new RemoteViews(getPackageName(),
R.layout.custom_notification_layout);

contentView.setImageViewResource(R.id.imageIcon,
R.drawable.notification_image);

contentView.setTextViewText(R.id.textView, "Hello Notify");

notification.contentView = contentView;


 為你把關每一道 學習品質                                                 281
Android通知元件-Notification

• Step2: 發出通知訊息
   • 使用contentIntent設置pendingIntent元件

Intent notificationIntent = new Intent(this, MyClass.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
notification.contentIntent = contentIntent;
mNotificationManager.notify(0, notification);




為你把關每一道 學習品質                                                       282
Android通知元件-Notification

• Notification相關FLAG設定
  • FLAG_AUTO_CANCEL:
     • 用戶點了該通知後,系統便會自動清除該訊息
  • FLAG_INSISTENT:
     • 重複發出響聲,直到使用者點選該訊息
  • FLAG_ONGOING_EVENT:
     • 將該訊息放置放”進行中”群組,一般用來代表背景
       Service還有在運行中。
  • FLAG_NO_CLEAR:
     • 使用者就算點選了清除訊息,系統也不會把該訊息清
       除,必須待應用程式自己發出清除的指令。

為你把關每一道 學習品質                 283
Android通知元件-Tost通知元件

• Tost通知元件
   • 為一個短暫提示元件,Toast會直接顯示於螢
     幕下方.
   • Tost內容可以直接為描述一串文字,也可以帶
     入View元件。
   • Toast的顯示時間長度分為長與短兩種
      • Toast.LENGTH_LONG
      • Toast.LENGTH_SHORT



為你把關每一道 學習品質                  284
Android通知元件-Tost通知元件

• 如何撰寫Tost通知
  • Step1:實體化Toast物件
           Toast toast = new Toast(this);

  • Step2:設定Toast內容
    • setText(CharSequence s)
    • setView(View view)
           LayoutInflater vi = (LayoutInflater)
           getSystemService(Context.LAYOUT_INFLATER_SERVICE);
           View view = vi.inflate(R.layout.toast,null);
           TextView tv = (TextView) view.findViewById(R.id.content);
           tv.setText("加入艾鍗,迅速提昇你的開發能力");
           toast.setView(view);
  • Step3:設定顯示時間
           toast.setDuration(Toast.LENGTH_SHORT);
           toast.show();

為你把關每一道 學習品質                                                           285
範例練習
        範例專案名: ex06_03_Toast_and_Notification

  練習目標:
   學習如何建立Notification與Toast通知事件
  程式撰寫
     透過getSystemService(NOTIFICATION_SERVICE)取得
      NotificationManager物件
     建立PendingIntent物件,供用戶執選通知後返回Activity
     透過notification.defaults決定通知時是否要加振動與音效
     建立Toast物件,並傳送一簡單字串於畫面上
  操作練習
   透過模擬器練習,練習時可注意畫面的最上頂狀態列
    收到Notification時的程現與執行後的處理方式

為你把關每一道 學習品質                                       286
Android Widget開發

   Widget程式開發
      開發上的限制
      Widget組成方式
      如何設置組態設定Activity
   Remove View的互動方式




                          287
Android Widget程式開發

• APP Widget為Android 1.5之後所提
  供的功能。提供於Android桌面程式
  (Home Screen)上安置各式各樣的
  常註程式,例如小時鐘、Google
  Search...



• 常註程式新增方式
  • 在主畫面上按下觸控面版約2秒,
    即會彈出Add to Home Screen
    選單,選擇Widget後即會顯現
    目前系統所安裝的各式Widget



為你把關每一道 學習品質                   288
Android Widget程式開發-使用限制

• Android Widget可以使用的功能
   • 可加載於主畫面(Home Screen)
   • 同一個常駐程式可以多次啟動
   • 常註程式啟動時不會採用全畫面(Full Screen)
• Android Widget中不能使用的功能
   • Event的呼叫。
   • 有限的Layout使用,有限的GUI元件使用。
   • 可使用的Layout類別:
      • Frame Layout
      • Linear Layout
      • Relative Layout
   • 可使用的GUI元件
      • AnalogClock     ImageButton
      • Button       ProgressBar
      • Chronometer      TextView


為你把關每一道 學習品質                          289
Android Widget程式開發-使用限制

• Android系統對Widget程式的處理方式會有所限制,
  Widget可以處理的方式選擇
       處理方式              說明
   指定執行間隔時間    於widget的資訊檔中設置定期執行的時間週期
   指定執行時間      於Widget的資訊檔裡設定執行的時間
   按下按鈕後才執行    常GUI介面被用戶按下時才執行

• Widget由於長駐於主畫面,且會不定時在背景運作,
  因此設計時要特別注意評估電池與處理器的消耗狀況。

• Widget與Activity還有Services一般,皆有其獨自的生
  命週期



為你把關每一道 學習品質                             290
Android Widget程式開發-生命週期

• Widget生命週期

       開始
                  onDelete()

    onEnabled()
                  onDisabled()

    onUpdate()

                  App Widget
      執行中            關閉




為你把關每一道 學習品質                     291
Android Widget程式開發-組成結構

    • Android Widget應用程式組成結構
                                   BroadcastReceiver                           AppWidgetManaget


                                   AppWidgetProvider
   實作生命週期函式                                                    廣播呼叫
  onEnable,onUpdate,
                                                               APPWIDGET_UPDATE
  onUpdate,onDelete
  d,
                               myAppWidgetProvider
  onDisabled


Android應用程式設定檔                       Metadata設定           Widget資訊設定檔            Layout畫面布局檔
    AndroidManifest.xml              Name:名稱需為            Appwidget_info.xml      Layout_sample.xml
                                     android.appwidget.
建立BroadcastReceiver                  provider              定義Layout布局            有限的layout元件使用
<action>欄位需明確定義為                                           畫面大小:74倍數-2
android.appwidget.action.APPWIDG                                                 有限的GUI元件使用
                                     Resource:指定           執行時間週期設定
ET_UPDATE
                                     information檔的來
                                     源
    為你把關每一道 學習品質                                                                                  292
Android Widget資料更新

• AppWidget主要是依建置在Home Launcher APP之上,
  因此Widget畫面的更新與Event互動皆必須透過一個
  Proxy來代為處理,而此Proxy就是AppWidgetManager
  元件。
• 所有待更新的Widget元件,皆必須透過RemoteViews
  元件封裝,所有的互動事件則必須透過pending Intent
  註冊於RemoteViews中。                 Home Launcher
• AppWidget元件updateAppWidget函式協助將
  RemoteViews更新於Widget元件上。            Widget
setTextViewText   setImageViewResource   AppWidget
                                          Manager
        setOnClickPendingIntent

           RemoteViews

為你把關每一道 學習品質                                         293
範例練習
          範例專案名: ex06_04_MyWidget

  練習目標:
   了解如何建置Widget元件
   學習如何為Widget加入listener與更新UI
  程式撰寫
   實作一個Widget 的receiver元件,並實作組態設定
    Activity,Widget啟動前會現顯示Activity應用程式。
   撰寫Appwidget_info.xml檔,決定Widget顯示方式
   撰寫Layout_sample.xml,決定Widget顯示的UI樣式。
   撰寫RemoteView更新函式,取得Widget觸發事件,
    並依事件狀態更新WidgetUI
  操作練習
   透過模擬器操作
為你把關每一道 學習品質                               294
Android Widget程式開發-組態設定Activity

• AppWidget組態設定Activity
  • 當用戶新增一個Widget時,系統可以呼叫一個組態設定
    Activity,提供用戶對該Widgegt進行設定,如改變顏色,顯示
    大小,執行週期..等等資訊。

• 如何為AppWidget配置組態設定Activity
  • AndroidManifest.xml中定義Activity,<action>需定義為:
    ACTION_APPWIDGET_CONFIGURE
     <activity android:name="myAppWidgetConfigure">
     <intent-filter>
     <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
     </intent-filter>
     </activity>
  • 於appwidget_info.xml中指定要呼叫的Activity
     <appwidget-provider
     ....
     android:configure= " com.example.android.appwidget.myAppwidgetConfigures"
     />
為你把關每一道 學習品質                                                                     295
Android Widget程式開發-組態設定Activity

• AppWidget呼叫組態設定Activity時注意事項
  • AppWidget呼叫執行Activity後,此Activity必須要返回一個結果,
    而此結果必須要包含Widget ID(存在EXTRA_APPWIDGET_ID)
  • Activity被建立時,AppWidget中的onUpdate方法將不會被呼叫
    到,因此Activity完成組態設定後一定要負責更新AppWidget程式
    (可以透過請求AppWIdgetManager協助更新)

• 組態設定Activity實作方式
  • Step1:透過Intent取得AppWidget ID

     final Bundle extras = getIntent().getExtras();
     If(extras != null){
           int mAppWidgetId = extras.getInt(
                   AppWidgetManager.EXTRA_APPWIDGET_ID,
                   AppWidgetManager.INVALID_APPWIDGET_ID);
     }


為你把關每一道 學習品質                                                 296
Android Widget程式開發-組態設定Activity

• Step2:執行組態設定,等待用戶設定操作
• Step3:設定完成後,更新AppWidget UI畫面
       AppWidgetManager appWidgetManager =
       AppWidgetManager.getInstance(LifeCycleConfigure.this);
       RemoteViews views = new RemoteViews(getPackageName(), R.layout.life_cycle);
       appWidgetManager.updateAppWidget(mAppWidgetId, views);




• Step4:最後建立一個Intent返回結果,並結束Activity
       Intent resultValue = new Intent();
       resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
       mAppWidgetId);
       setResult(RESULT_OK, resultValue);
       finish();




為你把關每一道 學習品質                                                                         297
範例練習
          範例專案名: ex06_05_Appwidget

  練習目標:
   了解桌面Widget應用程式的撰寫方式與生命流程
   學習如何為Widget加入組態設定用Activity
  程式撰寫
   實作一個Widget 的receiver元件,並實作組態設定
    Activity,Widget啟動前會現顯示Activity應用程式。
   撰寫Appwidget_info.xml檔,決定Widget顯示方式
   撰寫Layout_sample.xml,決定Widget顯示的UI樣式。
  操作練習
   透過模擬器操作

為你把關每一道 學習品質                               298
第8節: Broadcast Receiver元件
       Services元件
Broadcast Receiver與Service元件

  BroadCastReceiver元件
     廣播的用途與種類
     如何發送廣播封包
     如何註冊接收廣播封包
     廣播封包加入自定權限
  Services 元件應用
     Local 與 Remote Services
     Services生命週期
     如何與Services進行溝通
     Remote Services設計實作
     如何與RemoteServices溝通
     Services與Activity通訊架構
      設計

                                300
BroadCast Receiver元件

• 廣播接收程式可用來接收其他應用程式所發出的訊息。
• 許多的廣播通知訊息都是來自於Android作業系統
  • 電池電量快用盡
  • 網路連線變化
  • 有來電或簡訊通知

• 應用程式本身也可以發出廣播訊息,可做為與其他應用程
  式互動溝通的管道。
  • 需注意的是廣播訊息是公開的,任何應用程式都可以
    透過註冊BraodCast Receiver來接收到你所廣播的訊
    息。

• 一般常用來做為Services應用程式與Activity應用程式溝通
  使用。

為你把關每一道 學習品質                           301
BroadCast Receiver元件

• 如何發送廣播
  • 在程式中透過Intent建立好希望被那些action filter所接
    收,接著透過sendBroadcast函式發送出去。
     public static final String NEW_BROADCAST=
     " com.ittraining.action.NEW_BROADCAST ";

     Intent intent = new Intent(NEWO_BROADCAST);
     intent.putExtra(" data1",someData);
     intent.putExtra(" data2",someData);
     sendBroadcast(intent);




為你把關每一道 學習品質                                       302
BroadCast Receiver元件
• 如何接收廣播
   • 想接收並且處理廣播的Intent,就必需要註冊一個
     BroadcastReciever,並且設定一個Intent Filter以將不需
     要監聽的訊息過慮掉,最後在將其註冊到Android框架
     中。

• Step1: 繼承BroadcastReceiver類別,並覆寫
  onReceive(Context context, Intent intetn)函式
   • 需注意onReceive函式內的處理不宜超過5秒,長時間
     的處理建議移到Thread中執行。

    public class IttrainingAndroidReceiver extends BroadcastReceiver{
         @override
         Public void onReceive(Context context, Intent intent){
              //接收後的處理
         }
    }
為你把關每一道 學習品質                                                            303
BroadCast Receiver元件

• Step2: 註冊BroadCastReceiver
   • 透過XML註冊
  <receiver android:name= " IttrainingAndroidReceiver " >
       <intent-filter>
         <action android:name= " com.ittraining.action.NEW_BROADCAST " />
       </intent-filter>
  </receiver>

    • 透過程式碼註冊
  IntentFilter filter =new IntentFilter(NEW_BROADCAST);
  IttrainingAndroidReceiver receiver=new IttrainingAndroidReceiver();
  registerReceiver(receiver , filter);
  unregisterReceiver(receiver);
    • 取消註冊
  unregisterReceiver(receiver);

為你把關每一道 學習品質                                                                304
範例練習
        範例專案名: ex07_01_Broadcastreceiver

  練習目標:
   學習如何發送廣播訊息
   了解如何接收其它應用程式所發出的廣播訊息
  程式撰寫
   建立一個Activity應用程式與二個Recever程式
   由Activity發送broadcast至Recever程式
  操作練習
   透過模擬器操作。注意兩個receiver的<intent-
    filter>action name並不相同,透過Activity可透過
    不同的action決定要將訊息broadcast至指定的
    receiver.
為你把關每一道 學習品質                               305
BroadCast Receiver元件-安全性管理

• Android廣播服務安全性漏洞
  • 主要利用Intent Filter做為過濾,任何其它應用
    程式只要得知廣播的Action Name就可以註冊
    取得該廣播的資料。這將存在一個安全性的漏
    洞,若你的廣播中所傳遞的是很重要的資料,
    這將有可能被其它惡意軟體給監聽取得。

• 增加自訂權限傳送與接收廣播
  • 開發者可為自己的APP程式加入自訂權限,任
    何的應用程式如果要接收該廣播資料,則必須
    宣告取得相關的權限。


為你把關每一道 學習品質                       306
BroadCast Receiver元件-安全性管理

• 增加權限到AndroidManifest.xml定義描述檔
  <permission
          android:name="com.ittraining.ex07_02.SEND_DATA"
          android:description="@string/permission_aceess_deta"
          android:label="@string/permission_aceess"
          android:protectionLevel="normal" >
   </permission>

• name:權限名稱,請求權限與執行權限時使用,必須為唯
  一的值。
• description:提供詳細說明為何需要此權限,與如何使用
• lable:用戶安裝軟體時顯示給使用者看,以提供用戶進行
  授權,此字串不應太長。
• protectionLevel:權限等級,normal為最基本等級。

為你把關每一道 學習品質                                                     307
BroadCast Receiver元件-安全性管理

• 於AndroidManifest.xml宣告請求使用者授權
  <uses-permission android:name="com.ittraining.ex07_02.SEND_DATA"/>


• 發送廣播時於sendBroadcast第二個參數帶入權
  限名稱
  sendBroadcast(intent, "com.ittraining.ex07_02.SEND_DATA“);


• 接收端在註冊Receiver元件時,第三個參數需帶
  入權限名稱
  registerReceiver(receiver,filter, "com.ittraining.ex07_02.SEND_DATA“,null);




為你把關每一道 學習品質                                                                    308
Services元件
 • Services是在背景運作,不直接與使用者互動,因此並無
   UI畫面
 • Services無法獨立自行運作,而必須透過Activity或其它
   Context物件來呼叫啟動
   • Context.startService()
   • Context.binService()
 • 若Services的onCreate(),onStart()內需執行一些耗時的處
   理,請使用Thread處理,以避免造成UI操件lock.
 • 使用Services的好處,在於Activity結束後其Services元件
   依然會在背景做運行,Services有其獨立的生命週期不會
   受Activity生命週期影影。
   – 播放音樂
   – 背景接收網路訊息
為你把關每一道 學習品質                              309
Services元件
 • Android Services的使用方式可區分為二類
    • Local Services (操作自己應用程式的Services)
    • Remote Services (操作其它應用程式的Services)

 • 與Services溝通方式
   • 透過BroadCast傳送Intent至Services
   • 透過Binder與Services做Local Services連結
   • 透過IPC(interprocess communication)與Remote
     Services做連結
   • 透過Contex.getSystemService(String name),函
     式可取得Android預設的Services元件.


為你把關每一道 學習品質                                    310
Services元件-與Activity溝通方式
 • Services元件與前景的Activity元件之間的溝通架構設
   計模式




為你把關每一道 學習品質                          311
Services元件
 • Android系統內提供的一些Services服務
             Services代碼        對應Manager 物件               說明
  WINDOW_SERVICE            WindowManager         管理視窗畫面
  LAYOUT_INFLATER_SERVICE   LayoutInflater        載入xml檔所定義的View元件
  ACTIVITY_SERVICE          ActivityManager       管理應用程式的系統狀態
  POWER_SERVICE             PowerManger           電源管理
  ALARM_SERVICE             AlarmManager          鬧鐘管理
  NOTIFICATION_SERVICE      NotificationManager   狀態列訊息通知服務
  KEYGUARD_SERVICE          KeyguardManager       鍵盤鎖管理
  LOCATION_SERVICE          LocationManager       位置服務管理,GPS
  SEARCH_SERVICE            SearchManager         搜尋服務管理
  VEBRATOR_SERVICE          Vebrator              振動服務管理
  CONNECTIVITY_SERVICE      Connectivity          網路連線服務管理
  WIFI_SERVICE              WifiManager           WIFI連線服務管理
  TELEPHONY_SERVICE         TeleponyManager       電話服務管理


為你把關每一道 學習品質                                                         312
Services元件-與Activity繼承關係




為你把關每一道 學習品質               313
Services元件-生命週期
 • Services元件有其獨
   立的生命週期
    • onCreate()
    • onStart()
    • onDestroy()
 • 啟動Services的方式
   不同,對應的生命
   週期也不同。
    • startServices()
    • bindServices()




為你把關每一道 學習品質            314
Services元件-啟動Services
 • Step1: 於AndroidManifest.xml中加入Services宣告
    <service android:enabled="true" android:name=".TestService" />

 • Step2:覆寫Services函式-處理生命週期
    public class TestService extends Service {
           @Override
           public void onCreate() {
                  Log.e(TAG, "============> TestService.onCreate");
           }
           @Override
           public void onStart(Intent intent, int startId) {
                  Log.e(TAG, "============> TestService.onStart");
           }
           @Override
           public void onDestroy() {
                  Log.e(TAG, "============> TestService.onDestroy");
           }
    }




為你把關每一道 學習品質                                                           315
Services元件-啟動Services
 • Step3:覆寫Services函式-提供Bind接口
          @Override
          public IBinder onBind(Intent i) {
                 return new LocalBinder();;
          }
          public class LocalBinder extends Binder {
                 TestService getService() {
                        return TestService.this;
                 }
          }
          @Override
          public boolean onUnbind(Intent i) {
                 Log.e(TAG, "============> TestService.onUnbind");
                 Return true;
          }
          @Override
          public void onRebind(Intent i) {
                 Log.e(TAG, "============> TestService.onRebind");
          }




為你把關每一道 學習品質                                                         316
Services元件-啟動Service
 • Step4:透過Activity啟動Service-使用startService()
             private void startService() {
                  Intent i = new Intent(this, TestService.class);
                  this.startService(i);
             }
             private void stopService() {
                  Intent i = new Intent(this, TestService.class);
                  this.stopService(i);
             }

 • Step4:透過Activity啟動Services-使用bindService()
       private void bindService() {
            Intent it = new Intent(this, TestService.class);
             bindService(it , _connection, Context.BIND_AUTO_CREATE);
             _isBound = true;
         }
        private void unbindService() {
            if (_isBound) {
               unbindService(_connection);
               _isBound = false;
            }
為你把關每一道}學習品質                                                            317
Services元件-啟動Service
 • Step6:SerrviceConnection元件建立-透過bindService()
  private ServiceConnection _connection = new ServiceConnection() {
      public void onServiceConnected(ComponentName className, IBinder service){
             _boundService = ((TestService.LocalBinder)service).getService();
             Toast.makeText(TestServiceHolder.this, "Service connected:",
             Toast.LENGTH_SHORT).show();
      }

        public void onServiceDisconnected(ComponentName className) {
               _boundService = null;
               Toast.makeText(TestServiceHolder.this, "Service connected",
               Toast.LENGTH_SHORT).show();
        }
   };




為你把關每一道 學習品質                                                                      318
BroadcastReceiver與Services綜合演練

 • 結合Services服與程式與BroadcastReceiver,實作
   一鬧鐘計時器。

提供UI畫面讓User設定鬧鐘時                              Services在背景進行時間排程倒
間設定完成後會通知背景                                   數,當時間到時透過broadcast訊
Services進行倒數計時,並註冊                            息,傳送回主程式,並播放一段鬧鐘
一個BroadcastReceiver類別                         音效與Toast訊息

           KitchenTimer.java                     KitchenTimerService.java
              KitchenTimer                       Schedule(long delay)
 KitchenTimerSdervice.shecule(alarmtimer)    Timer.shedule(timerTask,delay)

               KitchenTimer                            TimerTask()
       KitchenTimerReceiver-receiver        sendBroadcast(new Intent(ACTION))




為你把關每一道 學習品質                                                                    319
BroadcastReceiver與Services綜合演練

 • Step1:建立Services宣告
   <service android:enabled="true" android:name=".KitchenTimerService" />

 • Step2:主程式onCreate()
   //啓動服務程式KitchenTimerService
   Intent intent = new Intent(this, KitchenTimerService.class);
   startService(intent);
   //註冊廣播接收receiver
   IntentFilter filter = new IntentFilter(KitchenTimerService.ACTION);
   registerReceiver(receiver, filter);
   //(Bind)服務程式KitchenTimerService
   bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);




為你把關每一道 學習品質                                                                320
BroadcastReceiver與Services綜合演練

  • Step3:主程式onDestroy()
       //Activity結束時,要將Service相關資源一並結束
       @Override
       public void onDestroy() {
              super.onDestroy();
              unbindService(serviceConnection); //Unbind service
              unregisterReceiver(receiver); //Unregister Receiver
              kitchenTimerService.stopSelf(); //Stop Service
       }

  • Step4:定義接收廣播類別KitchTimerReceiver
   private class KitchenTimerReceiver extends BroadcastReceiver {
         public void onReceive(Context context, Intent intent) {
                 Toast toast = Toast.makeText(getApplicationContext(), "Time over!",
                 Toast.LENGTH_LONG);
                 toast.show();
                 MediaPlayer mp = MediaPlayer.create(KitchenTimer.this, R.raw.alarm);
                 try {
                              mp.start();
                 } catch (Exception e) {
                 }
                 kitchenTimerService.schedule(alarmtimer);
         }
為你把關每一道 學習品質
   }                                                                                    321
BroadcastReceiver與Services綜合演練

 • Step5:定義與Service bind的ServiceConnection
   private ServiceConnection serviceConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
               kitchenTimerService =
               ((KitchenTimerService.KitchenTimerBinder)service).getService();
         }
         public void onServiceDisconnected(ComponentName className) {
               kitchenTimerService = null;
         }
   };




為你把關每一道 學習品質                                                                          322
BroadcastReceiver與Services綜合演練

 • Step6:建立Services類:KitchenTimerService
  public void onCreate() {
         super.onCreate();
         Toast toast = Toast.makeText(getApplicationContext(), "onCreate()", Toast.LENGTH_SHORT);
         toast.show();
  }
  public void onStart(Intent intent, int startId) {
         super.onStart(intent, startId);
         Toast toast = Toast.makeText(getApplicationContext(), "onStart()", Toast.LENGTH_SHORT);
         toast.show();
  }
  public void onDestroy() {
         super.onDestroy();
         Toast toast = Toast.makeText(getApplicationContext(), "onDestroy()", Toast.LENGTH_SHORT);
         toast.show();
         if (timer != null) {
                timer.cancel();
                timer = null;
         }
  }




為你把關每一道 學習品質                                                                                         323
BroadcastReceiver與Services綜合演練

 • Step7:覆寫Services Bind相關函式
  @Override
  public IBinder onBind(Intent intent) {
         Toast toast = Toast.makeText(getApplicationContext(), "onBind()", Toast.LENGTH_SHORT);
         toast.show();
         return new KitchenTimerBinder();
  }
  @Override
  public void onRebind(Intent intent) {
         Toast toast = Toast.makeText(getApplicationContext(), "onRebind()", Toast.LENGTH_SHORT);
         toast.show();
  }
  @Override
  public boolean onUnbind(Intent intent) {
         Toast toast = Toast.makeText(getApplicationContext(), "onUnbind()", Toast.LENGTH_SHORT);
         toast.show();
         return true; //當再度自Client接口時,呼叫 onRebind的場合會回覆 true
  }




為你把關每一道 學習品質                                                                                        324
BroadcastReceiver與Services綜合演練

 • Step8:Service發送廣播訊息至主程式
         public void schedule(long delay) {
              if (timer != null) {
                     timer.cancel();
              }
              timer = new Timer();
              TimerTask timerTask = new TimerTask() {
                     public void run() {
                                 //送出信息給廣播接收程式
                                 sendBroadcast(new Intent(ACTION));
                     }
              };
              //設定Alarm time,且Time out時會執行timerTask送出信息
              timer.schedule(timerTask, delay);
         }




為你把關每一道 學習品質                                                          325
範例練習

          範例專案名: ex07_02_Kitchentimer

  練習目標:
   學習如何結合BroadCastReceiver與Services的應用
  程式撰寫
   實作一個Activity並內置一個Receiver類別,當用設定
    好時間後將啟動一個Services在背景做倒數計時的動
    作。
   實作一個Services應用程式,由Activity所呼叫建立,
    當指定的計時工作結束後將透過broadcast方式通知
    Activity的receiver類別。
  操作練習
   透過模擬器操作,倒數計時的單位為分鐘。時間到後
    會發出聲響,並顯示一段Toast字串於畫面上。
為你把關每一道 學習品質                              326
Remote Services應用

• 要將Services元件跑在獨立的Processe中可透過在
  AndroidMainfest.xml中,宣告services元件加上
  android:process=":remote"
    <service android:name=".services.TrackerServices"
    android:process=":remote">


• Services中設置Messenger可以提供與遠端Services元件進
  行雙向溝通。
  private Handler mHandler = new Handler() {
       @Override
       public void handleMessage(Message msg) {
              /*接收來自client傳來的訊息*/
       }
     }
  private Messenger mMessenger = new Messenger(mHandler);
  @Override
  public IBinder onBind(Intent intent) {
       return mMessenger.getBinder();
  }
為你把關每一道 學習品質                                                327
Remote Services應用

• Client端在利用Bind與遠端Services連接,並取得
  Messenger元件。
 private Messenger remoteMessenger;
 private ServiceConnection connection = new ServiceConnection() {
        public void onServiceConnected(ComponentName name, IBinder service) {
          remoteMessenger = new Messenger(service);
        }
        public void onServiceDisconnected(ComponentName name) {
          remoteMessenger = null;
        }
     };

• 傳送訊息至Remote Services
 Private Message localMessenger;
 private void sendMessage() {
       Message message = Message.obtain(null, 0);
       message.replyTo = localMessenger;
       try {
          rMessenger.send(message);
       } catch (RemoteException e) {
         e.printStackTrace(); }
 }
為你把關每一道 學習品質                                                                    328
範例練習

         範例專案名: ex07_03_RemoteService

  練習目標:
   了解RemoteServices與Local Services的差別
   學習如何使用Messenger進行IPC跨Process通訊
  程式撰寫
   撰寫一個Services元件,並將process tag設為:remote
   設置Messenger 物件做為IPC通訊管道。
   撰寫Activity 元件,利用Bind 與remote services 通
    訊。
  操作練習
   透過模擬


為你把關每一道 學習品質                                  329
IntentService應用

• Android預設所有的四大元件都是運行在主執行緒中,包含
  Service也是運行在主執行緒中,因此若在Service執行耗時
  的工作則將會導致UI lock。避免UI Lock的方式為將Service
  設置為remote,或是透過IntentService。

• IntentService 為一次性使用的Service元件,並且會自動運
  行在子執行緒中,使用者可以免除複雜的Message、Loop
  與Handler設計,透過Intentservice可以快速的處理一次性
  耗時的工作。

• 將工作放置於IntentService的優勢
  • 比較不容易被系統Kill
  • 工作於子執行緒中,不會導致UI Thread Lock
  • 非常容易使用,使用完即自動回收,不佔用記憶體。

為你把關每一道 學習品質                          330
範例練習

          範例專案名: ex07_04_IntentService

  練習目標:
   了解Intent Service、Thread與Service的差別
   學習如何利用Intent Service 在背景處理耗時的工作
  程式撰寫
   繼承IntentService類別,並實作onHandleIntent函式
   將耗時的工作寫在onHandleIntent函式中。
   撰寫Activity頁面,利用startService函式呼叫
    IntentService工作。
  操作練習
   透過模擬
為你把關每一道 學習品質                                331
第9節: SQLite DataBase開發技巧
SQLite DataBase開發技巧

  SQLite Database存取技巧
     SQLite語言定義與建置工具
     SQLiteOpenHelp類別實作
     資料庫的基本IO操作方式
     設計DataBase Adapter架構




                             333
SQLite DataBase

• SQLite是Android內建的一個輕量化的嵌入式資料庫,可使
  用SQL語法進行控制存取。

• SQLite的優點
   • 免費,無需授權
   • 輕量,約150KB左右,很適在嵌入式手機領域使用
   • 無需設定、安裝與管理,沒有伺服器,不需組態檔,無
     需資料庫管理員
   • SQLite只是一個檔案,可以很方便的移動或複製到另一
     系統,也能運作的很良好。

• Android將SQLite檔案存放於下列路徑中
   • /data/data/packagename/databases
   • 可以使用adb或File Explorer來觀移存取資料庫檔案

為你把關每一道 學習品質                            334
SQLite DataBase

• SQL入門
   • SQL描述語法主要包含三種類型
      • DLL(資料定義語言)
      • 修改
      • 查尋
• DLL資料定義語言:
   • 資料庫的組成由多個資料表(table)多個資料列(Row)
     若干資料欄(column)所組成。
   • 每個資料欄具有欄位名稱與資料類形(文字,數字…)
   Create table mytalbe(
   _id integer primary key autoincrement,
   Name text,
   Phone text)

  • 第一個欄位指定為主鍵(PRIMARY KEY)
為你把關每一道 學習品質                                335
SQLite DataBase
• 安裝Questoid SQLite Browser Eclipse Plugin,協助以圖形化方式觀看
  Android內的SQLite資料表
   • http://www.questoid.net/Tools/QuestoidSQLiteBrowser.aspx
   • 將com.questoid.sqlitebrowser_1.1.0.jar Copy至Eclipse的plugins目
     錄中,並重新啟動Eclipse.
   • 切換至DDMS視圖,利用File Explorer工具找到要查看的SQLite
     data base檔案.




• SQL語法指令查尋與學習資源
   • http://www.1keydata.com/tw/sql/sqlhaving.html

為你把關每一道 學習品質                                                  336
SQLite DataBase-SQLiteOpenHelper

• Android應用程式中提供了SQLiteOpenHelper類別來協助操
  作SQLite資料庫並,提供產生與管理資料庫的版本

• SQLiteOpenHelper為一抽像類別,需繼承並實作三個函式
  • onCreate(SQLiteDatabase db)
     • 資料庫第一次產生時呼叫。
  • onUpdate(SQLiteDatabase db,int oldVersion,int newVersion)
     • 當資料庫需要升級時,由系統主動呼叫。一般用來刪除舊資料
       表,並建立新的資料表
  • onOpen(SQLiteDatabase db)
     • 當資料庫被開啟時的Callback函式,由系統呼叫,一般不會使用到。




為你把關每一道 學習品質                                                    337
SQLite DataBase-SQLiteOpenHelper

• 如何建立SQLiteOpenHelper類別
  private static final String DATABASE_NAME = "dbForTest.db";
  private static final int DATABASE_VERSION = 1;
  private static final String TABLE_NAME = "diary";
  private static final String TITLE = "title";
  private static final String BODY = "body";
  private static class DatabaseHelper extends SQLiteOpenHelper {
        DatabaseHelper(Context context) {
              super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }
        @Override
        public void onCreate(SQLiteDatabase db) {
              String sql = "CREATE TABLE " + TABLE_NAME + " (" + TITLE
              + " text not null, " + BODY + " text not null " + ");";
              db.execSQL(sql);
        }
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        }
  }
為你把關每一道 學習品質                                                                         338
SQLite DataBase-SQLiteOpenHelper

• 取得透過SQLiteOpenHelper取得SQLiteDatabase類別
  Public Methods
  synchronized SQLiteDatabase           getReadableDatabase()Create and/or open a database.


  synchronized SQLiteDatabase           getWritableDatabase()Create and/or open a database
                                        that will be used for reading and writing.



• 利用SQLiteDatabase提供的函式可以存取操作資料庫
  •   public Cursor rawQuery (String sql, String[] selectionArgs)
        •   最低階的操作函式,可以直接接受標準SQL語法
  • 為方便不熟SQL語法的開發者,另外有提供一系列的API函式,系統
    會將API指令自動轉換成標準的SQL語法呼叫資料庫。
        •   pubilc delete(….)
        •   pubilc insert(….)
        •   pubilc update(….)
        •   public Cursor query (….)
為你把關每一道 學習品質                                                                                  339
SQLite DataBase-資料庫操作

• 如何插入資料庫記錄
  private void insertItem() {
        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
        String sql1 = "insert into " + TABLE_NAME + " (" + TITLE + ", " + BODY
        + ") values('haiyang', 'android的發展真是迅速');";
        String sql2 = "insert into " + TABLE_NAME + " (" + TITLE + ", " + BODY
        + ") values('icesky', 'android的發展真是迅速');";
        try {
              db.execSQL(sql1);
              db.execSQL(sql2);
              setTitle("插入兩條數據成功");
        } catch (SQLException e) {
              setTitle("插入兩條數據失敗");
        }
  }




為你把關每一道 學習品質                                                                     340
SQLite DataBase-資料庫操作

• 如何刪除資料記錄
  private void deleteItem() {
        try {
              SQLiteDatabase db = mOpenHelper.getWritableDatabase();
              db.delete(TABLE_NAME, " title = 'haiyang'", null);
              setTitle("刪除title為haiyang的一條記錄");
        } catch (SQLException e) {
        }
  }

• 查尋資料
  private void showItems() {
        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
        String col[] = { TITLE, BODY };
        Cursor cur = db.query(TABLE_NAME, col, null, null, null, null, null);
        Integer num = cur.getCount();
        setTitle(Integer.toString(num) + " 條記錄");
  }


為你把關每一道 學習品質                                                                    341
SQLite DataBase-資料庫操作
• 刪除整個Table
    private void dropTable() {
          SQLiteDatabase db = mOpenHelper.getWritableDatabase();
          String sql = "drop table " + TABLE_NAME;
          try {
                 db.execSQL(sql);
                 setTitle("數據表成功刪除︰" + sql);
          } catch (SQLException e) {
                 setTitle("數據表刪除錯誤");
          }
    }

• 建立新的Table
  private void CreateTable() {
        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
        String sql = "CREATE TABLE " + TABLE_NAME + " (" + TITLE
        + " text not null, " + BODY + " text not null " + ");";
        try {
               db.execSQL("DROP TABLE IF EXISTS diary");
               db.execSQL(sql);
               setTitle("數據表成功重建");
        } catch (SQLException e) {
               setTitle("數據表重建錯誤");
        }
為你把關每一道 學習品質
  }                                                                342
範例練習
               範例專案名: ex08_01_Sqlite

  練習目標:
   學習如何建立與使用SQLite資料庫
  程式撰寫
     撰寫DataBaseHelper 繼承SQLiteOpenHelper
     透過DataBaseHelper取得SQLiteDatabase物件,並實作新
      增、刪除、查尋、建立資料表等函式
  操作練習
   透過模擬器操作,可以藉由DDMS的檔案瀏覽器
    將SQLite資料庫檔滙出,或滙入現有的SQLite資
    料庫至手機上。

為你把關每一道 學習品質                                    343
SQLite DataBase-Query函式
• SQLiteDatabase的query方法
   • Cursor query (boolean distinct, String table, String[] columns,
                   String selection, String[] selectionArgs, String groupBy,
                   String having, String orderBy, String limit)
    • distinct : 是否希望每一row都是唯一的
    • table:要查尋的資料表(Table)
    • columns:回傳資料包含的訊息列。不在清單中的其它列將不會取得。
    • selection:相當於SQL中的where,如想傳回所有資料請用null
    • selectionArgs:如select中有使用到[?]變數,此字串將用來取代[?]
    • groupBy:查尋得到的資料是否要分群組
    • having:相當於SQL中的having
    • orderBy:是否需要排序,若設定為null代表不排序
    • limit:限制查尋回的資料組數上限


為你把關每一道 學習品質                                                                   344
SQLite DataBase-Cursor介面
• android.database.Cursor介面
   • 由query方法查尋到資料後,將會回傳Cursor物件。
   • 透過Cursor可以將資料庫查出來的資料進行讀寫操作。
   • Cursor可以連結CursorAdapter並覆寫其bindView()和newView()兩
     抽像方法來達到更豐富的顯示方式


                               Activity

                                          SQLiteOpenHelper



         Cursor      Query結果

                                           SQLiteDatabase



為你把關每一道 學習品質                                                 345
SQLite DataBase-Cursor介面
• Cursor常用的函式
                        函式                      說明
      movetoPosition(int pos)        移動Cursor到指定位置
      Move(int offset)               向前或向後位移:正數向前,負責向後
      moveToFirst()                  移動Cursor到最前或最後位置
      moveToLast()
      moveToNext()                   將Cursor向前或向後移動一格
      moveToLast()
      isBeforeFirst()                判斷Cursor是否指向第一個數據之前,或最
      isAfterLast()                  後一個數據之後
      isFirst()                      判斷Cursor是否指向第一行或最後一行
      isLast()
      getColumnCount()               取得行(列)數目
      getCount()
      getColumnIndexOrThrow(String   根據列的名稱取得索引值(以0開始)
      columnName)
   getBlob(int index)                依據資料型別取回Cursor目前所指的資料。
   getInt(int index)
   getLong(int index)
   getShort(int index)
   getFloat(int index)
為你把關每一道 學習品質
   getString(int index)                                       346
SQLite DataBase-Cursor介面
• Cursor與CursorAdapter連接
  • public SimpleCursorAdapter (Context contex, int layout, Cursor c,
    String[]from, int[] to)
       • context:作用於那個Context物件上
       • layout:顯示介面layout樣版,需包含to所指定的View id
       • c: cursor資料來源
       • from:需要從cursor取出的列名稱索引值
       • to:layout中需要作用對應於from值的View元件id

 s = (Spinner)findViewById(R.id.spinner);
 display = (TextView)findViewById(R.id.display);
 SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
 android.R.layout.simple_spinner_item,c,new String[] { MyHelper.COUNTRY},
 new int[] {android.R.id.text1});
 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_it
 em);
 s.setAdapter(adapter);
 為你把關每一道 學習品質                                                                  347
SQLite DataBase-日記簿運作流程
         ActivityDiaryEdit
                                                DiaryDbAdapter
   onCreate ()
   onClick()                                    deleteDiary()
                                                createDiary()
                                                getAllNotes()
 EditText    EditText        Button             getDiary()
                                                updateDiary()
 ActivityMain extends ListActivity
  onMenuItemSelected()
  onCreateOptionsMenu()                         DatabaseHelper
  createDiary()
  onListItemClick()
  onCreate ()

     SimpleCursorAdapter                        NAME:database
                                                TABLE: diary
                                       Query結
                              Cursor     果
為你把關每一道 學習品質                                                     348
範例練習
           範例專案名: ex08_02_Sqldiary

  練習目標:
   學習如何利用SQLite開發一個簡單的日記本
   學習SimpleCursorAdapter的使用
  程式撰寫
   實作一個ListActivity,並將SQLite讀取得到的資料透
    過SimpleCursorAdapter顯示於ListActivity上.
   實作一個DiaryDbAdapter,協助處理與SQLite資料庫
    存取有關的所有操作
   設計一個日記輸入與編輯的UI頁面
  操作練習
   透過模擬器進行操作。
為你把關每一道 學習品質                                349
DataBaseAdapter架構實作

 • 設計DataBaseAdapter可提供Activity頁面一個統
   一且一致的存取資料庫的介面,並且將SQL語法
   隱藏在Adapter內,對外只提供高階的存取介面。


                                  SqlObject
                                    SqlObject
               DataBaseAdapter        SqlObject

                  IOInterface
                                                  Activity
  SQLite

               DataBaseOpenHelp




為你把關每一道 學習品質                                                 350
DataBaseAdapter架構實作

 • 資料庫表單常數定義介面
   • DataBaseColumnDefine
     public interface DataBaseColumnDefine {
           /* 表單名稱 */
           public static final String USERPROFILE_TABLE_NAME = "UserProfileDB";
           /* 欄位名稱 */
           public static final String USERPROFILE_KEY_ID = "_id";
           /*SQL指令*/
           public static final String SQL_CREATE="CREATE TABLE ";
           public static final String SQL_DATA_AUTO=" integer primary key autoincrement";
           public static final String SQL_DATA_NUMERIC=" NUMERIC";
           public static final String SQL_DATA_TEXT=" TEXT";

           /*建立table的sql語法*/
           public static final String CREATE_USERPROFILE_TABLE = SQL_CREATE +
           USERPROFILE_TABLE_NAME+ " ("
           + USERPROFILE_KEY_ID + SQL_DATA_AUTO+");";

           /*Query回來資料的欄位範圍*/
           public static String[] userProfileDataSet = { USERPROFILE_KEY_ID,};
     }

為你把關每一道 學習品質                                                                                351
DataBaseAdapter架構實作

 • SqlObject抽像介面設計
   • 抽像的功能
     /**
      * 取得privateKey值
      */
     abstract int getPrivateKey();
     /**
      * 設定privateKey值
      */
     abstract void setPrivateKey(int privateKey);
     /**
      * 從資料庫中讀入資料
      * @param cursor
      */
     abstract void readProfile(Cursor cursor);
     /**
      * 將資料轉換成ContentValues以供資料庫做後操作
      */
     abstract ContentValues getContentValues();




為你把關每一道 學習品質                                        352
DataBaseAdapter架構實作

 • SqlObject抽像介面
   • 產生SqlObject的建構工廠
     /**
      * 依需求取得不同型態的SQL Object
      * @param type
      * @return
      */
     public static SqlObject createUserDataObject(SqlType type){
           switch(type){
           }
           return null;
     }




為你把關每一道 學習品質                                                       353
DataBaseAdapter架構實作

 • DataBaseAdapter實作方式
   • 使用Singleton架構
     private SQLiteDatabase sqlDataBase;
     private static DataBaseAdapter dbAdapter;
     private DataBaseAdapter(Context context){
     DataBaseHelp dataBaseHelp= new DataBaseHelp(context);
           try {
                  dataBaseHelp.createDataBase();
           } catch (IOException e) {
                  e.printStackTrace();
           }
           sqlDataBase=dataBaseHelp.getWritableDatabase();
     }

     public synchronized static DataBaseInterface getInstence(Context context){
           if(dbAdapter==null)
                 dbAdapter=new DataBaseAdapter(context.getApplicationContext());
           return dbAdapter;
     }



為你把關每一道 學習品質                                                                       354
DataBaseAdapter架構實作

 • 透過DataBaseOpenHelp讀寫資料庫(SqlObject)
   • 新增
        mDb.insert(USERPROFILE_TABLE_NAME, null, initialValues);


   • 刪除
        mDb.delete(USERPROFILE_TABLE_NAME, USERPROFILE_KEY_ID + "=" +
        sqlObject.getPrivateKey(), null);

   • 修改
        mDb.update(USERPROFILE_TABLE_NAME, initialValues, USERPROFILE_KEY_ID + "="
        + sqlObject.getPrivateKey(0, null) > 0;



   • 查尋
        Cursor mCursor=mDb.query(USERPROFILE_TABLE_NAME, userProfileDataSet, null, null, null,
        null,null);

為你把關每一道 學習品質                                                                                 355
DataBaseAdapter架構實作

   • 上層Activity使用DataBaseAdapter方式
     • 取得DataBaseAdapter物件實體
        DataBaseAdapter dbAdapter=DataBaseAdapter.getInstence(this);


      • 讀取資料
        ArrayList<UserProfile>allUser= (ArrayList<UserProfile>) dbAdapter.getAllUser(null);



        ArrayList<UserProfile>allUser=dbAdapter.getAllUser(allUser); //參照更新



      • 新建資料
        profile.setPhotoType(1);
        profile.setUserCompony("test");
        profile.setUserName("Jarey");
        profile.setUserPhone("09xxx");
        long privateKey=dbAdapter.addUserProfile(profile);

為你把關每一道 學習品質                                                                                  356
範例練習
          範例專案名: ex08_03_SqlTemplet

  練習目標:
   學習如何設計DataBase Adapter
   透過DataBase Adapter層將應用層與資料存取層分
  程式撰寫
   設計一簡單的資料庫表單,並實作DataBase Adapter
    元件。
   Activity層透過DataBase Adapter對資料庫進行資料存
    取。
   實作一個BaseAdapter元件,將從DataBaseAdapter
    讀出的資料透過BaseAdapter顯示於ListView上。
  操作練習
   透過模擬器進行操作。

為你把關每一道 學習品質                               357
第10節: Content Provider元件
 Android Thread程式設計
Content Provider元件

  ContentProvider元件設計
     ContentProvider應用時機
     與系統ContentProvider連接
     自建ContentProvider




                             359
Content Provider元件

• ContentProvider作用
  • Android程式中所有的資料(包含檔案,資料庫)全都是Private的,不同
    的應用程式之間不能直接存取
  • ContentProvider提供解決不同應用程式之間交換資料的需求

• ContentProvider提供一組標準介面
  • query(Uri uri,String[] projection,String selection,String[]
    selectionArgs,String sortOrder)
     • 透過Uri進行查尋,結果將透過傳回的Cursor物件進行存取.
  • insert(Uri url,ContentValues values)
     • 將一組資料插入到Uri指定的位置
  • update(Uri url,ContentValues values,String where,String[]
    selectionArgs)
     • 更新Uri指定位置的資料
  • delete(Uri url,String where,String[] selectionArgs)
     • 刪除Uri指定並符合條件的資料

為你把關每一道 學習品質                                                      360
Content Provider元件

• ContentResolver
  • 外部應用程式可以透過ContentResolver介面來存取
    ContentProvider所提供的資料
  • ContentResolver物件是透過Activity.getContentResolver()取得
• ContentResolver所提供的存取介面
  • query(Uri uri,String[] projection,String selection,String[]
    selectionArgs,String sortOrder)
  • insert(Uri url,ContentValues values)
  • update(Uri url,ContentValues values,String where,String[]
    selectionArgs)
  • delete(Uri url,String where,String[] selectionArgs)

          Application                                 Application
                                  URI
                    Content                    Content
   Activity                                                         Data
                    Resolver    query          Provider
                                insert
                                update
為你把關每一道 學習品質                    delett                                     361
Content Provider元件

• ContentProvider 中使用的Uri形式
  • content://contacts/people/  代表全部聯絡人資料
  • content://contacts/people/1 代表ID為1的連絡人資料
• Uri的組成結構:
    content://authority/path/id

  • 第一部份:content://
    • 必要的標準前置碼(prefix)
  • 第二部份:authority
    • 提供者的名稱,在此建使用完全套件名稱定義以避免名稱出現衝
      突狀況
  • 第三部份:path
    • 為提供者內部的虛擬目錄路徑
  • 第四部份:id
    • 請求之特定記錄的主鍵ID,若要請求所有記錄可以直接以/結尾

為你把關每一道 學習品質                                   362
ContentProvider元件-讀取連絡人資料

• Android內建的ContentProvider
   • content://browser
   • content://contacts
   • content://media
   • content://settings
• Step1:於AndroidManifest.xml中加入權限
  <uses-permission android:name="android.permission.READ_CONTACTS" />

• Step2:取得ContentResolver物件,query連絡人資料
 import android.provider.ContactsContract;
 import android.content.ContentResolver;

 ContentResolver cr = getContentResolver();
 Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null,
 null, null);

為你把關每一道 學習品質                                                                363
Content Provider元件-讀取連絡人資料

• Step3:取得連絡人姓名
  String name = cur.getString(cur.getColumnIndex("display_name"));

• Ste4:取得連絡人ID (2.0.1後改版,Phone移至不同URI)
  long id = cur.getLong(cur.getColumnIndex(" _id"));


• Step5:透過ID重新查尋得使用者電話
  Cursor pcur = getContentResolver().query(
  ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
  null ,ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "="
  + Long.toString(id), null, null);


  String strPhoneNumber = pcur.getString(
  pcur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));


為你把關每一道 學習品質                                                             364
範例練習
         範例專案名: ex08_04_Contentprovider

  練習目標:
   學習如何建立ContentResolver並連接至Android
    的連絡人Content Povider,取得用戶的連絡人清
    單資料
  程式撰寫
   透過getContentResolver ()取得ContentResolver
    物件
   連接至Android CONTENT_URI ,並將資料透過
    adapter顯示於ListView上
  操作練習
   透過模擬器操作

為你把關每一道 學習品質                                   365
ContentProvider元件-自建ContentProvider
• 修改先前的日記簿範列,將新增、刪除、修改與查尋操作改以
  ContentProvider的方式來實作。
           ActivityDiaryEdit
     EditText    EditText    Button
                                                    DiaryContentProvider
     insertDiary()          Content                extend ContentProvider
     updateDiary()          Resolver
                                                    Content    query()
                                                    Provider   Insert()
                                                               delete()
  ActivityMain extends ListActivity                            update()
 onMenuItemSelected()
 onCreateOptionsMenu()         Content
 onOptionsItemSelected()       Resolver
 onListItemClick()                                   SQLiteOpenHelper

       SimpleCursorAdapter

       Diary
                                          Query結     NAME:database
                                 Cursor
   BaseColumns
為你把關每一道 學習品質
                                            果        TABLE: diary
                                                                            366
ContentProvider元件-自建ContentProvider

• Diary類別實作
public final class Diary {
//這裡的 AUTHORITY 要求是唯一,而且和Manifest當中provider標籤的AUTHORITY內容一致
  public static final String AUTHORITY = "com.ex09_2_contentprovider.diarycontentprovider";
  private Diary() {}
  public static final class DiaryColumns implements BaseColumns {
    // This class cannot be instantiated
    private DiaryColumns() {}
    public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/diaries");
    public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.google.diary";
    public static final String CONTENT_ITEM_TYPE =
            "vnd.android.cursor.item/vnd.google.diary";
    public static final String DEFAULT_SORT_ORDER = "created DESC";
    public static final String TITLE = "title";
    public static final String BODY = "body";                    _id      title  body        create
    public static final String CREATED = "created";
                                                              unique-id 標題        內文        建立時間
  }
}                                                             unique-id 標題        內文        建立時間



 為你把關每一道 學習品質                                                                                    367
ContentProvider元件-自建ContentProvider

• DiaryContentProvider類別實作
  • 繼承自ContentProvider類別
  • 定義Uri類別變數:
      content://com.ex09_2_contentprovider.diarycontentprovider/diaries
       • content:固定的開頭不用更改
       • AUTHORITY:授權字串必須是唯一的,宣告告於AndroidManifest.xml
       • request: 資料型別,在此只定義一個型別,對應資料表名稱。也可以設
          計成兩個公開的資料表例如 diaries/my ,diaries/other.
       • id:代表要存取那一筆資料
  • 建構資料儲存系統,在此使用的是SQLite資料庫
  • 實作ContentProvider抽像方法
    • oncreate();query();inster();delete();update();getType();
  • 於AndroidManifest.xml中加入<provider>標籤
   <provider android:name="DiaryContentProvider"
   android:authorities="com.ex09_2_contentprovider.diarycontentprovider" />



為你把關每一道 學習品質                                                                  368
ContentProvider元件-自建ContentProvider

• android.database.sqlite.SQLiteQueryBuilder類別介紹
   • 建構SQL查尋語法的輔助類別
      SQLiteQueryBuilder qb = new SQLiteQueryBuilder();

   • qb.query(SQLiteDatabase db,String[] projectionIn,String selection,String[]
     selectionArgs,String groupBy,String having,String sortOrder,String limit);




為你把關每一道 學習品質                                                                369
ContentProvider元件-自建ContentProvider

• android.content.ContentUris類別介紹
   • URI的一個補助類別,包含了二個函式
      • Public static Uri withAppendedId(Uri contentUri,long
        id)
         • 負責將id和Uri串接在一起成新的Uri。
             Uri diaryUri = ContentUris.withAppendedId(
             Diary.DiaryColumns.CONTENT_URI, rowId)

      • Public static long parseId(Uri contentUri)
         • 負責把Uri後的id解析出來。
         • 例如com.ex09_2_contentprovider.diarycontentprovider/100
           透過parseId後回傳值為100




為你把關每一道 學習品質                                                  370
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計
Android動態ui介面設計

Contenu connexe

Tendances

設計・構築においてのドキュメントの重要性について
設計・構築においてのドキュメントの重要性について設計・構築においてのドキュメントの重要性について
設計・構築においてのドキュメントの重要性についてTakayuki Higashi
 
LLD(ローレベルディスカバリ)を弄り倒せ、zabbix_senderを併用してらくらく可視化
LLD(ローレベルディスカバリ)を弄り倒せ、zabbix_senderを併用してらくらく可視化LLD(ローレベルディスカバリ)を弄り倒せ、zabbix_senderを併用してらくらく可視化
LLD(ローレベルディスカバリ)を弄り倒せ、zabbix_senderを併用してらくらく可視化Takeshi Yamane
 
計算量のはなし(Redisを使うなら必読!O(logN)など)
計算量のはなし(Redisを使うなら必読!O(logN)など)計算量のはなし(Redisを使うなら必読!O(logN)など)
計算量のはなし(Redisを使うなら必読!O(logN)など)Makoto SAKAI
 
セキュリティを楽しむ(CTFとbugbountyの始め方)
セキュリティを楽しむ(CTFとbugbountyの始め方)セキュリティを楽しむ(CTFとbugbountyの始め方)
セキュリティを楽しむ(CTFとbugbountyの始め方)kazkiti
 
Pull request時の画面差分取得の自動化
Pull request時の画面差分取得の自動化Pull request時の画面差分取得の自動化
Pull request時の画面差分取得の自動化Shunsuke Maeda
 
Beyond the Twelve-Factor App
Beyond the Twelve-Factor AppBeyond the Twelve-Factor App
Beyond the Twelve-Factor AppKazuya Takahashi
 
フリーでできるセキュリティチェック OpenVAS CLI編
フリーでできるセキュリティチェック OpenVAS CLI編フリーでできるセキュリティチェック OpenVAS CLI編
フリーでできるセキュリティチェック OpenVAS CLI編abend_cve_9999_0001
 
ラズベリー・パイでプログラミングと電子工作を体験してみよう
ラズベリー・パイでプログラミングと電子工作を体験してみようラズベリー・パイでプログラミングと電子工作を体験してみよう
ラズベリー・パイでプログラミングと電子工作を体験してみようTakashi Kanamaru
 
CVE、JVN番号の取得経験者になろう!
CVE、JVN番号の取得経験者になろう!CVE、JVN番号の取得経験者になろう!
CVE、JVN番号の取得経験者になろう!kazkiti
 
Delta Lake with Synapse dataflow
Delta Lake with Synapse dataflowDelta Lake with Synapse dataflow
Delta Lake with Synapse dataflowRyoma Nagata
 
コンテナイメージの脆弱性スキャンについて
コンテナイメージの脆弱性スキャンについてコンテナイメージの脆弱性スキャンについて
コンテナイメージの脆弱性スキャンについてYASUKAZU NAGATOMI
 
ITコミュニティと情報発信に共通する成長と貢献の要素
ITコミュニティと情報発信に共通する成長と貢献の要素ITコミュニティと情報発信に共通する成長と貢献の要素
ITコミュニティと情報発信に共通する成長と貢献の要素NISHIHARA Shota
 
今夜わかるWebアプリケーション脆弱性診断 (OWASP Day 758 / 2018)
今夜わかるWebアプリケーション脆弱性診断 (OWASP Day 758 / 2018)今夜わかるWebアプリケーション脆弱性診断 (OWASP Day 758 / 2018)
今夜わかるWebアプリケーション脆弱性診断 (OWASP Day 758 / 2018)Sen Ueno
 
SecurityCamp2015「バグハンティング入門」
SecurityCamp2015「バグハンティング入門」SecurityCamp2015「バグハンティング入門」
SecurityCamp2015「バグハンティング入門」Masato Kinugawa
 
Data Factoryの勘所・大事なところ
Data Factoryの勘所・大事なところData Factoryの勘所・大事なところ
Data Factoryの勘所・大事なところTsubasa Yoshino
 
.NET 7におけるBlazorの新機能
.NET 7におけるBlazorの新機能.NET 7におけるBlazorの新機能
.NET 7におけるBlazorの新機能TomomitsuKusaba
 
파이썬 리액티브하게 짜기 - PyCon Korea 2017
파이썬 리액티브하게 짜기 - PyCon Korea 2017파이썬 리액티브하게 짜기 - PyCon Korea 2017
파이썬 리액티브하게 짜기 - PyCon Korea 2017Kenneth Ceyer
 

Tendances (20)

Azure Search 大全
Azure Search 大全Azure Search 大全
Azure Search 大全
 
設計・構築においてのドキュメントの重要性について
設計・構築においてのドキュメントの重要性について設計・構築においてのドキュメントの重要性について
設計・構築においてのドキュメントの重要性について
 
LLD(ローレベルディスカバリ)を弄り倒せ、zabbix_senderを併用してらくらく可視化
LLD(ローレベルディスカバリ)を弄り倒せ、zabbix_senderを併用してらくらく可視化LLD(ローレベルディスカバリ)を弄り倒せ、zabbix_senderを併用してらくらく可視化
LLD(ローレベルディスカバリ)を弄り倒せ、zabbix_senderを併用してらくらく可視化
 
計算量のはなし(Redisを使うなら必読!O(logN)など)
計算量のはなし(Redisを使うなら必読!O(logN)など)計算量のはなし(Redisを使うなら必読!O(logN)など)
計算量のはなし(Redisを使うなら必読!O(logN)など)
 
セキュリティを楽しむ(CTFとbugbountyの始め方)
セキュリティを楽しむ(CTFとbugbountyの始め方)セキュリティを楽しむ(CTFとbugbountyの始め方)
セキュリティを楽しむ(CTFとbugbountyの始め方)
 
Pull request時の画面差分取得の自動化
Pull request時の画面差分取得の自動化Pull request時の画面差分取得の自動化
Pull request時の画面差分取得の自動化
 
Beyond the Twelve-Factor App
Beyond the Twelve-Factor AppBeyond the Twelve-Factor App
Beyond the Twelve-Factor App
 
フリーでできるセキュリティチェック OpenVAS CLI編
フリーでできるセキュリティチェック OpenVAS CLI編フリーでできるセキュリティチェック OpenVAS CLI編
フリーでできるセキュリティチェック OpenVAS CLI編
 
ラズベリー・パイでプログラミングと電子工作を体験してみよう
ラズベリー・パイでプログラミングと電子工作を体験してみようラズベリー・パイでプログラミングと電子工作を体験してみよう
ラズベリー・パイでプログラミングと電子工作を体験してみよう
 
CVE、JVN番号の取得経験者になろう!
CVE、JVN番号の取得経験者になろう!CVE、JVN番号の取得経験者になろう!
CVE、JVN番号の取得経験者になろう!
 
Delta Lake with Synapse dataflow
Delta Lake with Synapse dataflowDelta Lake with Synapse dataflow
Delta Lake with Synapse dataflow
 
コンテナイメージの脆弱性スキャンについて
コンテナイメージの脆弱性スキャンについてコンテナイメージの脆弱性スキャンについて
コンテナイメージの脆弱性スキャンについて
 
ITコミュニティと情報発信に共通する成長と貢献の要素
ITコミュニティと情報発信に共通する成長と貢献の要素ITコミュニティと情報発信に共通する成長と貢献の要素
ITコミュニティと情報発信に共通する成長と貢献の要素
 
JMeter入門
JMeter入門JMeter入門
JMeter入門
 
今夜わかるWebアプリケーション脆弱性診断 (OWASP Day 758 / 2018)
今夜わかるWebアプリケーション脆弱性診断 (OWASP Day 758 / 2018)今夜わかるWebアプリケーション脆弱性診断 (OWASP Day 758 / 2018)
今夜わかるWebアプリケーション脆弱性診断 (OWASP Day 758 / 2018)
 
SecurityCamp2015「バグハンティング入門」
SecurityCamp2015「バグハンティング入門」SecurityCamp2015「バグハンティング入門」
SecurityCamp2015「バグハンティング入門」
 
Data Factoryの勘所・大事なところ
Data Factoryの勘所・大事なところData Factoryの勘所・大事なところ
Data Factoryの勘所・大事なところ
 
130613-debug
130613-debug130613-debug
130613-debug
 
.NET 7におけるBlazorの新機能
.NET 7におけるBlazorの新機能.NET 7におけるBlazorの新機能
.NET 7におけるBlazorの新機能
 
파이썬 리액티브하게 짜기 - PyCon Korea 2017
파이썬 리액티브하게 짜기 - PyCon Korea 2017파이썬 리액티브하게 짜기 - PyCon Korea 2017
파이썬 리액티브하게 짜기 - PyCon Korea 2017
 

Similaire à Android動態ui介面設計

Android進階UI控制元件
Android進階UI控制元件Android進階UI控制元件
Android進階UI控制元件艾鍗科技
 
Layout Management - Android and Qt
Layout Management - Android and QtLayout Management - Android and Qt
Layout Management - Android and Qtrogeryi
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程yiditushe
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程appollo0312
 
3 hibernate映射元素和类型
3 hibernate映射元素和类型3 hibernate映射元素和类型
3 hibernate映射元素和类型Zelin Wang
 
Asp.net mvc網站的從無到有
Asp.net mvc網站的從無到有Asp.net mvc網站的從無到有
Asp.net mvc網站的從無到有Wade Huang
 
twMVC#01 | ASP.NET MVC 的第一次親密接觸
twMVC#01 | ASP.NET MVC 的第一次親密接觸twMVC#01 | ASP.NET MVC 的第一次親密接觸
twMVC#01 | ASP.NET MVC 的第一次親密接觸twMVC
 
Azure Data Lake 簡介
Azure Data Lake 簡介Azure Data Lake 簡介
Azure Data Lake 簡介Herman Wu
 
RockStor - A Cloud Object System based on Hadoop
RockStor -  A Cloud Object System based on HadoopRockStor -  A Cloud Object System based on Hadoop
RockStor - A Cloud Object System based on HadoopSchubert Zhang
 
Angular js twmvc#17
Angular js twmvc#17Angular js twmvc#17
Angular js twmvc#17twMVC
 
Servlet & JSP 教學手冊第二版 - 第 5 章:Servlet 進階 API、過濾器與傾聽器
Servlet & JSP 教學手冊第二版 - 第 5 章:Servlet 進階 API、過濾器與傾聽器Servlet & JSP 教學手冊第二版 - 第 5 章:Servlet 進階 API、過濾器與傾聽器
Servlet & JSP 教學手冊第二版 - 第 5 章:Servlet 進階 API、過濾器與傾聽器Justin Lin
 
整合資料庫
整合資料庫整合資料庫
整合資料庫Justin Lin
 
KISSY Editor Design 2
KISSY Editor Design 2KISSY Editor Design 2
KISSY Editor Design 2yiming he
 
Struts快速学习指南
Struts快速学习指南Struts快速学习指南
Struts快速学习指南yiditushe
 
山頂洞人日記 - 回歸到最純樸的開發
山頂洞人日記 -  回歸到最純樸的開發山頂洞人日記 -  回歸到最純樸的開發
山頂洞人日記 - 回歸到最純樸的開發koji lin
 
2011 JavaTwo JSF 2.0
2011 JavaTwo JSF 2.02011 JavaTwo JSF 2.0
2011 JavaTwo JSF 2.0Anthony Chen
 
RxJS 6 新手入門
RxJS 6 新手入門RxJS 6 新手入門
RxJS 6 新手入門Will Huang
 
Mvc training
Mvc trainingMvc training
Mvc trainingxioxu
 
Ch02 撰寫與設定Servlet
Ch02 撰寫與設定ServletCh02 撰寫與設定Servlet
Ch02 撰寫與設定ServletJustin Lin
 

Similaire à Android動態ui介面設計 (20)

Android進階UI控制元件
Android進階UI控制元件Android進階UI控制元件
Android進階UI控制元件
 
敦群學院-SharePoint精英計畫-系統開發-Day 3
敦群學院-SharePoint精英計畫-系統開發-Day 3敦群學院-SharePoint精英計畫-系統開發-Day 3
敦群學院-SharePoint精英計畫-系統開發-Day 3
 
Layout Management - Android and Qt
Layout Management - Android and QtLayout Management - Android and Qt
Layout Management - Android and Qt
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程
 
3 hibernate映射元素和类型
3 hibernate映射元素和类型3 hibernate映射元素和类型
3 hibernate映射元素和类型
 
Asp.net mvc網站的從無到有
Asp.net mvc網站的從無到有Asp.net mvc網站的從無到有
Asp.net mvc網站的從無到有
 
twMVC#01 | ASP.NET MVC 的第一次親密接觸
twMVC#01 | ASP.NET MVC 的第一次親密接觸twMVC#01 | ASP.NET MVC 的第一次親密接觸
twMVC#01 | ASP.NET MVC 的第一次親密接觸
 
Azure Data Lake 簡介
Azure Data Lake 簡介Azure Data Lake 簡介
Azure Data Lake 簡介
 
RockStor - A Cloud Object System based on Hadoop
RockStor -  A Cloud Object System based on HadoopRockStor -  A Cloud Object System based on Hadoop
RockStor - A Cloud Object System based on Hadoop
 
Angular js twmvc#17
Angular js twmvc#17Angular js twmvc#17
Angular js twmvc#17
 
Servlet & JSP 教學手冊第二版 - 第 5 章:Servlet 進階 API、過濾器與傾聽器
Servlet & JSP 教學手冊第二版 - 第 5 章:Servlet 進階 API、過濾器與傾聽器Servlet & JSP 教學手冊第二版 - 第 5 章:Servlet 進階 API、過濾器與傾聽器
Servlet & JSP 教學手冊第二版 - 第 5 章:Servlet 進階 API、過濾器與傾聽器
 
整合資料庫
整合資料庫整合資料庫
整合資料庫
 
KISSY Editor Design 2
KISSY Editor Design 2KISSY Editor Design 2
KISSY Editor Design 2
 
Struts快速学习指南
Struts快速学习指南Struts快速学习指南
Struts快速学习指南
 
山頂洞人日記 - 回歸到最純樸的開發
山頂洞人日記 -  回歸到最純樸的開發山頂洞人日記 -  回歸到最純樸的開發
山頂洞人日記 - 回歸到最純樸的開發
 
2011 JavaTwo JSF 2.0
2011 JavaTwo JSF 2.02011 JavaTwo JSF 2.0
2011 JavaTwo JSF 2.0
 
RxJS 6 新手入門
RxJS 6 新手入門RxJS 6 新手入門
RxJS 6 新手入門
 
Mvc training
Mvc trainingMvc training
Mvc training
 
Ch02 撰寫與設定Servlet
Ch02 撰寫與設定ServletCh02 撰寫與設定Servlet
Ch02 撰寫與設定Servlet
 

Plus de 艾鍗科技

TinyML - 4 speech recognition
TinyML - 4 speech recognition TinyML - 4 speech recognition
TinyML - 4 speech recognition 艾鍗科技
 
Appendix 1 Goolge colab
Appendix 1 Goolge colabAppendix 1 Goolge colab
Appendix 1 Goolge colab艾鍗科技
 
Project-IOT於餐館系統的應用
Project-IOT於餐館系統的應用Project-IOT於餐館系統的應用
Project-IOT於餐館系統的應用艾鍗科技
 
02 IoT implementation
02 IoT implementation02 IoT implementation
02 IoT implementation艾鍗科技
 
Tiny ML for spark Fun Edge
Tiny ML for spark Fun EdgeTiny ML for spark Fun Edge
Tiny ML for spark Fun Edge艾鍗科技
 
2. 機器學習簡介
2. 機器學習簡介2. 機器學習簡介
2. 機器學習簡介艾鍗科技
 
5.MLP(Multi-Layer Perceptron)
5.MLP(Multi-Layer Perceptron) 5.MLP(Multi-Layer Perceptron)
5.MLP(Multi-Layer Perceptron) 艾鍗科技
 
心率血氧檢測與運動促進
心率血氧檢測與運動促進心率血氧檢測與運動促進
心率血氧檢測與運動促進艾鍗科技
 
利用音樂&情境燈幫助放鬆
利用音樂&情境燈幫助放鬆利用音樂&情境燈幫助放鬆
利用音樂&情境燈幫助放鬆艾鍗科技
 
IoT感測器驅動程式 在樹莓派上實作
IoT感測器驅動程式在樹莓派上實作IoT感測器驅動程式在樹莓派上實作
IoT感測器驅動程式 在樹莓派上實作艾鍗科技
 
無線聲控遙控車
無線聲控遙控車無線聲控遙控車
無線聲控遙控車艾鍗科技
 
最佳光源的研究和實作
最佳光源的研究和實作最佳光源的研究和實作
最佳光源的研究和實作 艾鍗科技
 
無線監控網路攝影機與控制自走車
無線監控網路攝影機與控制自走車無線監控網路攝影機與控制自走車
無線監控網路攝影機與控制自走車 艾鍗科技
 
Reinforcement Learning
Reinforcement LearningReinforcement Learning
Reinforcement Learning艾鍗科技
 
人臉辨識考勤系統
人臉辨識考勤系統人臉辨識考勤系統
人臉辨識考勤系統艾鍗科技
 
智慧家庭Smart Home
智慧家庭Smart Home智慧家庭Smart Home
智慧家庭Smart Home艾鍗科技
 

Plus de 艾鍗科技 (20)

TinyML - 4 speech recognition
TinyML - 4 speech recognition TinyML - 4 speech recognition
TinyML - 4 speech recognition
 
Appendix 1 Goolge colab
Appendix 1 Goolge colabAppendix 1 Goolge colab
Appendix 1 Goolge colab
 
Project-IOT於餐館系統的應用
Project-IOT於餐館系統的應用Project-IOT於餐館系統的應用
Project-IOT於餐館系統的應用
 
02 IoT implementation
02 IoT implementation02 IoT implementation
02 IoT implementation
 
Tiny ML for spark Fun Edge
Tiny ML for spark Fun EdgeTiny ML for spark Fun Edge
Tiny ML for spark Fun Edge
 
Openvino ncs2
Openvino ncs2Openvino ncs2
Openvino ncs2
 
Step motor
Step motorStep motor
Step motor
 
2. 機器學習簡介
2. 機器學習簡介2. 機器學習簡介
2. 機器學習簡介
 
5.MLP(Multi-Layer Perceptron)
5.MLP(Multi-Layer Perceptron) 5.MLP(Multi-Layer Perceptron)
5.MLP(Multi-Layer Perceptron)
 
3. data features
3. data features3. data features
3. data features
 
心率血氧檢測與運動促進
心率血氧檢測與運動促進心率血氧檢測與運動促進
心率血氧檢測與運動促進
 
利用音樂&情境燈幫助放鬆
利用音樂&情境燈幫助放鬆利用音樂&情境燈幫助放鬆
利用音樂&情境燈幫助放鬆
 
IoT感測器驅動程式 在樹莓派上實作
IoT感測器驅動程式在樹莓派上實作IoT感測器驅動程式在樹莓派上實作
IoT感測器驅動程式 在樹莓派上實作
 
無線聲控遙控車
無線聲控遙控車無線聲控遙控車
無線聲控遙控車
 
最佳光源的研究和實作
最佳光源的研究和實作最佳光源的研究和實作
最佳光源的研究和實作
 
無線監控網路攝影機與控制自走車
無線監控網路攝影機與控制自走車無線監控網路攝影機與控制自走車
無線監控網路攝影機與控制自走車
 
Reinforcement Learning
Reinforcement LearningReinforcement Learning
Reinforcement Learning
 
Linux Device Tree
Linux Device TreeLinux Device Tree
Linux Device Tree
 
人臉辨識考勤系統
人臉辨識考勤系統人臉辨識考勤系統
人臉辨識考勤系統
 
智慧家庭Smart Home
智慧家庭Smart Home智慧家庭Smart Home
智慧家庭Smart Home
 

Dernier

1.🎉“入侵大学入学考试中心修改成绩”来袭!ALEVEL替考大揭秘,轻松搞定考试成绩! 💥你还在为无法进入大学招生系统而烦恼吗?想知道如何通过技术手段更改...
1.🎉“入侵大学入学考试中心修改成绩”来袭!ALEVEL替考大揭秘,轻松搞定考试成绩! 💥你还在为无法进入大学招生系统而烦恼吗?想知道如何通过技术手段更改...1.🎉“入侵大学入学考试中心修改成绩”来袭!ALEVEL替考大揭秘,轻松搞定考试成绩! 💥你还在为无法进入大学招生系统而烦恼吗?想知道如何通过技术手段更改...
1.🎉“入侵大学入学考试中心修改成绩”来袭!ALEVEL替考大揭秘,轻松搞定考试成绩! 💥你还在为无法进入大学招生系统而烦恼吗?想知道如何通过技术手段更改...黑客 接单【TG/微信qoqoqdqd】
 
泽兰应用科学大学毕业证制作/定制国外大学录取通知书/购买一个假的建国科技大学硕士学位证书
泽兰应用科学大学毕业证制作/定制国外大学录取通知书/购买一个假的建国科技大学硕士学位证书泽兰应用科学大学毕业证制作/定制国外大学录取通知书/购买一个假的建国科技大学硕士学位证书
泽兰应用科学大学毕业证制作/定制国外大学录取通知书/购买一个假的建国科技大学硕士学位证书jakepaige317
 
educ6506presentationtc3302771-240427173057-06a46de5.pptx
educ6506presentationtc3302771-240427173057-06a46de5.pptxeduc6506presentationtc3302771-240427173057-06a46de5.pptx
educ6506presentationtc3302771-240427173057-06a46de5.pptxmekosin001123
 
哪里可以购买日本筑波学院大学学位记/做个假的文凭可认证吗/仿制日本大学毕业证/意大利语CELI证书定制
哪里可以购买日本筑波学院大学学位记/做个假的文凭可认证吗/仿制日本大学毕业证/意大利语CELI证书定制哪里可以购买日本筑波学院大学学位记/做个假的文凭可认证吗/仿制日本大学毕业证/意大利语CELI证书定制
哪里可以购买日本筑波学院大学学位记/做个假的文凭可认证吗/仿制日本大学毕业证/意大利语CELI证书定制jakepaige317
 
EDUC6506(001)_ClassPresentation_2_TC330277 (1).pptx
EDUC6506(001)_ClassPresentation_2_TC330277 (1).pptxEDUC6506(001)_ClassPresentation_2_TC330277 (1).pptx
EDUC6506(001)_ClassPresentation_2_TC330277 (1).pptxmekosin001123
 
EDUC6506_ClassPresentation_TC330277 (1).pptx
EDUC6506_ClassPresentation_TC330277 (1).pptxEDUC6506_ClassPresentation_TC330277 (1).pptx
EDUC6506_ClassPresentation_TC330277 (1).pptxmekosin001123
 

Dernier (6)

1.🎉“入侵大学入学考试中心修改成绩”来袭!ALEVEL替考大揭秘,轻松搞定考试成绩! 💥你还在为无法进入大学招生系统而烦恼吗?想知道如何通过技术手段更改...
1.🎉“入侵大学入学考试中心修改成绩”来袭!ALEVEL替考大揭秘,轻松搞定考试成绩! 💥你还在为无法进入大学招生系统而烦恼吗?想知道如何通过技术手段更改...1.🎉“入侵大学入学考试中心修改成绩”来袭!ALEVEL替考大揭秘,轻松搞定考试成绩! 💥你还在为无法进入大学招生系统而烦恼吗?想知道如何通过技术手段更改...
1.🎉“入侵大学入学考试中心修改成绩”来袭!ALEVEL替考大揭秘,轻松搞定考试成绩! 💥你还在为无法进入大学招生系统而烦恼吗?想知道如何通过技术手段更改...
 
泽兰应用科学大学毕业证制作/定制国外大学录取通知书/购买一个假的建国科技大学硕士学位证书
泽兰应用科学大学毕业证制作/定制国外大学录取通知书/购买一个假的建国科技大学硕士学位证书泽兰应用科学大学毕业证制作/定制国外大学录取通知书/购买一个假的建国科技大学硕士学位证书
泽兰应用科学大学毕业证制作/定制国外大学录取通知书/购买一个假的建国科技大学硕士学位证书
 
educ6506presentationtc3302771-240427173057-06a46de5.pptx
educ6506presentationtc3302771-240427173057-06a46de5.pptxeduc6506presentationtc3302771-240427173057-06a46de5.pptx
educ6506presentationtc3302771-240427173057-06a46de5.pptx
 
哪里可以购买日本筑波学院大学学位记/做个假的文凭可认证吗/仿制日本大学毕业证/意大利语CELI证书定制
哪里可以购买日本筑波学院大学学位记/做个假的文凭可认证吗/仿制日本大学毕业证/意大利语CELI证书定制哪里可以购买日本筑波学院大学学位记/做个假的文凭可认证吗/仿制日本大学毕业证/意大利语CELI证书定制
哪里可以购买日本筑波学院大学学位记/做个假的文凭可认证吗/仿制日本大学毕业证/意大利语CELI证书定制
 
EDUC6506(001)_ClassPresentation_2_TC330277 (1).pptx
EDUC6506(001)_ClassPresentation_2_TC330277 (1).pptxEDUC6506(001)_ClassPresentation_2_TC330277 (1).pptx
EDUC6506(001)_ClassPresentation_2_TC330277 (1).pptx
 
EDUC6506_ClassPresentation_TC330277 (1).pptx
EDUC6506_ClassPresentation_TC330277 (1).pptxEDUC6506_ClassPresentation_TC330277 (1).pptx
EDUC6506_ClassPresentation_TC330277 (1).pptx
 

Android動態ui介面設計

  • 2. Android動態UI介面設計 Android動態元件設計  ListView  Gallery  GridView  ImageSwitch Adapter元件  ArrayAdapter  SimpleAdapter  自定Adapter 226
  • 3. 進階UI控制元件-Adapter使用 • Android 框架只負責應用程式的流程架構,框架設計師並不會知道最 終使用框架開發出的Application長的是什麼樣子。 • 應用程式設計師並不能直接去修改Android框架的內容,如此會造成 相容性問題,因此無法直接透過框架修改來決定應用程式的長相. • 為解決上述兩個問題,在Android裡設計了Adapter類別來做為 Android框架與應用程式之間的橋樑 • 為應付各種不同的資料數據來源,與不同的View元件,因此發展出各 式不同的Adapter元件。 為你把關每一道 學習品質 227
  • 4. 進階UI控制元件-Adapter使用 Adapter • 常見的Adapter的類別 ListAdapter SpinnerAdapter BaseAdapter ArrayAdapter CursorAdapter SimpleAdapter ResourceCursorAdapter • 常見Adapter對應到UI端的類別 SimpleCursorAdapter ViewGroup AdapterView AbsListView AbsSpinner ListView GridView Gallery Spinner 為你把關每一道 學習品質 228
  • 5. 進階UI控制元件-Adapter使用 • ArrayAdapter用途 • 作用為陣列與ListView之間的橋梁 • 可將陣列中定義的資料逐一的對應到ListView之中顯示 • 一般ArrayAdapter中顯示的ListView每行通常只有一個TextView ArrayList ListView Jarey Jarey TextView-Two John John ArrayAdapter May TextView-Two Ken May TextView-Two Ken TextView-Two 為你把關每一道 學習品質 229
  • 6. 進階UI控制元件-Adapter使用 • SimpleAdapter用途 • simpleAdapter可以定製每一列ListView中要顯示的內容 • 一般ListView中每一列的版面配置(Layout)會撰寫在XML檔中,在 由SimpleAdapter負責將內容(Data)填入Layout中的元件(View)。 ArrayList ListView HashMap Jarey 09222222 Name Jarey John Phone 0922 SimpleAdapter 09333333 HashMap May 09444444 Name John Phone 0933 Ken 095555555 為你把關每一道 學習品質 230
  • 7. 進階UI控制元件-Adapter使用 • 建構式ArrayAdapter (Context context, int resource, int textViewResourceId, T[] objects) • contex:要顯示的Context容器 • resource:layout定義,可以使用Android系統內建,或是自定layout. • textViewResourceId:位於layout中的textView,用來顯示data內容. • data:要顯示的資料內容 • 建構式SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to) • contex:要顯示的Context容器 • data:基於Map的List. Map中包含了ListView每一列所需要的資料 • resource:顯示的Layout版型,此layout中至少要包含在to參數中所出現的 View。可使系統提供的layout,亦可自行定義 • from:名稱陣列,每一個名稝都對應Data中的索引鍵。 • to:為TextView類形的陣列,必須要在layout中可以被索引到。 為你把關每一道 學習品質 231
  • 8. 範例練習 範例專案名: ex05_01_Spinner 練習目標:  學習使用Spinner,利用ArrayAdapter提供 Spinner內容。 程式撰寫  建置Spinner元件,其內容資料於XML中利用 string array xml標籤編寫內容。  於Activity中讀入string array內容至記憶體,並套 用ArrayAdapter提供資料給Spiiner元件。 操作練習  模擬器練習,分練習XML方式導入靜態資料,與 使用Adapter方式動態載入資料兩種應用方式。 為你把關每一道 學習品質 232
  • 9. 進階UI控制元件-ListView • ListView為Android中用來顯示大量資 料的一個很重要的UI介面 • 由於手機受限於螢幕大小,當欲顯示 的資料數量超過一個頁面可以顯示時, 就可以利用ListView來做資料顯示 • ListView需搭配Adapter使用, ListView會自動依顯示控制的需求透 過Adapter介面取得資料。 • ListView提供OnItemClickListener() 方法,可以取得用戶的動件事件(例 如點選了那一個ListView元件) 為你把關每一道 學習品質 233
  • 10. 進階UI控制元件-ListView • ListView使用方式 • set data source to Adapter • get ListView from R.layout • set adapter to ListView • set click listener for each list item • ListView Event處理函式 • onItemClick(AdapterView<?> parent, View view, int position, long id) • onItemLongClick(AdapterView<?> parent, View view, int position, long id) • onItemSelected(AdapterView<?> parent, View view, int position, long id) 為你把關每一道 學習品質 234
  • 11. 範例練習 範例專案名: ex05_02_Adapter 練習目標:  了解各式adapter的使用  了解ListView與adapter之間的關係與運作 流程 程式撰寫  設計一ListView元件,並練習接上各式不 同的adapter與不同的資料來源串接  SimpleAdapter, ArrayAdapter 操作練習  透過模擬器操作不同的Activity,每一個 Activity代表一個不同Adapter的連接範例。 為你把關每一道 學習品質 235
  • 12. 進階UI控制元件-ListActivity • ListActivity使用時機 • 當一個Activity中只有顯示ListView,而且此ListView又會填滿整 個螢幕,此時可以直接使用ListActivity來代替Activity。 • ListActivity為一個包含了ListView的Activity,以wrapper的方式將 ListVIew包裝起來,方便更容易與直接的控制。 • ListActivity 預設ID元件 • ListActivity使用的layout檔中必須定義一個ListView,且此 ListView的id必須固定為[ @id/android:list ] • 另外可定義一個TextView當ListView裡沒有資料時可以顯示,此 TextView的id必須固定為[ @id/android:empty] 為你把關每一道 學習品質 236
  • 13. 進階UI控制元件-ListView • ListActivity使用方式 • Application extended ListActivity • set data source to Adapter • get ListView from ListActivity • set adapter to ListView • set click listener for each list item • ListView Event處理函式 • 在ListActivity中不用註冊Listener,而是直接以覆寫 (Override)來進行事件處理 • 可處理的Event函式與ListView相同 為你把關每一道 學習品質 237
  • 14. 範例練習 範例專案名: ex05_03_ListActivity 練習目標:  了解ListActivity的應用 程式撰寫  修改前一隻範例程式,試著將其改寫成 ListActivity  Activity直接繼承自ListActivity 操作練習  透過模擬器操作,注意ListActivity與ListView在對 於listener event 處理的寫法是否有所不同? 為你把關每一道 學習品質 238
  • 15. 進階UI控制元件-Adapter使用 • 自行定義Adapter內容 • 繼承(extended)BaseAdapter • 於建構式接收要處理的資料(Data)來源 • 覆寫(Override)以下四個Method • public int getCount() ; • 傳回Data的數量.(ListView的列數) • public Object getItem(int position); • 傳回指定的Data元件. • public long getItemId(int position); • 傳回Data的識別ID • public View getView(int position, View convertView, ViewGroup parent) • 傳回Layout與Data組合後的View元件(顯示於畫面上) • ※當Data內容有變更時,必須呼叫notifyDataSetChanged才會更新 ListView中的內容。 239 為你把關每一道 學習品質
  • 16. 進階UI控制元件-Adapter使用 • Adapter與Android框架運作流程 Android Activity AdapterView Adapter 框架 3.getCount() 4.getView() Application 2.setContentView() 1.onCreate() Map MyAdapter ListActivity Array Data Layout Cursor View XML 為你把關每一道 學習品質 240
  • 17. 範例練習 範例專案名: ex05_04_ImageAdapter 練習目標:  了解如何自行擴充Adapter類別  學習如何以高效率,最佳化記憶體方式設計 Adapter 程式撰寫  設計一個ImageAdapter類別,繼承至BaseAdapter 抽像類別  實作BaseAdapter的四個抽像函式  利用系統快取與ViewHolder提高Adapter的效能 操作練習  透過模擬器操作 為你把關每一道 學習品質 241
  • 18. 進階UI控制元件-ListView資料快取問題 • ListView為了節省記憶體與提高顯示的效能,會利用快取 機制,在ListView滑動時會重覆利用己使用過,目前不在 畫面上的View元件。 ConvertView ConvertView 重覆利用 ConvertView 由下往上滑動 ConvertView ConvertView 為你把關每一道 學習品質 242
  • 19. 進階UI控制元件-ListView內元件如何監聽事件 • ListView本身可以透過註冊setOnItemSelectListener來監 聽用戶點擊了那一條List Item。 • 若希望能為List Item中的每一個View元件單獨的設置 Listener事件,那麼需要注意以下二個問題: • ListView本身具有快取,List Item是重覆利用的,這將 導致用戶滑動List後,所點擊的元件可能與你當初註冊 的Listener元件不一致(如點了第5個Item中的一個 Button,但實際上第5個Item等同於重覆利用的第1個 Item) 為你把關每一道 學習品質 243
  • 20. 進階UI控制元件-ListView內元件如何監聽事件 • 由於Item元件是重覆利用,因此你將無法判斷用戶點 擊的Button為第幾個Item選項的Button,同時若你在每 次getView時都為新的Item重新設置新的Listener那麼 將會造成記憶體大量的浪費,同時也會降低顯示的效 能。 重覆利用 點擊第4個Item內的checkbox, 但呼叫的listener將與第1個 item相同。 為你把關每一道 學習品質 244
  • 21. 進階UI控制元件-ListView內元件如何監聽事件 • 解決LIstView 內Item元件的監聽事件的方法,可以透過 View.setTag方式,為將該List Item的資料快取在要被監 聽的View元件身上。如此當用戶點擊了CheckBox後,可 以在透過getTag的方式取得該List Item的資料做為判斷。 List Data Set setTag(Object); Profile1 Profile2 重覆利用 Profile3 Profile4 為你把關每一道 學習品質 245
  • 22. 進階UI控制元件-ListView資料快取問題 • 重覆使用的View元件會造成顯示不一致的問題,由其是當 View元件中有使用到如CheckBox這類的選單元件。 雖然只勾了一個選項。但往 上滑動時會造成第五個選項 看起來也是被勾選的 重覆利用 由下往上滑動 為你把關每一道 學習品質 246
  • 23. 進階UI控制元件-ListView資料快取問題 • 解決View元件顯示不一致的狀況,必須將ListView中每一 條的UI狀態記錄起來,在每次呼叫getView時去重新設定 UI狀態。 List Data狀態表 勾選 由下往上滑動 未勾選 重覆利用 未勾選 未勾選 未勾選 在準備顯示到畫面上前,重新將 View元件上的UI狀態做更新,將 勾選取消掉。 為你把關每一道 學習品質 247
  • 24. 範例練習 範例專案名: ex05_04_ImageAdapter 練習目標:  直接修改ImageAdapter範例,加入刪除模式功能  於刪除模式下顯示CheckBox元件提供用戶勾選。 程式撰寫  建置ListData 狀態表記錄每個ListView中每個元件的UI 狀態。  將ListView中的Layout所有的元件forcues狀能設為false 以避免遮避到ListView本身的onItemSelect事件。  註冊CheckBox的Onclick事件,並將狀態資料帶入至 Tag中提供供識別所點選的元件。 操作練習  透過模擬器操作 為你把關每一道 學習品質 248
  • 25. 進階UI控制元件-ImageSwitch&Gallery • ImageSwitch ViewGroup • 主要用來做圖片切換與自動播放用. AdapterView 可支援不同的進場與退場動畫特效 AbsSpinner • Gallery Gallery • 提供一個拖拉式圖片瀏覽與選擇介面 • 僅支援水平擺設方式 • 通常搭配ImageSwitch可用來做成簡 易的圖片瀏覽器。 為你把關每一道 學習品質 249
  • 26. 進階UI控制元件-ImageSwitch&Gallery • ImageSwitch元件 • XML宣告方式 • 程式碼使用方式 功能 程式碼 package Import android.widget.ImageSwitch; Reference ImageSwitch sw1 = (ImageSwitch) findViewById(R.id.imsw1); set sw1.setFactory(ViewSwitch.ViewFactory factory) sw1.setInAnimation(Animation inAnimation) sw1.setOutAnimation(Animation outAnimation) sw1.setImageResource (int resid) 為你把關每一道 學習品質 250
  • 27. 進階UI控制元件-ImageSwitch&Gallery • Gallery元件 • XML宣告方式 • 程式碼使用方式 功能 程式碼 package Import android.widget.Gallery; Reference Gallery gal1 = (Gallery) findViewById(R.id.gallery); set gal1.setAdapter(SpinnerAdapter adapter); Call back gal1.setOnItemSelectedListener(AdapterView.OnItemSelect edListener listener); 為你把關每一道 學習品質 251
  • 28. 範例練習 範例專案名: ex05_05_Gallery 練習目標:  透過Gallery與ImageSwitch設計一個簡易的相片 瀏覽器  復習先前教過的Adapter的應用 程式撰寫  撰寫一個Activity包含ImageSwitch與Gallery元件。  撰寫一個ImageAdapter提供給Gallery。 操作練習  透過模擬器操作 為你把關每一道 學習品質 252
  • 29. 進階UI控制元件-GridView • GridView為網格檢視元件,可以將很很多圖片以 ViewGroup 固定的大小排列顯示在畫面上可用來做為相簿與圖 片瀏覽等應用 AdapterView • GridView的資料取至於ListAdapter,一般要用做 AbsListView 相簿使用需要自行實作ImageAdapter(繼承至 BaseAdapter). GridView 為你把關每一道 學習品質 253
  • 30. 進階UI控制元件-GridView • GridView元件 • XML宣告方式 • 程式碼使用方式 功能 程式碼 package Import android.widget.GridView; Reference GridView grid= (GridView ) findViewById(R.id.grid); set grid.setAdapter(BaseAdapter adapter); Call back grid.setOnItemSelectedListener(AdapterView.OnItemSele ctedListener listener); 為你把關每一道 學習品質 254
  • 31. 第7節: Android 通知元件設計 Android Widget開發
  • 32. Android 通知元件設計 Android Menu元件設計  Option Menu  Context Menu Android通知元件設計  Dialog  Toast  Notification  Menu AppWidget桌面元件設計  Widget開發上的限制  Remove View的互動方式 256
  • 33. 進階UI控制元件-Menu選單 • Menu選單操作元件 • Option Menu • 按下menu建後顯 示 • Context Menu • 長時間按下一個視 窗後顯示 • Submenu • 子選單,可被 option或context Menu所呼叫 為你把關每一道 學習品質 257
  • 34. 進階UI控制元件-Option Menu • Option Menu • 選單位於整體畫面的下方,透過按下手機上的 Menu按鈕顯示 • 一個畫面最多可以安置6個選單項目,不支援 Checkbox及RadioButton • 超過6個選單的項目將會以擴充列的方式顯示。 • Option Menu 使用XML宣告 為你把關每一道 學習品質 258
  • 35. 進階UI控制元件-Option Menu • Inflating Option Menu Resource File • 透過MenuInflater.inflate() 協助載入xml資源檔 • public void inflate (int menuRes, Menu menu) @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.game_menu, menu); return true; } 為你把關每一道 學習品質 259
  • 36. 進階UI控制元件-Option Menu • 建立Option Menu 使用MenuItem add函式 Public boolean onCreateOptionsMenu(Menu menu){ menu.add(0,MENU_ITEM_ID1, 0 “ MENU_ITEM_1”); menu.add(0,MENU_ITEM_ID2, 0 “ MENU_ITEM_2”); return true; } • MenuItem add函式 • public abstract MenuItem add (int groupId, int itemId, int order, int titleRes) • groupid:群組ID • itemid:項目ID • order:排序方式 • titleRes:每一個Item上的標題 為你把關每一道 學習品質 260
  • 37. 進階UI控制元件-Option Menu • 建立Menu • Call Back Function 為你把關每一道 學習品質 261
  • 38. 進階UI控制元件-Context Menu • Context Menu • 與在PC上的滑鼠右鍵功能類似,當按位某一 個View 2秒鐘,就會出現一個浮動式的 Context Menu。 • 較常使用在ListView上。 • 建立Option Menu 使用MenuItem add函式 為你把關每一道 學習品質 262
  • 39. 進階UI控制元件-Context Menu • Context Menu的callback函式 為你把關每一道 學習品質 263
  • 40. 進階UI控制元件-Submenu • Submenu • Context Menu與Option Menu可以在內嵌一個 子選單(Submenu)做為擴充。 • 子選單(Submenu)不能在擴充子選單 • 建立Submenu 使用xml 為你把關每一道 學習品質 264
  • 41. 進階UI控制元件-Submenu • 建立Submenu 使用SubMenu addSubMenu函式 @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); SubMenu fileMenu = menu.addSubMenu(GALLERY, SUBMANU01, Menu.NONE, "File"); SubMenu editMenu = menu.addSubMenu(GALLERY, SUBMANU02, Menu.NONE, "Edit"); fileMenu.add(GALLERY, MANU01, Menu.NONE, "new"); fileMenu.add(GALLERY, MANU02, Menu.NONE, "open"); fileMenu.add(GALLERY, MANU03, Menu.NONE, "save"); editMenu.add(GALLERY, MANU04, Menu.NONE, "undo"); editMenu.add(GALLERY, MANU05, Menu.NONE, "redo"); return true; } 為你把關每一道 學習品質 265
  • 42. 進階UI控制元件-Submenu • 處理Callback函式 @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case MANU01: case MANU02: case MANU03: case MANU04: case MANU05: String itemid = Integer.toString(item.getItemId()); String title = item.getTitle().toString(); showAlertDialog("項目ID = " + itemid + "n" + "標題 = " + title); return true; } return super.onOptionsItemSelected(item); } 為你把關每一道 學習品質 266
  • 43. 範例練習 範例專案名: ex06_01_01_OptionsMenu ex06_01_02_ContextMenu ex06_01_03_Submenu 練習目標:  學習各種Menu的應用場合與撰寫方式 程式撰寫  透過覆寫onCreateOptionsMenu函式來加入 Menu選單  透過覆寫onOptionsItemSelected來接收使用者的 選擇 操作練習  透過模擬器操作,透過按下手機上的Menu鍵來 呼叫出Menu選單。 為你把關每一道 學習品質 267
  • 44. Android通知元件-Notifications • Android提供三種不同的通知元件 • Toast • 短暫警示與通知,顯示數秒後會 自動消失 Toast Notification • Dialog • 對話窗可與使用者做簡單交談式 互動,一般用來做進度提示或確 認使用者的需求。 Dialog Notification • Status Bar Notification • 位於訊息列,訊息會長註於狀態 列,點擊後可啟動Activity。一般 Services會透過此通知用戶有事件 發生需返回Activity處理 Status Bar Notification 268 為你把關每一道 學習品質
  • 45. Android通知元件-Dialog元件 • Dialog是一切對話框基本類別,並非繼承於View類別. • Dialog也具有生命週期,其生命週期由Activity來誰護。 • 開發者可主動呼叫的函式 Activity • showDialog(int id) showDialog(int id) • dismissDialog(int id) Andr oid onCreateDialog(int id) 框架 onPreparDialog(int id, Dialog dialog) • 框架控制Dialog生命週期函式 • onCreateDialog(int id) • onPrepareDialog(int id, Dialog dialog) 269 為你把關每一道 學習品質
  • 46. Android通知元件-Dialog元件 • Dialog於Activity中的建立流程 • Step1: 呼叫Activity的showDialog(id) Button1.setOnClickListener(new OnClickListener(){ public void on click(View v){ showDialog(DIALOG1); } } ); • Step2: 覆寫(override)onCreateDialog(int id)函式 Protected Dialog onCreateDialog(int id){ switch(id){ Case DIALOG1: return buildDialog1(this); } return null; } 270 為你把關每一道 學習品質
  • 47. Android通知元件-Dialog元件 • Step3:建立需要的Dialog類別,將其返return回 Android框架 Private Dialog buildDialog1(Context context){ AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setIcon(R.drawable.alert_dialog_icon); builder.setTitle(R.string.alert_dialog_two_buttons_title); builder.setPositiveButton(R.string.alert_dialog_ok,new DialogInterface.OnClickListener(){ public void onClick(DialogInterface dialog, int whichButton){ setTitle(“確認鈕”); } }); return builder.create(); } • Step4:覆寫onPrepareDialog(int id, Dialog dialog) protected void onPrepareDialog (int id, Dialog dialog, Bundle args){ return dialog; } 271 為你把關每一道 學習品質
  • 48. Android通知元件-Dialog元件 • AlertDialog • AlertDialog是Dialog的子類別,為最常使用的對話框 • 一個AlertDialog可以有二個至三個按鈕 • 不能直接以建構函式來產生AlertDialog物件,必須透過 AlertDialog.Builder來建構。 private Dialog buildDialog2(Context context) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setIcon(R.drawable.alert_dialog_icon); builder.setTitle(R.string.alert_dialog_two_buttons_msg); builder.setMessage(R.string.alert_dialog_two_buttons2_msg); builder.setPositiveButton(R.string.alert_dialog_ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { setTitle("點選了對話框上的確定按鈕"); }}); builder.setNeutralButton(略.同上); builder.setNegativeButton(略,同上; return builder.create(); } 272 為你把關每一道 學習品質
  • 49. Android通知元件-Dialog元件 • 具有View元件的對話框 private Dialog buildDialog3(Context context) { LayoutInflater inflater = LayoutInflater.from(this); final View textEntryView = inflater.inflate( R.layout.alert_dialog_text_entry, null); 略 AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setView(textEntryView); builder.setPositiveButton(R.string.alert_dialog_ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { setTitle("點選了對話框上的確定按鈕:" + ((TextView) textEntryView.findViewById(R.id.username_edit)).getText()); }}); builder.setNegativeButton(略…….); return builder.create(); } 為你把關每一道 學習品質 273
  • 50. Android通知元件-Dialog元件 • 進度對話框 private Dialog buildDialog4(Context context) { ProgressDialog dialog = new ProgressDialog(context); dialog.setTitle("正在下載歌曲"); dialog.setMessage("請稍候……-"); return dialog; } 為你把關每一道 學習品質 274
  • 51. 範例練習 範例專案名: ex06_02_Dialog 練習目標:  學習操作Android各種不同的Dialog對話視窗  學習如何將Dialog改成可以自定Layout元件 的對訊窗 程式撰寫  覆寫onCreateDialog函式,負責管理Activity 中呼叫的Dialog.  透過AlertDialog.Builder建立Dialog物件 操作練習  透過模擬器操作。 為你把關每一道 學習品質 275
  • 52. Android通知元件-Notification • Notification通知元件 • 不會打斷目前使用者的操作,訊息會長註於訊 息列中,待用戶有空時在進行處理,並可直接 啟動對應的Activity. • Notification可加入振動或聲音通知,以加強引 起用戶的注意。 為你把關每一道 學習品質 276
  • 53. Android通知元件-Notification • 如何撰寫Notification事件 • Step1:取得NotificationManager管理元件 mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); • Step2:建構Notification物件 • 第一個參數:要顯示的圖片ID • 第二個參數:要顯示的文字 • 第三個參數:顯示的時間,System.currentTimeMillis()代表立 即顯示 Notification notification = new Notification(drawable, tickerText,System.currentTimeMillis()); 為你把關每一道 學習品質 277
  • 54. Android通知元件-Notification • Step3:決定Notification如何呈現與處理事件 PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, ActivityMain.class), 0); • Context:作用於那一個Activity的Context • requestCode:目前無使用到 • Intent:要被啟動的Activity Intent • Flags: 細部的Intent操作控制,如 FLAG_CANCEL_CURRENT notification.setLatestEventInfo(this, title, content, contentIntent); • Step4:設定Notification預設的表現形式 • Notification.DEFAULT_VIBRATE 振動 • Notification.DEFAULT_SOUND 聲音 • Notification.DEFAULT_ALL 聲音+振動 • 需加入權限才能使用振動功能:Android.permission.VIBRATE notification.defaults = Notification.DEFAULT_ALL; mNotificationManager.notify(NOTIFICATIONS_ID, notification); 為你把關每一道 學習品質 278
  • 55. Android通知元件-Notification • Notification通知更新 • 透過notify()函式來更新通知,可以避免一直不斷產生新的 Notify訊息通知而導致塞滿了用戶的通知視窗 mNotificationManager.notify(NOTIFICATIONS_ID, notification); • 加入自定音效 • 系統預設音效 • notification.defaults |= Notification.DEFAULT_SOUND; • 讀取SD卡的mp3 • notification.sound =Uri.parse("file:///sdcard/notification/test.mp3"); • 從MediaStore的ContentProvider取得 • notification.sound = Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6"); 為你把關每一道 學習品質 279
  • 56. Android通知元件-Notification • Notification相關FLAG設定 • FLAG_AUTO_CANCEL: • 用戶點了該通知後,系統便會自動清除該訊息 • FLAG_INSISTENT: • 重複發出響聲,直到使用者點選該訊息 • FLAG_ONGOING_EVENT: • 將該訊息放置放”進行中”群組,一般用來代表背景 Service還有在運行中。 • FLAG_NO_CLEAR: • 使用者就算點選了清除訊息,系統也不會把該訊息清 除,必須待應用程式自己發出清除的指令。 為你把關每一道 學習品質 280
  • 57. Android通知元件-Notification • 自定Notification顯示UI元件 • Step1: 利用RemoveView定義元件內容 RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.custom_notification_layout); contentView.setImageViewResource(R.id.imageIcon, R.drawable.notification_image); contentView.setTextViewText(R.id.textView, "Hello Notify"); notification.contentView = contentView; 為你把關每一道 學習品質 281
  • 58. Android通知元件-Notification • Step2: 發出通知訊息 • 使用contentIntent設置pendingIntent元件 Intent notificationIntent = new Intent(this, MyClass.class); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); notification.contentIntent = contentIntent; mNotificationManager.notify(0, notification); 為你把關每一道 學習品質 282
  • 59. Android通知元件-Notification • Notification相關FLAG設定 • FLAG_AUTO_CANCEL: • 用戶點了該通知後,系統便會自動清除該訊息 • FLAG_INSISTENT: • 重複發出響聲,直到使用者點選該訊息 • FLAG_ONGOING_EVENT: • 將該訊息放置放”進行中”群組,一般用來代表背景 Service還有在運行中。 • FLAG_NO_CLEAR: • 使用者就算點選了清除訊息,系統也不會把該訊息清 除,必須待應用程式自己發出清除的指令。 為你把關每一道 學習品質 283
  • 60. Android通知元件-Tost通知元件 • Tost通知元件 • 為一個短暫提示元件,Toast會直接顯示於螢 幕下方. • Tost內容可以直接為描述一串文字,也可以帶 入View元件。 • Toast的顯示時間長度分為長與短兩種 • Toast.LENGTH_LONG • Toast.LENGTH_SHORT 為你把關每一道 學習品質 284
  • 61. Android通知元件-Tost通知元件 • 如何撰寫Tost通知 • Step1:實體化Toast物件 Toast toast = new Toast(this); • Step2:設定Toast內容 • setText(CharSequence s) • setView(View view) LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); View view = vi.inflate(R.layout.toast,null); TextView tv = (TextView) view.findViewById(R.id.content); tv.setText("加入艾鍗,迅速提昇你的開發能力"); toast.setView(view); • Step3:設定顯示時間 toast.setDuration(Toast.LENGTH_SHORT); toast.show(); 為你把關每一道 學習品質 285
  • 62. 範例練習 範例專案名: ex06_03_Toast_and_Notification 練習目標:  學習如何建立Notification與Toast通知事件 程式撰寫  透過getSystemService(NOTIFICATION_SERVICE)取得 NotificationManager物件  建立PendingIntent物件,供用戶執選通知後返回Activity  透過notification.defaults決定通知時是否要加振動與音效  建立Toast物件,並傳送一簡單字串於畫面上 操作練習  透過模擬器練習,練習時可注意畫面的最上頂狀態列 收到Notification時的程現與執行後的處理方式 為你把關每一道 學習品質 286
  • 63. Android Widget開發 Widget程式開發  開發上的限制  Widget組成方式  如何設置組態設定Activity Remove View的互動方式 287
  • 64. Android Widget程式開發 • APP Widget為Android 1.5之後所提 供的功能。提供於Android桌面程式 (Home Screen)上安置各式各樣的 常註程式,例如小時鐘、Google Search... • 常註程式新增方式 • 在主畫面上按下觸控面版約2秒, 即會彈出Add to Home Screen 選單,選擇Widget後即會顯現 目前系統所安裝的各式Widget 為你把關每一道 學習品質 288
  • 65. Android Widget程式開發-使用限制 • Android Widget可以使用的功能 • 可加載於主畫面(Home Screen) • 同一個常駐程式可以多次啟動 • 常註程式啟動時不會採用全畫面(Full Screen) • Android Widget中不能使用的功能 • Event的呼叫。 • 有限的Layout使用,有限的GUI元件使用。 • 可使用的Layout類別: • Frame Layout • Linear Layout • Relative Layout • 可使用的GUI元件 • AnalogClock ImageButton • Button ProgressBar • Chronometer TextView 為你把關每一道 學習品質 289
  • 66. Android Widget程式開發-使用限制 • Android系統對Widget程式的處理方式會有所限制, Widget可以處理的方式選擇 處理方式 說明 指定執行間隔時間 於widget的資訊檔中設置定期執行的時間週期 指定執行時間 於Widget的資訊檔裡設定執行的時間 按下按鈕後才執行 常GUI介面被用戶按下時才執行 • Widget由於長駐於主畫面,且會不定時在背景運作, 因此設計時要特別注意評估電池與處理器的消耗狀況。 • Widget與Activity還有Services一般,皆有其獨自的生 命週期 為你把關每一道 學習品質 290
  • 67. Android Widget程式開發-生命週期 • Widget生命週期 開始 onDelete() onEnabled() onDisabled() onUpdate() App Widget 執行中 關閉 為你把關每一道 學習品質 291
  • 68. Android Widget程式開發-組成結構 • Android Widget應用程式組成結構 BroadcastReceiver AppWidgetManaget AppWidgetProvider 實作生命週期函式 廣播呼叫 onEnable,onUpdate, APPWIDGET_UPDATE onUpdate,onDelete d, myAppWidgetProvider onDisabled Android應用程式設定檔 Metadata設定 Widget資訊設定檔 Layout畫面布局檔 AndroidManifest.xml Name:名稱需為 Appwidget_info.xml Layout_sample.xml android.appwidget. 建立BroadcastReceiver provider 定義Layout布局 有限的layout元件使用 <action>欄位需明確定義為 畫面大小:74倍數-2 android.appwidget.action.APPWIDG 有限的GUI元件使用 Resource:指定 執行時間週期設定 ET_UPDATE information檔的來 源 為你把關每一道 學習品質 292
  • 69. Android Widget資料更新 • AppWidget主要是依建置在Home Launcher APP之上, 因此Widget畫面的更新與Event互動皆必須透過一個 Proxy來代為處理,而此Proxy就是AppWidgetManager 元件。 • 所有待更新的Widget元件,皆必須透過RemoteViews 元件封裝,所有的互動事件則必須透過pending Intent 註冊於RemoteViews中。 Home Launcher • AppWidget元件updateAppWidget函式協助將 RemoteViews更新於Widget元件上。 Widget setTextViewText setImageViewResource AppWidget Manager setOnClickPendingIntent RemoteViews 為你把關每一道 學習品質 293
  • 70. 範例練習 範例專案名: ex06_04_MyWidget 練習目標:  了解如何建置Widget元件  學習如何為Widget加入listener與更新UI 程式撰寫  實作一個Widget 的receiver元件,並實作組態設定 Activity,Widget啟動前會現顯示Activity應用程式。  撰寫Appwidget_info.xml檔,決定Widget顯示方式  撰寫Layout_sample.xml,決定Widget顯示的UI樣式。  撰寫RemoteView更新函式,取得Widget觸發事件, 並依事件狀態更新WidgetUI 操作練習  透過模擬器操作 為你把關每一道 學習品質 294
  • 71. Android Widget程式開發-組態設定Activity • AppWidget組態設定Activity • 當用戶新增一個Widget時,系統可以呼叫一個組態設定 Activity,提供用戶對該Widgegt進行設定,如改變顏色,顯示 大小,執行週期..等等資訊。 • 如何為AppWidget配置組態設定Activity • AndroidManifest.xml中定義Activity,<action>需定義為: ACTION_APPWIDGET_CONFIGURE <activity android:name="myAppWidgetConfigure"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" /> </intent-filter> </activity> • 於appwidget_info.xml中指定要呼叫的Activity <appwidget-provider .... android:configure= " com.example.android.appwidget.myAppwidgetConfigures" /> 為你把關每一道 學習品質 295
  • 72. Android Widget程式開發-組態設定Activity • AppWidget呼叫組態設定Activity時注意事項 • AppWidget呼叫執行Activity後,此Activity必須要返回一個結果, 而此結果必須要包含Widget ID(存在EXTRA_APPWIDGET_ID) • Activity被建立時,AppWidget中的onUpdate方法將不會被呼叫 到,因此Activity完成組態設定後一定要負責更新AppWidget程式 (可以透過請求AppWIdgetManager協助更新) • 組態設定Activity實作方式 • Step1:透過Intent取得AppWidget ID final Bundle extras = getIntent().getExtras(); If(extras != null){ int mAppWidgetId = extras.getInt( AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); } 為你把關每一道 學習品質 296
  • 73. Android Widget程式開發-組態設定Activity • Step2:執行組態設定,等待用戶設定操作 • Step3:設定完成後,更新AppWidget UI畫面 AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(LifeCycleConfigure.this); RemoteViews views = new RemoteViews(getPackageName(), R.layout.life_cycle); appWidgetManager.updateAppWidget(mAppWidgetId, views); • Step4:最後建立一個Intent返回結果,並結束Activity Intent resultValue = new Intent(); resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId); setResult(RESULT_OK, resultValue); finish(); 為你把關每一道 學習品質 297
  • 74. 範例練習 範例專案名: ex06_05_Appwidget 練習目標:  了解桌面Widget應用程式的撰寫方式與生命流程  學習如何為Widget加入組態設定用Activity 程式撰寫  實作一個Widget 的receiver元件,並實作組態設定 Activity,Widget啟動前會現顯示Activity應用程式。  撰寫Appwidget_info.xml檔,決定Widget顯示方式  撰寫Layout_sample.xml,決定Widget顯示的UI樣式。 操作練習  透過模擬器操作 為你把關每一道 學習品質 298
  • 76. Broadcast Receiver與Service元件 BroadCastReceiver元件  廣播的用途與種類  如何發送廣播封包  如何註冊接收廣播封包  廣播封包加入自定權限 Services 元件應用  Local 與 Remote Services  Services生命週期  如何與Services進行溝通  Remote Services設計實作  如何與RemoteServices溝通  Services與Activity通訊架構 設計 300
  • 77. BroadCast Receiver元件 • 廣播接收程式可用來接收其他應用程式所發出的訊息。 • 許多的廣播通知訊息都是來自於Android作業系統 • 電池電量快用盡 • 網路連線變化 • 有來電或簡訊通知 • 應用程式本身也可以發出廣播訊息,可做為與其他應用程 式互動溝通的管道。 • 需注意的是廣播訊息是公開的,任何應用程式都可以 透過註冊BraodCast Receiver來接收到你所廣播的訊 息。 • 一般常用來做為Services應用程式與Activity應用程式溝通 使用。 為你把關每一道 學習品質 301
  • 78. BroadCast Receiver元件 • 如何發送廣播 • 在程式中透過Intent建立好希望被那些action filter所接 收,接著透過sendBroadcast函式發送出去。 public static final String NEW_BROADCAST= " com.ittraining.action.NEW_BROADCAST "; Intent intent = new Intent(NEWO_BROADCAST); intent.putExtra(" data1",someData); intent.putExtra(" data2",someData); sendBroadcast(intent); 為你把關每一道 學習品質 302
  • 79. BroadCast Receiver元件 • 如何接收廣播 • 想接收並且處理廣播的Intent,就必需要註冊一個 BroadcastReciever,並且設定一個Intent Filter以將不需 要監聽的訊息過慮掉,最後在將其註冊到Android框架 中。 • Step1: 繼承BroadcastReceiver類別,並覆寫 onReceive(Context context, Intent intetn)函式 • 需注意onReceive函式內的處理不宜超過5秒,長時間 的處理建議移到Thread中執行。 public class IttrainingAndroidReceiver extends BroadcastReceiver{ @override Public void onReceive(Context context, Intent intent){ //接收後的處理 } } 為你把關每一道 學習品質 303
  • 80. BroadCast Receiver元件 • Step2: 註冊BroadCastReceiver • 透過XML註冊 <receiver android:name= " IttrainingAndroidReceiver " > <intent-filter> <action android:name= " com.ittraining.action.NEW_BROADCAST " /> </intent-filter> </receiver> • 透過程式碼註冊 IntentFilter filter =new IntentFilter(NEW_BROADCAST); IttrainingAndroidReceiver receiver=new IttrainingAndroidReceiver(); registerReceiver(receiver , filter); unregisterReceiver(receiver); • 取消註冊 unregisterReceiver(receiver); 為你把關每一道 學習品質 304
  • 81. 範例練習 範例專案名: ex07_01_Broadcastreceiver 練習目標:  學習如何發送廣播訊息  了解如何接收其它應用程式所發出的廣播訊息 程式撰寫  建立一個Activity應用程式與二個Recever程式  由Activity發送broadcast至Recever程式 操作練習  透過模擬器操作。注意兩個receiver的<intent- filter>action name並不相同,透過Activity可透過 不同的action決定要將訊息broadcast至指定的 receiver. 為你把關每一道 學習品質 305
  • 82. BroadCast Receiver元件-安全性管理 • Android廣播服務安全性漏洞 • 主要利用Intent Filter做為過濾,任何其它應用 程式只要得知廣播的Action Name就可以註冊 取得該廣播的資料。這將存在一個安全性的漏 洞,若你的廣播中所傳遞的是很重要的資料, 這將有可能被其它惡意軟體給監聽取得。 • 增加自訂權限傳送與接收廣播 • 開發者可為自己的APP程式加入自訂權限,任 何的應用程式如果要接收該廣播資料,則必須 宣告取得相關的權限。 為你把關每一道 學習品質 306
  • 83. BroadCast Receiver元件-安全性管理 • 增加權限到AndroidManifest.xml定義描述檔 <permission android:name="com.ittraining.ex07_02.SEND_DATA" android:description="@string/permission_aceess_deta" android:label="@string/permission_aceess" android:protectionLevel="normal" > </permission> • name:權限名稱,請求權限與執行權限時使用,必須為唯 一的值。 • description:提供詳細說明為何需要此權限,與如何使用 • lable:用戶安裝軟體時顯示給使用者看,以提供用戶進行 授權,此字串不應太長。 • protectionLevel:權限等級,normal為最基本等級。 為你把關每一道 學習品質 307
  • 84. BroadCast Receiver元件-安全性管理 • 於AndroidManifest.xml宣告請求使用者授權 <uses-permission android:name="com.ittraining.ex07_02.SEND_DATA"/> • 發送廣播時於sendBroadcast第二個參數帶入權 限名稱 sendBroadcast(intent, "com.ittraining.ex07_02.SEND_DATA“); • 接收端在註冊Receiver元件時,第三個參數需帶 入權限名稱 registerReceiver(receiver,filter, "com.ittraining.ex07_02.SEND_DATA“,null); 為你把關每一道 學習品質 308
  • 85. Services元件 • Services是在背景運作,不直接與使用者互動,因此並無 UI畫面 • Services無法獨立自行運作,而必須透過Activity或其它 Context物件來呼叫啟動 • Context.startService() • Context.binService() • 若Services的onCreate(),onStart()內需執行一些耗時的處 理,請使用Thread處理,以避免造成UI操件lock. • 使用Services的好處,在於Activity結束後其Services元件 依然會在背景做運行,Services有其獨立的生命週期不會 受Activity生命週期影影。 – 播放音樂 – 背景接收網路訊息 為你把關每一道 學習品質 309
  • 86. Services元件 • Android Services的使用方式可區分為二類 • Local Services (操作自己應用程式的Services) • Remote Services (操作其它應用程式的Services) • 與Services溝通方式 • 透過BroadCast傳送Intent至Services • 透過Binder與Services做Local Services連結 • 透過IPC(interprocess communication)與Remote Services做連結 • 透過Contex.getSystemService(String name),函 式可取得Android預設的Services元件. 為你把關每一道 學習品質 310
  • 88. Services元件 • Android系統內提供的一些Services服務 Services代碼 對應Manager 物件 說明 WINDOW_SERVICE WindowManager 管理視窗畫面 LAYOUT_INFLATER_SERVICE LayoutInflater 載入xml檔所定義的View元件 ACTIVITY_SERVICE ActivityManager 管理應用程式的系統狀態 POWER_SERVICE PowerManger 電源管理 ALARM_SERVICE AlarmManager 鬧鐘管理 NOTIFICATION_SERVICE NotificationManager 狀態列訊息通知服務 KEYGUARD_SERVICE KeyguardManager 鍵盤鎖管理 LOCATION_SERVICE LocationManager 位置服務管理,GPS SEARCH_SERVICE SearchManager 搜尋服務管理 VEBRATOR_SERVICE Vebrator 振動服務管理 CONNECTIVITY_SERVICE Connectivity 網路連線服務管理 WIFI_SERVICE WifiManager WIFI連線服務管理 TELEPHONY_SERVICE TeleponyManager 電話服務管理 為你把關每一道 學習品質 312
  • 90. Services元件-生命週期 • Services元件有其獨 立的生命週期 • onCreate() • onStart() • onDestroy() • 啟動Services的方式 不同,對應的生命 週期也不同。 • startServices() • bindServices() 為你把關每一道 學習品質 314
  • 91. Services元件-啟動Services • Step1: 於AndroidManifest.xml中加入Services宣告 <service android:enabled="true" android:name=".TestService" /> • Step2:覆寫Services函式-處理生命週期 public class TestService extends Service { @Override public void onCreate() { Log.e(TAG, "============> TestService.onCreate"); } @Override public void onStart(Intent intent, int startId) { Log.e(TAG, "============> TestService.onStart"); } @Override public void onDestroy() { Log.e(TAG, "============> TestService.onDestroy"); } } 為你把關每一道 學習品質 315
  • 92. Services元件-啟動Services • Step3:覆寫Services函式-提供Bind接口 @Override public IBinder onBind(Intent i) { return new LocalBinder();; } public class LocalBinder extends Binder { TestService getService() { return TestService.this; } } @Override public boolean onUnbind(Intent i) { Log.e(TAG, "============> TestService.onUnbind"); Return true; } @Override public void onRebind(Intent i) { Log.e(TAG, "============> TestService.onRebind"); } 為你把關每一道 學習品質 316
  • 93. Services元件-啟動Service • Step4:透過Activity啟動Service-使用startService() private void startService() { Intent i = new Intent(this, TestService.class); this.startService(i); } private void stopService() { Intent i = new Intent(this, TestService.class); this.stopService(i); } • Step4:透過Activity啟動Services-使用bindService() private void bindService() { Intent it = new Intent(this, TestService.class); bindService(it , _connection, Context.BIND_AUTO_CREATE); _isBound = true; } private void unbindService() { if (_isBound) { unbindService(_connection); _isBound = false; } 為你把關每一道}學習品質 317
  • 94. Services元件-啟動Service • Step6:SerrviceConnection元件建立-透過bindService() private ServiceConnection _connection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service){ _boundService = ((TestService.LocalBinder)service).getService(); Toast.makeText(TestServiceHolder.this, "Service connected:", Toast.LENGTH_SHORT).show(); } public void onServiceDisconnected(ComponentName className) { _boundService = null; Toast.makeText(TestServiceHolder.this, "Service connected", Toast.LENGTH_SHORT).show(); } }; 為你把關每一道 學習品質 318
  • 95. BroadcastReceiver與Services綜合演練 • 結合Services服與程式與BroadcastReceiver,實作 一鬧鐘計時器。 提供UI畫面讓User設定鬧鐘時 Services在背景進行時間排程倒 間設定完成後會通知背景 數,當時間到時透過broadcast訊 Services進行倒數計時,並註冊 息,傳送回主程式,並播放一段鬧鐘 一個BroadcastReceiver類別 音效與Toast訊息 KitchenTimer.java KitchenTimerService.java KitchenTimer Schedule(long delay) KitchenTimerSdervice.shecule(alarmtimer) Timer.shedule(timerTask,delay) KitchenTimer TimerTask() KitchenTimerReceiver-receiver sendBroadcast(new Intent(ACTION)) 為你把關每一道 學習品質 319
  • 96. BroadcastReceiver與Services綜合演練 • Step1:建立Services宣告 <service android:enabled="true" android:name=".KitchenTimerService" /> • Step2:主程式onCreate() //啓動服務程式KitchenTimerService Intent intent = new Intent(this, KitchenTimerService.class); startService(intent); //註冊廣播接收receiver IntentFilter filter = new IntentFilter(KitchenTimerService.ACTION); registerReceiver(receiver, filter); //(Bind)服務程式KitchenTimerService bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); 為你把關每一道 學習品質 320
  • 97. BroadcastReceiver與Services綜合演練 • Step3:主程式onDestroy() //Activity結束時,要將Service相關資源一並結束 @Override public void onDestroy() { super.onDestroy(); unbindService(serviceConnection); //Unbind service unregisterReceiver(receiver); //Unregister Receiver kitchenTimerService.stopSelf(); //Stop Service } • Step4:定義接收廣播類別KitchTimerReceiver private class KitchenTimerReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { Toast toast = Toast.makeText(getApplicationContext(), "Time over!", Toast.LENGTH_LONG); toast.show(); MediaPlayer mp = MediaPlayer.create(KitchenTimer.this, R.raw.alarm); try { mp.start(); } catch (Exception e) { } kitchenTimerService.schedule(alarmtimer); } 為你把關每一道 學習品質 } 321
  • 98. BroadcastReceiver與Services綜合演練 • Step5:定義與Service bind的ServiceConnection private ServiceConnection serviceConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { kitchenTimerService = ((KitchenTimerService.KitchenTimerBinder)service).getService(); } public void onServiceDisconnected(ComponentName className) { kitchenTimerService = null; } }; 為你把關每一道 學習品質 322
  • 99. BroadcastReceiver與Services綜合演練 • Step6:建立Services類:KitchenTimerService public void onCreate() { super.onCreate(); Toast toast = Toast.makeText(getApplicationContext(), "onCreate()", Toast.LENGTH_SHORT); toast.show(); } public void onStart(Intent intent, int startId) { super.onStart(intent, startId); Toast toast = Toast.makeText(getApplicationContext(), "onStart()", Toast.LENGTH_SHORT); toast.show(); } public void onDestroy() { super.onDestroy(); Toast toast = Toast.makeText(getApplicationContext(), "onDestroy()", Toast.LENGTH_SHORT); toast.show(); if (timer != null) { timer.cancel(); timer = null; } } 為你把關每一道 學習品質 323
  • 100. BroadcastReceiver與Services綜合演練 • Step7:覆寫Services Bind相關函式 @Override public IBinder onBind(Intent intent) { Toast toast = Toast.makeText(getApplicationContext(), "onBind()", Toast.LENGTH_SHORT); toast.show(); return new KitchenTimerBinder(); } @Override public void onRebind(Intent intent) { Toast toast = Toast.makeText(getApplicationContext(), "onRebind()", Toast.LENGTH_SHORT); toast.show(); } @Override public boolean onUnbind(Intent intent) { Toast toast = Toast.makeText(getApplicationContext(), "onUnbind()", Toast.LENGTH_SHORT); toast.show(); return true; //當再度自Client接口時,呼叫 onRebind的場合會回覆 true } 為你把關每一道 學習品質 324
  • 101. BroadcastReceiver與Services綜合演練 • Step8:Service發送廣播訊息至主程式 public void schedule(long delay) { if (timer != null) { timer.cancel(); } timer = new Timer(); TimerTask timerTask = new TimerTask() { public void run() { //送出信息給廣播接收程式 sendBroadcast(new Intent(ACTION)); } }; //設定Alarm time,且Time out時會執行timerTask送出信息 timer.schedule(timerTask, delay); } 為你把關每一道 學習品質 325
  • 102. 範例練習 範例專案名: ex07_02_Kitchentimer 練習目標:  學習如何結合BroadCastReceiver與Services的應用 程式撰寫  實作一個Activity並內置一個Receiver類別,當用設定 好時間後將啟動一個Services在背景做倒數計時的動 作。  實作一個Services應用程式,由Activity所呼叫建立, 當指定的計時工作結束後將透過broadcast方式通知 Activity的receiver類別。 操作練習  透過模擬器操作,倒數計時的單位為分鐘。時間到後 會發出聲響,並顯示一段Toast字串於畫面上。 為你把關每一道 學習品質 326
  • 103. Remote Services應用 • 要將Services元件跑在獨立的Processe中可透過在 AndroidMainfest.xml中,宣告services元件加上 android:process=":remote" <service android:name=".services.TrackerServices" android:process=":remote"> • Services中設置Messenger可以提供與遠端Services元件進 行雙向溝通。 private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { /*接收來自client傳來的訊息*/ } } private Messenger mMessenger = new Messenger(mHandler); @Override public IBinder onBind(Intent intent) { return mMessenger.getBinder(); } 為你把關每一道 學習品質 327
  • 104. Remote Services應用 • Client端在利用Bind與遠端Services連接,並取得 Messenger元件。 private Messenger remoteMessenger; private ServiceConnection connection = new ServiceConnection() { public void onServiceConnected(ComponentName name, IBinder service) { remoteMessenger = new Messenger(service); } public void onServiceDisconnected(ComponentName name) { remoteMessenger = null; } }; • 傳送訊息至Remote Services Private Message localMessenger; private void sendMessage() { Message message = Message.obtain(null, 0); message.replyTo = localMessenger; try { rMessenger.send(message); } catch (RemoteException e) { e.printStackTrace(); } } 為你把關每一道 學習品質 328
  • 105. 範例練習 範例專案名: ex07_03_RemoteService 練習目標:  了解RemoteServices與Local Services的差別  學習如何使用Messenger進行IPC跨Process通訊 程式撰寫  撰寫一個Services元件,並將process tag設為:remote  設置Messenger 物件做為IPC通訊管道。  撰寫Activity 元件,利用Bind 與remote services 通 訊。 操作練習  透過模擬 為你把關每一道 學習品質 329
  • 106. IntentService應用 • Android預設所有的四大元件都是運行在主執行緒中,包含 Service也是運行在主執行緒中,因此若在Service執行耗時 的工作則將會導致UI lock。避免UI Lock的方式為將Service 設置為remote,或是透過IntentService。 • IntentService 為一次性使用的Service元件,並且會自動運 行在子執行緒中,使用者可以免除複雜的Message、Loop 與Handler設計,透過Intentservice可以快速的處理一次性 耗時的工作。 • 將工作放置於IntentService的優勢 • 比較不容易被系統Kill • 工作於子執行緒中,不會導致UI Thread Lock • 非常容易使用,使用完即自動回收,不佔用記憶體。 為你把關每一道 學習品質 330
  • 107. 範例練習 範例專案名: ex07_04_IntentService 練習目標:  了解Intent Service、Thread與Service的差別  學習如何利用Intent Service 在背景處理耗時的工作 程式撰寫  繼承IntentService類別,並實作onHandleIntent函式  將耗時的工作寫在onHandleIntent函式中。  撰寫Activity頁面,利用startService函式呼叫 IntentService工作。 操作練習  透過模擬 為你把關每一道 學習品質 331
  • 109. SQLite DataBase開發技巧 SQLite Database存取技巧  SQLite語言定義與建置工具  SQLiteOpenHelp類別實作  資料庫的基本IO操作方式  設計DataBase Adapter架構 333
  • 110. SQLite DataBase • SQLite是Android內建的一個輕量化的嵌入式資料庫,可使 用SQL語法進行控制存取。 • SQLite的優點 • 免費,無需授權 • 輕量,約150KB左右,很適在嵌入式手機領域使用 • 無需設定、安裝與管理,沒有伺服器,不需組態檔,無 需資料庫管理員 • SQLite只是一個檔案,可以很方便的移動或複製到另一 系統,也能運作的很良好。 • Android將SQLite檔案存放於下列路徑中 • /data/data/packagename/databases • 可以使用adb或File Explorer來觀移存取資料庫檔案 為你把關每一道 學習品質 334
  • 111. SQLite DataBase • SQL入門 • SQL描述語法主要包含三種類型 • DLL(資料定義語言) • 修改 • 查尋 • DLL資料定義語言: • 資料庫的組成由多個資料表(table)多個資料列(Row) 若干資料欄(column)所組成。 • 每個資料欄具有欄位名稱與資料類形(文字,數字…) Create table mytalbe( _id integer primary key autoincrement, Name text, Phone text) • 第一個欄位指定為主鍵(PRIMARY KEY) 為你把關每一道 學習品質 335
  • 112. SQLite DataBase • 安裝Questoid SQLite Browser Eclipse Plugin,協助以圖形化方式觀看 Android內的SQLite資料表 • http://www.questoid.net/Tools/QuestoidSQLiteBrowser.aspx • 將com.questoid.sqlitebrowser_1.1.0.jar Copy至Eclipse的plugins目 錄中,並重新啟動Eclipse. • 切換至DDMS視圖,利用File Explorer工具找到要查看的SQLite data base檔案. • SQL語法指令查尋與學習資源 • http://www.1keydata.com/tw/sql/sqlhaving.html 為你把關每一道 學習品質 336
  • 113. SQLite DataBase-SQLiteOpenHelper • Android應用程式中提供了SQLiteOpenHelper類別來協助操 作SQLite資料庫並,提供產生與管理資料庫的版本 • SQLiteOpenHelper為一抽像類別,需繼承並實作三個函式 • onCreate(SQLiteDatabase db) • 資料庫第一次產生時呼叫。 • onUpdate(SQLiteDatabase db,int oldVersion,int newVersion) • 當資料庫需要升級時,由系統主動呼叫。一般用來刪除舊資料 表,並建立新的資料表 • onOpen(SQLiteDatabase db) • 當資料庫被開啟時的Callback函式,由系統呼叫,一般不會使用到。 為你把關每一道 學習品質 337
  • 114. SQLite DataBase-SQLiteOpenHelper • 如何建立SQLiteOpenHelper類別 private static final String DATABASE_NAME = "dbForTest.db"; private static final int DATABASE_VERSION = 1; private static final String TABLE_NAME = "diary"; private static final String TITLE = "title"; private static final String BODY = "body"; private static class DatabaseHelper extends SQLiteOpenHelper { DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { String sql = "CREATE TABLE " + TABLE_NAME + " (" + TITLE + " text not null, " + BODY + " text not null " + ");"; db.execSQL(sql); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } } 為你把關每一道 學習品質 338
  • 115. SQLite DataBase-SQLiteOpenHelper • 取得透過SQLiteOpenHelper取得SQLiteDatabase類別 Public Methods synchronized SQLiteDatabase getReadableDatabase()Create and/or open a database. synchronized SQLiteDatabase getWritableDatabase()Create and/or open a database that will be used for reading and writing. • 利用SQLiteDatabase提供的函式可以存取操作資料庫 • public Cursor rawQuery (String sql, String[] selectionArgs) • 最低階的操作函式,可以直接接受標準SQL語法 • 為方便不熟SQL語法的開發者,另外有提供一系列的API函式,系統 會將API指令自動轉換成標準的SQL語法呼叫資料庫。 • pubilc delete(….) • pubilc insert(….) • pubilc update(….) • public Cursor query (….) 為你把關每一道 學習品質 339
  • 116. SQLite DataBase-資料庫操作 • 如何插入資料庫記錄 private void insertItem() { SQLiteDatabase db = mOpenHelper.getWritableDatabase(); String sql1 = "insert into " + TABLE_NAME + " (" + TITLE + ", " + BODY + ") values('haiyang', 'android的發展真是迅速');"; String sql2 = "insert into " + TABLE_NAME + " (" + TITLE + ", " + BODY + ") values('icesky', 'android的發展真是迅速');"; try { db.execSQL(sql1); db.execSQL(sql2); setTitle("插入兩條數據成功"); } catch (SQLException e) { setTitle("插入兩條數據失敗"); } } 為你把關每一道 學習品質 340
  • 117. SQLite DataBase-資料庫操作 • 如何刪除資料記錄 private void deleteItem() { try { SQLiteDatabase db = mOpenHelper.getWritableDatabase(); db.delete(TABLE_NAME, " title = 'haiyang'", null); setTitle("刪除title為haiyang的一條記錄"); } catch (SQLException e) { } } • 查尋資料 private void showItems() { SQLiteDatabase db = mOpenHelper.getReadableDatabase(); String col[] = { TITLE, BODY }; Cursor cur = db.query(TABLE_NAME, col, null, null, null, null, null); Integer num = cur.getCount(); setTitle(Integer.toString(num) + " 條記錄"); } 為你把關每一道 學習品質 341
  • 118. SQLite DataBase-資料庫操作 • 刪除整個Table private void dropTable() { SQLiteDatabase db = mOpenHelper.getWritableDatabase(); String sql = "drop table " + TABLE_NAME; try { db.execSQL(sql); setTitle("數據表成功刪除︰" + sql); } catch (SQLException e) { setTitle("數據表刪除錯誤"); } } • 建立新的Table private void CreateTable() { SQLiteDatabase db = mOpenHelper.getWritableDatabase(); String sql = "CREATE TABLE " + TABLE_NAME + " (" + TITLE + " text not null, " + BODY + " text not null " + ");"; try { db.execSQL("DROP TABLE IF EXISTS diary"); db.execSQL(sql); setTitle("數據表成功重建"); } catch (SQLException e) { setTitle("數據表重建錯誤"); } 為你把關每一道 學習品質 } 342
  • 119. 範例練習 範例專案名: ex08_01_Sqlite 練習目標:  學習如何建立與使用SQLite資料庫 程式撰寫  撰寫DataBaseHelper 繼承SQLiteOpenHelper  透過DataBaseHelper取得SQLiteDatabase物件,並實作新 增、刪除、查尋、建立資料表等函式 操作練習  透過模擬器操作,可以藉由DDMS的檔案瀏覽器 將SQLite資料庫檔滙出,或滙入現有的SQLite資 料庫至手機上。 為你把關每一道 學習品質 343
  • 120. SQLite DataBase-Query函式 • SQLiteDatabase的query方法 • Cursor query (boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) • distinct : 是否希望每一row都是唯一的 • table:要查尋的資料表(Table) • columns:回傳資料包含的訊息列。不在清單中的其它列將不會取得。 • selection:相當於SQL中的where,如想傳回所有資料請用null • selectionArgs:如select中有使用到[?]變數,此字串將用來取代[?] • groupBy:查尋得到的資料是否要分群組 • having:相當於SQL中的having • orderBy:是否需要排序,若設定為null代表不排序 • limit:限制查尋回的資料組數上限 為你把關每一道 學習品質 344
  • 121. SQLite DataBase-Cursor介面 • android.database.Cursor介面 • 由query方法查尋到資料後,將會回傳Cursor物件。 • 透過Cursor可以將資料庫查出來的資料進行讀寫操作。 • Cursor可以連結CursorAdapter並覆寫其bindView()和newView()兩 抽像方法來達到更豐富的顯示方式 Activity SQLiteOpenHelper Cursor Query結果 SQLiteDatabase 為你把關每一道 學習品質 345
  • 122. SQLite DataBase-Cursor介面 • Cursor常用的函式 函式 說明 movetoPosition(int pos) 移動Cursor到指定位置 Move(int offset) 向前或向後位移:正數向前,負責向後 moveToFirst() 移動Cursor到最前或最後位置 moveToLast() moveToNext() 將Cursor向前或向後移動一格 moveToLast() isBeforeFirst() 判斷Cursor是否指向第一個數據之前,或最 isAfterLast() 後一個數據之後 isFirst() 判斷Cursor是否指向第一行或最後一行 isLast() getColumnCount() 取得行(列)數目 getCount() getColumnIndexOrThrow(String 根據列的名稱取得索引值(以0開始) columnName) getBlob(int index) 依據資料型別取回Cursor目前所指的資料。 getInt(int index) getLong(int index) getShort(int index) getFloat(int index) 為你把關每一道 學習品質 getString(int index) 346
  • 123. SQLite DataBase-Cursor介面 • Cursor與CursorAdapter連接 • public SimpleCursorAdapter (Context contex, int layout, Cursor c, String[]from, int[] to) • context:作用於那個Context物件上 • layout:顯示介面layout樣版,需包含to所指定的View id • c: cursor資料來源 • from:需要從cursor取出的列名稱索引值 • to:layout中需要作用對應於from值的View元件id s = (Spinner)findViewById(R.id.spinner); display = (TextView)findViewById(R.id.display); SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_spinner_item,c,new String[] { MyHelper.COUNTRY}, new int[] {android.R.id.text1}); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_it em); s.setAdapter(adapter); 為你把關每一道 學習品質 347
  • 124. SQLite DataBase-日記簿運作流程 ActivityDiaryEdit DiaryDbAdapter onCreate () onClick() deleteDiary() createDiary() getAllNotes() EditText EditText Button getDiary() updateDiary() ActivityMain extends ListActivity onMenuItemSelected() onCreateOptionsMenu() DatabaseHelper createDiary() onListItemClick() onCreate () SimpleCursorAdapter NAME:database TABLE: diary Query結 Cursor 果 為你把關每一道 學習品質 348
  • 125. 範例練習 範例專案名: ex08_02_Sqldiary 練習目標:  學習如何利用SQLite開發一個簡單的日記本  學習SimpleCursorAdapter的使用 程式撰寫  實作一個ListActivity,並將SQLite讀取得到的資料透 過SimpleCursorAdapter顯示於ListActivity上.  實作一個DiaryDbAdapter,協助處理與SQLite資料庫 存取有關的所有操作  設計一個日記輸入與編輯的UI頁面 操作練習  透過模擬器進行操作。 為你把關每一道 學習品質 349
  • 126. DataBaseAdapter架構實作 • 設計DataBaseAdapter可提供Activity頁面一個統 一且一致的存取資料庫的介面,並且將SQL語法 隱藏在Adapter內,對外只提供高階的存取介面。 SqlObject SqlObject DataBaseAdapter SqlObject IOInterface Activity SQLite DataBaseOpenHelp 為你把關每一道 學習品質 350
  • 127. DataBaseAdapter架構實作 • 資料庫表單常數定義介面 • DataBaseColumnDefine public interface DataBaseColumnDefine { /* 表單名稱 */ public static final String USERPROFILE_TABLE_NAME = "UserProfileDB"; /* 欄位名稱 */ public static final String USERPROFILE_KEY_ID = "_id"; /*SQL指令*/ public static final String SQL_CREATE="CREATE TABLE "; public static final String SQL_DATA_AUTO=" integer primary key autoincrement"; public static final String SQL_DATA_NUMERIC=" NUMERIC"; public static final String SQL_DATA_TEXT=" TEXT"; /*建立table的sql語法*/ public static final String CREATE_USERPROFILE_TABLE = SQL_CREATE + USERPROFILE_TABLE_NAME+ " (" + USERPROFILE_KEY_ID + SQL_DATA_AUTO+");"; /*Query回來資料的欄位範圍*/ public static String[] userProfileDataSet = { USERPROFILE_KEY_ID,}; } 為你把關每一道 學習品質 351
  • 128. DataBaseAdapter架構實作 • SqlObject抽像介面設計 • 抽像的功能 /** * 取得privateKey值 */ abstract int getPrivateKey(); /** * 設定privateKey值 */ abstract void setPrivateKey(int privateKey); /** * 從資料庫中讀入資料 * @param cursor */ abstract void readProfile(Cursor cursor); /** * 將資料轉換成ContentValues以供資料庫做後操作 */ abstract ContentValues getContentValues(); 為你把關每一道 學習品質 352
  • 129. DataBaseAdapter架構實作 • SqlObject抽像介面 • 產生SqlObject的建構工廠 /** * 依需求取得不同型態的SQL Object * @param type * @return */ public static SqlObject createUserDataObject(SqlType type){ switch(type){ } return null; } 為你把關每一道 學習品質 353
  • 130. DataBaseAdapter架構實作 • DataBaseAdapter實作方式 • 使用Singleton架構 private SQLiteDatabase sqlDataBase; private static DataBaseAdapter dbAdapter; private DataBaseAdapter(Context context){ DataBaseHelp dataBaseHelp= new DataBaseHelp(context); try { dataBaseHelp.createDataBase(); } catch (IOException e) { e.printStackTrace(); } sqlDataBase=dataBaseHelp.getWritableDatabase(); } public synchronized static DataBaseInterface getInstence(Context context){ if(dbAdapter==null) dbAdapter=new DataBaseAdapter(context.getApplicationContext()); return dbAdapter; } 為你把關每一道 學習品質 354
  • 131. DataBaseAdapter架構實作 • 透過DataBaseOpenHelp讀寫資料庫(SqlObject) • 新增 mDb.insert(USERPROFILE_TABLE_NAME, null, initialValues); • 刪除 mDb.delete(USERPROFILE_TABLE_NAME, USERPROFILE_KEY_ID + "=" + sqlObject.getPrivateKey(), null); • 修改 mDb.update(USERPROFILE_TABLE_NAME, initialValues, USERPROFILE_KEY_ID + "=" + sqlObject.getPrivateKey(0, null) > 0; • 查尋 Cursor mCursor=mDb.query(USERPROFILE_TABLE_NAME, userProfileDataSet, null, null, null, null,null); 為你把關每一道 學習品質 355
  • 132. DataBaseAdapter架構實作 • 上層Activity使用DataBaseAdapter方式 • 取得DataBaseAdapter物件實體 DataBaseAdapter dbAdapter=DataBaseAdapter.getInstence(this); • 讀取資料 ArrayList<UserProfile>allUser= (ArrayList<UserProfile>) dbAdapter.getAllUser(null); ArrayList<UserProfile>allUser=dbAdapter.getAllUser(allUser); //參照更新 • 新建資料 profile.setPhotoType(1); profile.setUserCompony("test"); profile.setUserName("Jarey"); profile.setUserPhone("09xxx"); long privateKey=dbAdapter.addUserProfile(profile); 為你把關每一道 學習品質 356
  • 133. 範例練習 範例專案名: ex08_03_SqlTemplet 練習目標:  學習如何設計DataBase Adapter  透過DataBase Adapter層將應用層與資料存取層分 程式撰寫  設計一簡單的資料庫表單,並實作DataBase Adapter 元件。  Activity層透過DataBase Adapter對資料庫進行資料存 取。  實作一個BaseAdapter元件,將從DataBaseAdapter 讀出的資料透過BaseAdapter顯示於ListView上。 操作練習  透過模擬器進行操作。 為你把關每一道 學習品質 357
  • 134. 第10節: Content Provider元件 Android Thread程式設計
  • 135. Content Provider元件 ContentProvider元件設計  ContentProvider應用時機  與系統ContentProvider連接  自建ContentProvider 359
  • 136. Content Provider元件 • ContentProvider作用 • Android程式中所有的資料(包含檔案,資料庫)全都是Private的,不同 的應用程式之間不能直接存取 • ContentProvider提供解決不同應用程式之間交換資料的需求 • ContentProvider提供一組標準介面 • query(Uri uri,String[] projection,String selection,String[] selectionArgs,String sortOrder) • 透過Uri進行查尋,結果將透過傳回的Cursor物件進行存取. • insert(Uri url,ContentValues values) • 將一組資料插入到Uri指定的位置 • update(Uri url,ContentValues values,String where,String[] selectionArgs) • 更新Uri指定位置的資料 • delete(Uri url,String where,String[] selectionArgs) • 刪除Uri指定並符合條件的資料 為你把關每一道 學習品質 360
  • 137. Content Provider元件 • ContentResolver • 外部應用程式可以透過ContentResolver介面來存取 ContentProvider所提供的資料 • ContentResolver物件是透過Activity.getContentResolver()取得 • ContentResolver所提供的存取介面 • query(Uri uri,String[] projection,String selection,String[] selectionArgs,String sortOrder) • insert(Uri url,ContentValues values) • update(Uri url,ContentValues values,String where,String[] selectionArgs) • delete(Uri url,String where,String[] selectionArgs) Application Application URI Content Content Activity Data Resolver query Provider insert update 為你把關每一道 學習品質 delett 361
  • 138. Content Provider元件 • ContentProvider 中使用的Uri形式 • content://contacts/people/ 代表全部聯絡人資料 • content://contacts/people/1 代表ID為1的連絡人資料 • Uri的組成結構: content://authority/path/id • 第一部份:content:// • 必要的標準前置碼(prefix) • 第二部份:authority • 提供者的名稱,在此建使用完全套件名稱定義以避免名稱出現衝 突狀況 • 第三部份:path • 為提供者內部的虛擬目錄路徑 • 第四部份:id • 請求之特定記錄的主鍵ID,若要請求所有記錄可以直接以/結尾 為你把關每一道 學習品質 362
  • 139. ContentProvider元件-讀取連絡人資料 • Android內建的ContentProvider • content://browser • content://contacts • content://media • content://settings • Step1:於AndroidManifest.xml中加入權限 <uses-permission android:name="android.permission.READ_CONTACTS" /> • Step2:取得ContentResolver物件,query連絡人資料 import android.provider.ContactsContract; import android.content.ContentResolver; ContentResolver cr = getContentResolver(); Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null); 為你把關每一道 學習品質 363
  • 140. Content Provider元件-讀取連絡人資料 • Step3:取得連絡人姓名 String name = cur.getString(cur.getColumnIndex("display_name")); • Ste4:取得連絡人ID (2.0.1後改版,Phone移至不同URI) long id = cur.getLong(cur.getColumnIndex(" _id")); • Step5:透過ID重新查尋得使用者電話 Cursor pcur = getContentResolver().query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null ,ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + Long.toString(id), null, null); String strPhoneNumber = pcur.getString( pcur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); 為你把關每一道 學習品質 364
  • 141. 範例練習 範例專案名: ex08_04_Contentprovider 練習目標:  學習如何建立ContentResolver並連接至Android 的連絡人Content Povider,取得用戶的連絡人清 單資料 程式撰寫  透過getContentResolver ()取得ContentResolver 物件  連接至Android CONTENT_URI ,並將資料透過 adapter顯示於ListView上 操作練習  透過模擬器操作 為你把關每一道 學習品質 365
  • 142. ContentProvider元件-自建ContentProvider • 修改先前的日記簿範列,將新增、刪除、修改與查尋操作改以 ContentProvider的方式來實作。 ActivityDiaryEdit EditText EditText Button DiaryContentProvider insertDiary() Content extend ContentProvider updateDiary() Resolver Content query() Provider Insert() delete() ActivityMain extends ListActivity update() onMenuItemSelected() onCreateOptionsMenu() Content onOptionsItemSelected() Resolver onListItemClick() SQLiteOpenHelper SimpleCursorAdapter Diary Query結 NAME:database Cursor BaseColumns 為你把關每一道 學習品質 果 TABLE: diary 366
  • 143. ContentProvider元件-自建ContentProvider • Diary類別實作 public final class Diary { //這裡的 AUTHORITY 要求是唯一,而且和Manifest當中provider標籤的AUTHORITY內容一致 public static final String AUTHORITY = "com.ex09_2_contentprovider.diarycontentprovider"; private Diary() {} public static final class DiaryColumns implements BaseColumns { // This class cannot be instantiated private DiaryColumns() {} public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/diaries"); public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.google.diary"; public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.google.diary"; public static final String DEFAULT_SORT_ORDER = "created DESC"; public static final String TITLE = "title"; public static final String BODY = "body"; _id title body create public static final String CREATED = "created"; unique-id 標題 內文 建立時間 } } unique-id 標題 內文 建立時間 為你把關每一道 學習品質 367
  • 144. ContentProvider元件-自建ContentProvider • DiaryContentProvider類別實作 • 繼承自ContentProvider類別 • 定義Uri類別變數: content://com.ex09_2_contentprovider.diarycontentprovider/diaries • content:固定的開頭不用更改 • AUTHORITY:授權字串必須是唯一的,宣告告於AndroidManifest.xml • request: 資料型別,在此只定義一個型別,對應資料表名稱。也可以設 計成兩個公開的資料表例如 diaries/my ,diaries/other. • id:代表要存取那一筆資料 • 建構資料儲存系統,在此使用的是SQLite資料庫 • 實作ContentProvider抽像方法 • oncreate();query();inster();delete();update();getType(); • 於AndroidManifest.xml中加入<provider>標籤 <provider android:name="DiaryContentProvider" android:authorities="com.ex09_2_contentprovider.diarycontentprovider" /> 為你把關每一道 學習品質 368
  • 145. ContentProvider元件-自建ContentProvider • android.database.sqlite.SQLiteQueryBuilder類別介紹 • 建構SQL查尋語法的輔助類別 SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); • qb.query(SQLiteDatabase db,String[] projectionIn,String selection,String[] selectionArgs,String groupBy,String having,String sortOrder,String limit); 為你把關每一道 學習品質 369
  • 146. ContentProvider元件-自建ContentProvider • android.content.ContentUris類別介紹 • URI的一個補助類別,包含了二個函式 • Public static Uri withAppendedId(Uri contentUri,long id) • 負責將id和Uri串接在一起成新的Uri。 Uri diaryUri = ContentUris.withAppendedId( Diary.DiaryColumns.CONTENT_URI, rowId) • Public static long parseId(Uri contentUri) • 負責把Uri後的id解析出來。 • 例如com.ex09_2_contentprovider.diarycontentprovider/100 透過parseId後回傳值為100 為你把關每一道 學習品質 370