實現的功能:計時器。
實現的思路:1)後台Service每隔1秒發送廣播通知時間已發生變化;
2)UI層(Activity)通過BroadcastReceiver接收到廣播,更新顯
示的時間。
關鍵技術點:Service的應用、BroadcastReceiver的應用
說明:1)Activity與通過startService方法啟動的Service之間無法直接進行通信,但是借助BroadcastService可以實現兩者之間的通信。
2)實現計時器的方式有很多種,比如通過Thread的sleep等,此處只是演示Service與BroadcastService的組合應用(可以將Service中獲取當前時間的操作想象為非常耗時的操作,所以不宜直接在UI層來做)。
3)此處演示的Service與BroadcastService的組合是“單向通信”即:UI層只是被動接收Service發來的廣播,而沒有主 動發送廣播控制後台Service。下一篇文章將會編寫一個實例進行演示“雙向通信”。
第一步:新建一個工程,命名為DynamicUI,Activity命名為DynamicUIActivity。
修改布局文件main.xml,代碼如下:
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:Android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical" android:layout_width="fill_parent"
- android:layout_height="fill_parent" android:background="#FFFFFF">
- <TextView android:id="@+id/tv" android:layout_width="wrap_content"
- android:layout_height="wrap_content" android:text="當前時間: " />
- <TextView android:id="@+id/time" android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_toRightOf="@id/tv" />
- </RelativeLayout>
DynamicUIActivity類代碼如下:
- package com.zyg.demo.service.dynamicui;
-
- import android.app.Activity;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.graphics.Color;
- import android.os.Bundle;
- import android.widget.TextView;
-
- public class DynamicUIActivity extends Activity {
- public static String TIME_CHANGED_ACTION = "com.zyg.demo.service.dynamicui.action.TIME_CHANGED_ACTION";
- public static TextView time = null;
- private Intent timeService = null;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
-
- //初始化UI
- initUI();
- System.out.println("initUI");
-
- //注冊廣播-方法1
- /*
- * 配置
- * <receiver android:name=".UITimeReceiver">
- <intent-filter>
- <action android:name="com.zyg.demo.service.dynamicui.action.TIME_CHANGED_ACTION"/>
- </intent-filter>
- </receiver>
- */
-
- //注冊廣播-方法2
- //注冊廣播,監聽後台Service發送過來的廣播
- //registerBroadcastReceiver();
-
- //啟動服務,時間改變後發送廣播,通知UI層修改時間
- startTimeService();
- }
-
- public TextView getTimeTextView(){
- return time;
- }
-
- /**
- * 初始化UI
- */
- private void initUI(){
- time = (TextView)findViewById(R.id.time);
- time.setTextColor(Color.RED);
- time.setTextSize(15);
- }
-
- /**
- * 注冊廣播
- */
- private void registerBroadcastReceiver(){
- UITimeReceiver receiver = new UITimeReceiver();
- IntentFilter filter = new IntentFilter(TIME_CHANGED_ACTION);
- registerReceiver(receiver, filter);
- }
-
- /**
- * 啟動服務
- */
- private void startTimeService(){
- timeService = new Intent(this,TimeService.class);
- this.startService(timeService);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- //停止服務
- stopService(timeService);
- }
- }
第二步:實現自定義BroadcatReceiver類UITimeReceiver,負責接收從後台Service發送過來的廣播,獲取最新時間數據後更新UI層組件。本類最好作為UI層(Activity)的內部類,此處將其作為外部類實現(通過xml文件配置注冊BroadcatReceiver,如果是內部類如何通過xml文件配置目前沒找到),有意顯示如此做導致代碼不夠優雅。
UITimeReceiver代碼如下:
- package com.zyg.demo.service.dynamicui;
-
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.os.Bundle;
-
- /**
- * 自定義的UI層BroadcastReceiver,負責監聽從後台Service發送過來的廣播,根據廣播數據更新UI
- * @author zhangyg
- */
- public class UITimeReceiver extends BroadcastReceiver{
- private DynamicUIActivity dUIActivity = new DynamicUIActivity();
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if(DynamicUIActivity.TIME_CHANGED_ACTION.equals(action)){
- Bundle bundle = intent.getExtras();
- String strtime = bundle.getString("time");
- //此處實現不夠優雅,為了在UITimeReceiver中使用DynamicUIActivity中的TextView組件time,而將其設置為public類型,
- //更好的實現是將UITimeReceiver作為DynamicUIActivity的內部類
- dUIActivity.time.setText(strtime);
- }
- }
- }
第三步:實現自定義Service類TimeService,其代碼如下:
- package com.zyg.demo.service.dynamicui;
-
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import java.util.Timer;
- import java.util.TimerTask;
-
- import android.app.Service;
- import android.content.ComponentName;
- import android.content.Intent;
- import android.os.Bundle;
- import android.os.IBinder;
- import android.util.Log;
-
- public class TimeService extends Service{
- private String TAG = "TimeService";
- private Timer timer = null;
- private SimpleDateFormat sdf = null;
- private Intent timeIntent = null;
- private Bundle bundle = null;
- @Override
- public void onCreate() {
- super.onCreate();
- Log.i(TAG,"TimeService->onCreate");
- //初始化
- this.init();
- //定時器發送廣播
- timer.schedule(new TimerTask() {
- @Override
- public void run() {
- //發送廣播
- sendTimeChangedBroadcast();
- }
- }, 1000,1000);
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- Log.i(TAG,"TimeService->onBind");
- return null;
- }
-
- /**
- * 相關變量初始化
- */
- private void init(){
- timer = new Timer();
- sdf = new SimpleDateFormat("yyyy年MM月dd日 "+"hh:mm:ss");
- timeIntent = new Intent();
- bundle = new Bundle();
- }
-
- /**
- * 發送廣播,通知UI層時間已改變
- */
- private void sendTimeChangedBroadcast(){
- bundle.putString("time", getTime());
- timeIntent.putExtras(bundle);
- timeIntent.setAction(DynamicUIActivity.TIME_CHANGED_ACTION);
- //發送廣播,通知UI層時間改變了
- sendBroadcast(timeIntent);
- }
-
- /**
- * 獲取最新系統時間
- * @return
- */
- private String getTime(){
- return sdf.format(new Date());
- }
-
- @Override
- public ComponentName startService(Intent service) {
- Log.i(TAG,"TimeService->startService");
- return super.startService(service);
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- Log.i(TAG,"TimeService->onDestroy");
- }
- }
第四步:修改AndroidManifest.xml文件,代碼如下:
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.zyg.demo.service.dynamicui"
- android:versionCode="1"
- android:versionName="1.0">
- <uses-sdk android:minSdkVersion="8" />
-
- <application android:icon="@drawable/icon" android:label="@string/app_name">
- <activity android:name=".DynamicUIActivity"
- android:label="@string/app_name">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- <receiver android:name=".UITimeReceiver">
- <intent-filter>
- <action android:name="com.zyg.demo.service.dynamicui.action.TIME_CHANGED_ACTION"/>
- </intent-filter>
- </receiver>
- <service android:name=".TimeService"></service>
- </application>
- </manifest>
第五步:運行程序,效果如下: