Android + Service 建國科技大學 資管系 饒瑞佶.

Slides:



Advertisements
Similar presentations
3.2 Java的类 Java 类库的概念 语言规则——程序的书写规范 Java语言 类库——已有的有特定功能的Java程序模块
Advertisements

第13章 繪圖與多媒體 13-1 顯示圖檔-行動相簿 13-2 音樂播放-音樂播放器 13-3 影片播放-視訊播放器
實驗五:多媒體播放器選單介面.
Part 2 開發Android應用程式的流程
位置與地圖應用 此投影片為講解Android如何取得定位經緯度和使用Google Map地圖.
第二章 JAVA语言基础.
類別與物件 Class & Object.
Android + BLE 建國科技大學 資管系 饒瑞佶 2017/3 v1.
Android + Web Service 建國科技大學 資管系 饒瑞佶 2017/3 V1.
ArrayAdapter & Spinner
建立Android新專案 建國科技大學 資管系 饒瑞佶 2010/10.
厦门大学数据库实验室 报告人:谢荣东 导师:林子雨 2014年8月30日
實驗四:單位轉換程式.
第7章 Android文件与本地数据库(SQLite)
Chapter 13 Android 實戰演練.
Android + JUnit 單元測試 建國科技大學資管系 饒瑞佶 2012/8/19V4.
2.1 基本資料型別 2.2 變數 2.3 運算式與運算子 2.4 輸出與輸入資料 2.5 資料型別轉換 2.6 實例
實驗十三:顯示目前經緯度位置.
Ch06 再談選單元件 物件導向系統實務.
使用Android控制Arduino 史先强
7.3 Intent传值.
第10章 App微信分享的实现 倚动实验室.
Android資料庫處理 Android智慧型手機程式設計 程式設計與應用班 建國科技大學 資管系 饒瑞佶 2012/4 V1
第一个Android程序 本讲大纲: 1、创建Android应用程序 2、Android项目结构说明 3、运行Android应用程序
第8章 Android内容提供者(ContentProvider)应用
Chapter 6 Advanced UI Design.
第四次课后作业 1 问题描述: 将谜题定义为:包含一个初始位置,一个目标位置,以及用于判断是否是有效移动的规则集。
Chapter 7 Android應用元件 Android應用元件可以幫助我們獲得系統資源訊息(ActivityManager)、提供系統服務(Service)、搜尋系統服務(SearchManager)、監聽Intent訊息(Broadcast Receiver)以及資料共享(ContentProvider和ContentResolver)。
Android介面設計 Android智慧型手機程式設計 建國科技大學 資管系 饒瑞佶 2012/4 V1 2012/8 V2
Chapter 6 進階UI設計.
第4章 Android生命周期.
第9章 使用意圖啟動活動與內建應用程式 9-1 意圖的基礎 9-2 使用意圖啟動活動
ANDROID PROGRAMMING2.
程式設計實作.
CH7 佈局、按鈕與文字編輯元件.
Android 基礎.
實驗十四:顯示與控制地圖.
第2讲 移动应用开发基础知识(二) 宋婕
RecyclerView and CardView
建立Android新專案 Android智慧型手機程式設計 程式設計與應用班 建國科技大學 資管系 饒瑞佶 2012/4 V1
第8章 Service解析.
第6章 建立Android使用介面 6-1 介面元件的基礎 6-2 Android的事件處理 6-3 按鈕元件 6-4 文字元件
C/C++/Java 哪些值不是头等程序对象
實驗十一:待辦事項程式 (儲存在手機上).
主编:钟元生 赵圣鲁.
Android Studio介面設計 建國科技大學資管系 饒瑞佶 2016/3 V1.
Android Application Component
JAVA 编 程 技 术 主编 贾振华 2010年1月.
Chapter 5 Basic UI Design.
實驗九:延續實驗八, 製作一個完整音樂播放器
Location Based Services - LBS
進階UI元件:Spinner與接合器 靜宜大學資管系 楊子青
補間動畫 (Tween Animation) 靜宜大學資管系 楊子青
第二章 Java基本语法 讲师:复凡.
第五次课后作业 1 问题描述: 将谜题定义为:包含一个初始位置,一个目标位置,以及用于判断是否是有效移动的规则集。
第二章 Java语法基础.
第二章 Java基本语法 讲师:复凡.
進階UI元件:ListView元件以及複選 靜宜大學資管系 楊子青
RecyclerView and CardView
Android藍芽聊天室 SDK內的範例程式
Android Speech To Text(STT)
Activity的生命週期: 播放音樂與影片 靜宜大學資管系 楊子青
用Intent啟動程式中的其他Activity、運用WebView顯示網頁 靜宜大學資管系 楊子青
第2章 Java语言基础.
Android进程间通讯.
讀取網路資料及JSON開放資料 靜宜大學資管系 楊子青
加速感測器 靜宜大學資管系 楊子青.
第二章 Java基础语法 北京传智播客教育
Part 8 Broadcast Receiver、Service和App Widget
進階UI元件:Spinner與接合器 靜宜大學資管系 楊子青
Presentation transcript:

Android + Service 建國科技大學 資管系 饒瑞佶

Android Service Android中的Service與Activity不同,Service不具有UI 介面,不能自己啟動

Android Service life cycle Android Service的生命週期不同於Activity, Service的生命 週期只有onCreate(),onStart(),onDestroy()三個方法 第一次啟動Service時,首先執行onCreate(),再執行 onStart()方法 停止Service則是執行onDestroy()方法 如果Service已經啟動,再次啟動Service時,將不再執行 onCreate()方法,而是直接執行onStart()方法

Service life cycle 不牽涉到Activity與Service兩邊互動與資料傳輸

Service lifecycle Activity與Service需要互相傳輸使用 Activity單純呼叫Service

Activity呼叫Service內的方法 Service做一個計時器方法,Activity呼叫後取得結果顯示在畫面上 Android bound service Activity呼叫Service內的方法 Service做一個計時器方法,Activity呼叫後取得結果顯示在畫面上

建立一個Service-BoundService

Service名稱

會自動註冊到AndroidManidest.xml中

預設有BoundService與onBind事件

Service lifecycle Activity與Service需要互相傳輸使用 Activity單純呼叫Service

加入onCreate事件

onCreate事件

public class BoundService extends Service { private static String LOG_TAG = "ServiceTest"; // debug用 private Chronometer mChronometer; // 計時器 public BoundService() { } @Override public void onCreate() { super.onCreate(); Log.v(LOG_TAG, "onCreate"); mChronometer = new Chronometer(this); mChronometer.setBase(SystemClock.elapsedRealtime()); mChronometer.start(); // 開始計時

onBind事件 @Override public IBinder onBind(Intent intent) { Log.v(LOG_TAG, "onBind2"); return mBinder; }

建立Activity與Service間聯繫(bind) private IBinder mBinder = new MyBinder(); public class MyBinder extends Binder { BoundService getService() { return BoundService.this; }

加入onRebind與onUnbind與onDestroy事件

加入對應的事件程式 @Override public void onRebind(Intent intent) { Log.v(LOG_TAG, "onRebind"); super.onRebind(intent); } public boolean onUnbind(Intent intent) { Log.v(LOG_TAG, "onUnbind"); return true; public void onDestroy() { super.onDestroy(); Log.v(LOG_TAG, "onDestroy"); mChronometer.stop();

Service中加入計時程式 // 等待Activity呼叫使用 public String getTimestamp() { long elapsedMillis = SystemClock.elapsedRealtime() - mChronometer.getBase(); int hours = (int) (elapsedMillis / 3600000); int minutes = (int) (elapsedMillis - hours * 3600000) / 60000; int seconds = (int) (elapsedMillis - hours * 3600000 - minutes * 60000) / 1000; int millis = (int) (elapsedMillis - hours * 3600000 - minutes * 60000 - seconds * 1000); return hours + ":" + minutes + ":" + seconds + ":" + millis; }

layout <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="edu.ctu.rcjao.androidservice.MainActivity"> <Button android:id="@+id/print_timestamp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:text="從Service取出計時時間" /> <TextView android:id="@+id/timestamp_text" android:text="" /> android:id="@+id/stop_service" android:text="停止Service" /> </LinearLayout> layout

設定Activity bind Service

public class MainActivity extends AppCompatActivity { BoundService mBoundService; // Service boolean mServiceBound = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 對應畫面物件 final TextView timestampText = (TextView) findViewById(R.id.timestamp_text); Button printTimestampButton = (Button) findViewById(R.id.print_timestamp); Button stopServiceButon = (Button) findViewById(R.id.stop_service); // 從Service取出計時時間 printTimestampButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if (mServiceBound) { // 如果已經bind,呼叫Service內的getTimestamp方法 timestampText.setText(mBoundService.getTimestamp()); } }); // 停止Service stopServiceButon.setOnClickListener(new View.OnClickListener() { if (mServiceBound) { // 如果已經bind,切斷Service unbindService(mServiceConnection); mServiceBound = false; Intent intent = new Intent(MainActivity.this, BoundService.class); stopService(intent); 呼叫Service 停止Service

建立onStart與onStop @Override protected void onStart() { super.onStart(); Intent intent = new Intent(this, BoundService.class); startService(intent); bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE); } protected void onStop() { super.onStop(); if (mServiceBound) { unbindService(mServiceConnection); mServiceBound = false;

建立mServiceConnection private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { mServiceBound = false; } public void onServiceConnected(ComponentName name, IBinder service) { BoundService.MyBinder myBinder = (BoundService.MyBinder) service; mBoundService = myBinder.getService(); mServiceBound = true; };

result 每按一次取出經過的時間

執行log

從Service更新Activity Service呼叫Activity方法

Layout加入一個TextView 用來顯示Service更新的資料 android:id="@+id/timestamp_text_from_service" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:text="" />

修改Service,加入callback Callbacks activity; //宣告 // 加入callbacks interface(需要到Activity實作updateClient) public interface Callbacks{ public void updateClient(long data); } // 註冊Activity 成為Callbacks client public void registerClient(Activity activity){ this.activity = (Callbacks)activity;

修改Service,加入計時與更新Activity // 開始計時 private long startTime = 0; private long millis = 0; public void startCounter(){ // 由Activity發動 startTime = System.currentTimeMillis(); handler.postDelayed(serviceRunnable, 0); Toast.makeText(getApplicationContext(), "開始計時", Toast.LENGTH_SHORT).show(); } // 停止計時 public void stopCounter(){ handler.removeCallbacks(serviceRunnable); Handler handler = new Handler(); Runnable serviceRunnable = new Runnable() { @Override public void run() { millis = System.currentTimeMillis() - startTime; activity.updateClient(millis); // 透過callback更新Activity handler.postDelayed(this, 1000); };

修改Activity 繼承Callback 會被要求實作updateClient

加入畫面TextView物件對應

開始與停止計時

註冊Activity到Service

@Override public void updateClient(long data) { int seconds = (int) (data / 1000) % 60 ; int minutes = (int) ((data / (1000*60)) % 60); int hours = (int) ((data / (1000*60*60)) % 24); timestampTextfromservice.setText((hours>0 ? String.format("%d:", hours) : "") + ((minutes<10 && hours > 0)? "0" + String.format("%d:", minutes) : String.format("%d:", minutes)) + (seconds<10 ? "0" + seconds: seconds)); }

Service 範例 播放音樂

單純呼叫

Service流程

新增一組Activity與layout

MediaController.java

<LinearLayout xmlns:android="http://schemas. android xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_media_controller" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="edu.ctu.rcjao.androidservice.MediaController" android:orientation="vertical"> <TextView android:text="" android:layout_height="wrap_content" android:id="@+id/textState " android:textSize="30sp" /> <Button android:text="播放" android:id="@+id/Play" android:text="繼續播放" android:id="@+id/ContinuePlay" android:text="暫停" android:id="@+id/Pause" android:text="停止" android:id="@+id/Stop" </LinearLayout> layout 顯示播放狀態

加入OnClickListener

設定對應畫面物件

public class MediaController extends AppCompatActivity implements View public class MediaController extends AppCompatActivity implements View.OnClickListener { Button buttonPlay, buttonContinuePlay, buttonStop, buttonPause; TextView textState; Intent intent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_media_controller); // 對應layout物件 buttonPlay = (Button) findViewById(R.id.Play); buttonContinuePlay = (Button) findViewById(R.id.ContinuePlay); buttonPause = (Button) findViewById(R.id.Pause); buttonStop = (Button) findViewById(R.id.Stop); textState = (TextView)findViewById(R.id.textState); // 設定onclick事件 buttonPlay.setOnClickListener(this); buttonStop.setOnClickListener(this); buttonPause.setOnClickListener(this); buttonContinuePlay.setOnClickListener(this); intent = new Intent(this, MusicService.class); //透過intent啟動Service }

onClick @Override public void onClick(View v) { switch (v.getId()) { case R.id.Play: playAction(1); textState.setText("- Playing -"); buttonPlay.setEnabled(false); buttonContinuePlay.setEnabled(false); buttonPause.setEnabled(true); buttonStop.setEnabled(true); break; case R.id.ContinuePlay: playAction(2); case R.id.Pause: playAction(3); textState.setText("- Pause -"); buttonPlay.setEnabled(true); buttonContinuePlay.setEnabled(true); buttonPause.setEnabled(false); case R.id.Stop: playAction(4); textState.setText("- Stop -"); buttonStop.setEnabled(false); } onClick

新增playAction方法 // 執行的播放動作 private void playAction(int op) { Bundle bundle = new Bundle(); bundle.putInt("op", op); //設定intent啟動的動作 intent.putExtras(bundle); MediaController.this.startService(intent); //啟動service,透過intent傳送資料 }

建立Service-MusicService 會自動註冊到AndroidManifest.xml中

建立播放音樂物件

加入onStart 音樂檔 @Override public void onStart(Intent intent, int startId) { //完成onCreate()後啟動 if (intent != null) { Bundle bundle = intent.getExtras(); if (bundle != null) { int op = bundle.getInt("op"); switch (op) { case 1: //play player=MediaPlayer.create(this, R.raw.test) ; player.start(); break; case 2: //replay case 3: //pause player.pause(); case 4: //stop if (player != null) { player.stop(); } 加入onStart 音樂檔

加入onStop @Override public void onDestroy() { super.onDestroy(); if (player != null) { player.stop(); player.release(); }

執行 當App在背景時,音樂仍然會繼續播放