2013年6月23日 星期日

Service BroadcastReceiver Notification 整合應用--在通知列上顯示時間,並常駐!!!

小小的研究心得~分享給大家!!!
程式在按開始後會顯示目前時間及一個計數值,並顯示在通知列上,且通知列上的時間
會持續更新
(顯示計數值是為了確定程式有持續在背景運行)
當使用者按裝置上的Home鍵,程式仍會在背景運行,可點擊通知列上的圖示返回程式
程式畫面:
 

程式流程:
MainActivity ==> 執行 Service (要執行的動作/運算)
Service ==> 運用 BroadcastReceiver 改變主畫面 UI / 生成 Notification
AndroidManifest.xml 要記得加上 service

程式碼:
=============layout=============

    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

   
        android:id="@+id/btn_start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="39dp"
        android:layout_marginTop="28dp"
        android:text="開始" />

   
        android:id="@+id/btn_stop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/btn_start"
        android:layout_alignBottom="@+id/btn_start"
        android:layout_centerHorizontal="true"
        android:text="結束" />

   
        android:id="@+id/tv_timer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/btn_start"
        android:layout_marginTop="19dp"
        android:text="Medium Text"
        android:textAppearance="?android:attr/textAppearanceMedium" />

   
        android:id="@+id/tv_counter"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/tv_timer"
        android:layout_below="@+id/tv_timer"
        android:layout_marginTop="19dp"
        android:text="Medium Text"
        android:textAppearance="?android:attr/textAppearanceMedium" />



=============MainActivity.java=============
package com.example.testservice003;

import android.os.Bundle;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.app.NotificationCompat;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity implements OnClickListener{
Button start,stop;
TextView show,counter;
static final String ActionFlag = "showtime"; //自訂動作
NotificationManager NM;
Context mContext;
myReceiver mr;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

start = (Button)this.findViewById(R.id.btn_start);
stop = (Button)this.findViewById(R.id.btn_stop);
show = (TextView)this.findViewById(R.id.tv_timer);
counter = (TextView)this.findViewById(R.id.tv_counter);
mContext = this;

//取得NotificationManager
NM = (NotificationManager)this.getSystemService(Context.NOTIFICATION_SERVICE);
//生成 BroadcastReceiver instance
mr = new myReceiver();
//設定自定動作給 Receiver 用
IntentFilter intentFilter = new IntentFilter(ActionFlag);
registerReceiver(mr, intentFilter);

start.setOnClickListener(this);
stop.setOnClickListener(this);
}

@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mr); //在Activity 消滅時才unregister
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

@Override
public void onClick(View v) {
Intent intent = new Intent(getBaseContext(), myService.class);
Bundle bundle = new Bundle();
switch (v.getId()) {
case R.id.btn_start:
//將動作傳給預備回傳資料的 Service
bundle.putString("action", ActionFlag);
intent.putExtras(bundle);
startService(intent);
break;
case R.id.btn_stop:
//將動作傳給預備回傳資料的 Service
bundle.putString("action", ActionFlag);
intent.putExtras(bundle);
stopService(intent);
break;
}
}

class myReceiver extends BroadcastReceiver{

@Override
public void onReceive(Context context, Intent intent) {
//判斷是否為自訂動作 showtime
if(intent.getAction()==ActionFlag){
//將傳回值塞入View 及 變數中
Bundle bundle = intent.getExtras();
show.setText(bundle.getString("time"));
counter.setText(bundle.getInt("counter")+"");
//取得預備要執行的動作
String action = bundle.getString("action");

if(action.equals("start")){
//準備返回用的Intent
Intent backToMain = new Intent(mContext,MainActivity.class);
//Bundle comebackbundle = new Bundle();
//comebackbundle.putString("comback", "我回來主程式了"); 這個要API Level16 才能用
//PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, backToMain, 0, comebackbundle);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, backToMain, 0);

Notification NF = new NotificationCompat.Builder(mContext)
.setContentTitle("顯示時間") //設定Notification 抬頭
.setContentText(bundle.getString("time")) //設定Notification 顯示內容
.setContentInfo("info訊息") //設定Notification 右方訊息
.setTicker("有時間顯示囉!!") //設定Notification 一開始顯示文字
.setSmallIcon(R.drawable.ic_launcher) //設定Notification 的Icon
.setContentIntent(pendingIntent) //設定Notification 點擊返回的Activity
.setAutoCancel(false) //設定Notification 是否點擊後就消除
.build();
         //設定Notification不被清除

          NF.flags = Notification.FLAG_NO_CLEAR;
//生成Notification 並給定識別號碼 1
NM.notify(1,NF);
}else{
//取消Notificaiton
NM.cancel(1);
}
}
}
}
}

=============myService.java=============
package com.example.testservice003;

import java.util.Date;

import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;

public class myService extends Service {
Handler handler = new Handler();
String action ="";
int counter;

@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public void onCreate() {

super.onCreate();
}

@Override
public void onDestroy() {
//移除Runnable
handler.removeCallbacks(timer);

//準備傳回資料到Receiver,準備關閉Notification
Intent intent = new Intent(action);
Bundle bundle = new Bundle();
bundle.putString("action", "stop");
intent.putExtras(bundle);
sendBroadcast(intent);

super.onDestroy();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//取得動作
action = intent.getExtras().getString("action");
//每隔一秒執行 timer 的動作
handler.postDelayed(timer, 1000);
return START_NOT_STICKY;
}

Runnable timer = new Runnable() {
@Override
public void run() {
counter++;
sendToReceiver(new Date().toString(), counter);
//每隔一秒重覆執行
handler.postDelayed(this, 1000);
}
};

private void sendToReceiver(String time,int number){
//預備將資料傳回給Receiver,由其來做UI的改變
Intent intent = new Intent(action);
Bundle bundle = new Bundle();
bundle.putString("time", time);
bundle.putInt("counter", number);
bundle.putString("action", "start");
intent.putExtras(bundle);
sendBroadcast(intent);
}
}
           
               
           
       
       
   

沒有留言 :

張貼留言