天天看點

Android 實作service背景多任務下載下傳notification進度條更新

隻需要一串 URL 位址,就可以實作 背景多任務下載下傳的demo,notification進度條更新資訊封裝好直接提取,更新頻率等問題都已優化。

demo源碼下載下傳位址在CSDN上和eoe android裡都有,這邊就給個連結吧。

由于是很久之前的在eoe android 社群裡發帖讨論回複過相關問題了,這裡就發個原帖位址連結吧。

service背景多任務下載下傳notification進度條斷點續傳。

首先是service服務檔案,内部包含相關注解。主要是支援背景下載下傳,并且更新下載下傳進度到狀态欄。

package com.ljp.download.service;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;
import com.ljp.download.tempActivity;
import com.ljp.version.R;
public class DownloadService extends Service {
private NotificationManager notificationMrg;
public static Map<String, MyThread> threadcache = new HashMap<String, MyThread>();
private Holder holder;
int notifyflag = 1;

private ConnectivityManager connectivityManager;
private NetworkInfo info;

public void onCreate() {
super.onCreate();
notificationMrg = (NotificationManager) this
.getSystemService(android.content.Context.NOTIFICATION_SERVICE);


// 注冊網絡監聽接收器
IntentFilter mFilter = new IntentFilter();
mFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
mFilter.addAction("android.basic.notification.click.pause");
mFilter.addAction("android.basic.notification.click.cancel");
mFilter.addAction("android.basic.notification.click.restart");
registerReceiver(stateReceiver, mFilter);
// 注冊任務廣播接收器
}

@SuppressWarnings("null")
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
System.out.println("Get intent:" + intent);
final String apkurl = intent.getStringExtra("url");
System.out.println("Get url from intent:" + apkurl);


Intent notificationIntent = new Intent(getApplicationContext(),
tempActivity.class);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
notificationIntent.putExtra("url", apkurl);
Bundle bundle = new Bundle();
bundle.putInt("flag", notifyflag);
Log.i("avi", "loadfile中的flag     " + notifyflag);
notificationIntent.putExtras(bundle);
// addflag設定跳轉類型
PendingIntent contentIntent1 = PendingIntent.getActivity(
getApplicationContext(), notifyflag, notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
// 建立Notifcation對象,設定圖示,提示文字
Notification notification = new Notification(R.drawable.ic_launcher,
"下載下傳進度", System.currentTimeMillis());// 設定Notification出現時的聲音,一般不建議自定義
// System.currentTimeMillis()
notification.flags = Notification.FLAG_ONGOING_EVENT
| Notification.FLAG_NO_CLEAR;// 出現在 “正在運作的”欄目下面
// notification.flags |= Notification.FLAG_NO_CLEAR;// 标題欄預設清除按鈕失效
RemoteViews contentView1 = new RemoteViews(getPackageName(),
R.layout.notification_version);
contentView1.setTextViewText(R.id.n_title, "準備下載下傳");
contentView1.setTextViewText(R.id.n_text, "目前進度:" + 0 + "% ");
contentView1.setProgressBar(R.id.n_progress, 100, 0, false);
notification.contentView = contentView1;
notification.contentIntent = contentIntent1;


final MyThread thread = new MyThread(notification, apkurl, notifyflag++);
thread.setchanger(true);
threadcache.put(apkurl, thread);
thread.start();
return START_REDELIVER_INTENT;
}


@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(stateReceiver);
}


// 狀态欄視圖更新
private Notification displayNotificationMessage(Notification notification,
int count, int flag, String url, String filename) {
notification.contentIntent = receiveMsmIntent(flag, url);
RemoteViews contentView1 = notification.contentView;
Log.i("TAG", "updata   flag==  " + flag);
Log.i("TAG", "updata   count==  " + count);
Log.i("TAG", "updata   filename==  " + filename);
contentView1.setTextViewText(R.id.n_title, filename);
contentView1.setTextViewText(R.id.n_text, "目前進度:" + count + "% ");
contentView1.setProgressBar(R.id.n_progress, 100, count, false);
Log.i("temp", "diaplaynotification   " + flag);
notification.contentView = contentView1;
// 送出一個通知在狀态欄中顯示。如果擁有相同标簽和相同id的通知已經被送出而且沒有被移除,該方法會用更新的資訊來替換之前的通知。
notificationMrg.notify(flag, notification);
return notification;


}


@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}


private void sendMsg(int what, int c, String url,
Notification notification, int flag, Uri uri, String filename,
boolean changer) {
Message msg = new Message();
msg.what = what;// 用來識别發送消息的類型
msg.arg1 = 0;
holder = new Holder();
holder.count = c;
holder.url = url;
holder.flag = flag;
holder.notify = notification;
holder.Uri = uri;
holder.filename = filename;
holder.changer = changer;
msg.obj = holder;// 消息傳遞的自定義對象資訊
handler.sendMessage(msg);
}


// 定義一個Handler,用于處理下載下傳線程與主線程間通訊
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
final Holder data = (Holder) msg.obj;
if (!Thread.currentThread().isInterrupted()) {
// 判斷下載下傳線程是否中斷
switch (msg.what) {
case 1:
Log.i("TAG", "handlemessage中的 case 1: data.count     "
+ data.count);
Log.i("TAG", "handlemessage中的 case 1: flag          "
+ data.flag);
if (data.count >= 99) {
notificationMrg.cancel(data.flag);
break;
}


if (threadcache.containsKey(data.url)) {
// 每次更新時,先以key,掃描hashmap,存在則讀取出來。
Notification notification;
MyThread thread;
thread = threadcache.get(data.url);
notification = thread.notification;
notification = displayNotificationMessage(notification,
data.count, data.flag, data.url, data.filename);
thread.notification = notification;
threadcache.put(data.url, thread);
}
break;
case 2:
Log.i("avi", "case 2中filename :  " + data.filename);
Log.i("avi", "case 2中filename :  " + data.changer);
if (data.changer) {
openfile(data.Uri);
} else {
Log.i("avi", "取消下載下傳");
Toast.makeText(getApplicationContext(),
data.filename + "下載下傳取消", 1).show();
}
threadcache.remove(data.url);
Intent cancel =new Intent().setAction("android.basic.button.click.cancel");
cancel.putExtra("url", data.url);
sendBroadcast(cancel);
break;
case -1:
String error = msg.getData().getString("error");
Toast.makeText(getApplication(), data.filename + "下載下傳異常終止",
1).show();
Intent cancel2 =new Intent().setAction("android.basic.button.click.cancel");
cancel2.putExtra("url", data.url);
sendBroadcast(cancel2);
break;
// 否則輸出錯誤提示
}
}
super.handleMessage(msg);
}
};


public void openfile(Uri url) {
Intent intent = new Intent(Intent.ACTION_VIEW);
// 差別于預設優先啟動在activity棧中已經存在的activity(如果之前啟動過,并還沒有被destroy的話)而是無論是否存在,都重新啟動新的activity
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(url, "application/vnd.android.package-archive");
startActivity(intent);
}


public class Holder {
Notification notify;
String url;
int count;
int flag;
Uri Uri;
String filename;
boolean changer;
}


private BroadcastReceiver stateReceiver = new BroadcastReceiver() {


@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();

if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
Log.d("mark", "網絡狀态已經改變");
connectivityManager = (ConnectivityManager)


getSystemService(Context.CONNECTIVITY_SERVICE);
info = connectivityManager.getActiveNetworkInfo();
if (info != null && info.isAvailable()) {
String name = info.getTypeName();
Log.d("mark", "目前網絡名稱:" + name);
} else {
Log.d("mark", "沒有可用網絡,下載下傳服務停止");
while (notifyflag > 0) {
notificationMrg.cancel(notifyflag);
notifyflag -= 1;
}
Toast.makeText(getApplicationContext(), "網絡異常,下載下傳服務停止!", 1)
.show();
onDestroy();
}
}

if (action.equals("android.basic.notification.click.cancel")) {
Bundle bundle = intent.getExtras();
int m = bundle.getInt("flag");
String url = intent.getStringExtra("url");
Log.i("avi", "cancel   clickbroadcast中         接收到的 flag: " + m);
Log.i("avi", "cancel   clickbroadcast中         接收到的 url: "
+ url);
notificationMrg.cancel(m);
if (threadcache.containsKey(url)) {
MyThread onethread = threadcache.get(url);
Log.i("avi", "cancel  clickbroadcast中 thread 線程      url: "
+ onethread.geturl());
onethread.setchanger(false);
Log.i("avi",
"cancel   clickbroadcast中 thread 線程      url: "
+ onethread.getchanger());
}
}

if (action.equals("android.basic.notification.click.pause")) {
Bundle bundle = intent.getExtras();
int m = bundle.getInt("flag");
String url = intent.getStringExtra("url");
Log.i("avi", "pause  clickbroadcast中         接收到的 flag: " + m);
Log.i("avi", "pause  clickbroadcast中         接收到的 url: " + url);
// notificationMrg.cancel(m);
if (threadcache.containsKey(url)) {
MyThread onethread = threadcache.get(url);
Log.i("avi", "pause   clickbroadcast中 thread 線程      url: "
+ onethread.geturl());
onethread.setSuspend(true);
// 目前線程暫停/ 等待
}
}

if (action.equals("android.basic.notification.click.restart")) {
Bundle bundle = intent.getExtras();
int m = bundle.getInt("flag");
String url = intent.getStringExtra("url");
Log.i("avi", "restart  clickbroadcast中         接收到的 flag: " + m);
Log.i("avi", "restart  clickbroadcast中         接收到的 url: "
+ url);
// notificationMrg.cancel(m);
if (threadcache.containsKey(url)) {
MyThread onethread = threadcache.get(url);
Log.i("avi",
"restart   clickbroadcast中 thread 線程      url: "
+ onethread.geturl());
onethread.setSuspend(false);
// 調用setSuspend(false)讓目前線程恢複/喚醒
}
}
}
};



private PendingIntent receiveMsmIntent(int flag, String url) {
Intent intent = new Intent(getApplicationContext(), tempActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra("url", url);
Bundle bundle = new Bundle();
bundle.putInt("flag", flag);
intent.putExtras(bundle);
PendingIntent contentIntent = PendingIntent.getActivity(
getApplicationContext(), flag, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
return contentIntent;
}<pre name="code" class="java">//接下來時寫了一個自定義線程,專門用來處理下載下傳邏輯
public class MyThread extends Thread {
private boolean changer;
private String url;
private int flag;
private boolean suspend = false;
private String control = ""; // 隻是需要一個對象而已,這個對象沒有實際意義
private Notification notification;


public MyThread(Notification notification, String apkurl, int notifyflag) {
super();
this.notification = notification;
this.url = apkurl;
this.flag = notifyflag;
}


public void run() {
System.out.println("父類中的方法");
String url = geturl();
int flag = getflag();
String filename;
int first = url.lastIndexOf("/") + 1;
filename = url.substring(first, url.length()).toLowerCase();
Log.i("filename", "從url中截取的filename  " + filename);
double m = 0.0;


HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(url);
HttpResponse response;
try {
response = client.execute(get);
HttpEntity entity = response.getEntity();
double length = entity.getContentLength();
InputStream is = entity.getContent();
// 使用InputStream對檔案進行讀取,就是位元組流的輸入
FileOutputStream fileOutputStream = null;
File file = null;
Log.i("avi", "開關狀态      " + getchanger());
if (is != null && getchanger()) {
file = new File(Environment.getExternalStorageDirectory(),
filename);
fileOutputStream = new FileOutputStream(file);
byte[] buf = new byte[1024];
int ch = -1;
float count = 0;
// ch中存放從buf位元組數組中讀取到的位元組個數
while ((ch = is.read(buf)) != -1 && getchanger()) {


synchronized (control) {
if (getSuspend()) {
try {
Log.i("avi", "暫停下載下傳任務                "
+ getSuspend());
Intent pause =new Intent().setAction("android.basic.button.click.pause");
pause.putExtra("url", url);
sendBroadcast(pause);
control.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}


fileOutputStream.write(buf, 0, ch);
count += ch;
// 從位元組數組讀取資料read(buf)後,傳回,讀取的個數,count中儲存,已下載下傳的資料位元組數
double temp = count / length;
if (temp >= m) {
Log.i("TAG", "讀取位元組循環中的count" + temp);
m += 0.1;
int load = (int) (count * 100 / length);
sendMsg(1, load, url, notification, flag, null,
filename, true);
}
// 函數調用handler發送資訊
}
}
// 檔案輸出流為空,則表示下載下傳完成,安裝apk檔案
Uri Url = Uri.fromFile(file);
Log.i("TAG", "下載下傳完成,傳遞檔案位置Url  " + Url);


sendMsg(2, 0, url, notification, 0, Url, filename, getchanger());
fileOutputStream.flush();
if (fileOutputStream != null) {
fileOutputStream.close();
}
} catch (Exception e) {
sendMsg(-1, 0, url, notification, 0, null, filename, true);
}


}


public void setSuspend(boolean suspend) {
this.suspend = suspend;
if (!suspend) {
synchronized (control) {
String filename=geturlfilename(url);
Log.i("avi", filename+"繼續下載下傳   :   " + getSuspend());
Toast.makeText(getApplicationContext(), filename+"繼續下載下傳---", 1).show();
Intent restart=new Intent();
restart.setAction("android.basic.button.click.restart");
restart.putExtra("url", url);
sendBroadcast(restart);
control.notify();
}
}


}


public boolean getSuspend() {
return this.suspend;
}


// 設定開關狀态
public void setchanger(boolean changer) {
this.changer = changer;
}


public boolean getchanger() {
return this.changer;
}


public int getflag() {
return this.flag;
}


public String geturl() {
return this.url;
}

public String geturlfilename(String url){

String filename;
int first = url.lastIndexOf("/") + 1;
filename = url.substring(first, url.length()).toLowerCase();
return filename;
}


}


}
           

接下來時主界面測試代碼:

package com.ljp.download;


import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;


import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.ActivityGroup;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;


import com.ljp.download.service.DownloadService;
import com.ljp.download.service.DownloadService.MyThread;
import com.ljp.version.R;


public class ServiceDownLoadActivity extends ActivityGroup {


private String apkurl1 = "http://c.uzzf.com//ddl/anzhuozhinenguanjia.apk";
private String apkurl2 = "http://file.liqucn.com/upload/2011/liaotian/Youni_3.4.1.3.apk";
private String apkurl3 = "http://gdown.baidu.com/data/wisegame/77dae776f870e572/PPTVjuli_61.apk";
private String apkurl4 = "http://11.gddx1.crsky.com/sj/201302/TaoYouhuiSlide-v3.0.1.apk";
private String apkurl5 = "http://apka.mumayi.com/2013/07/26/36/366358/zhonghuawannianli_V4.2.0_mumayi_c2b92.apk";
    private Map<String,Button> buttoncache =new HashMap<String,Button>();
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_main);
final Button button1=(Button)findViewById(R.id.startdown01);
final Button button2=(Button)findViewById(R.id.startdown02);
final Button button3=(Button)findViewById(R.id.startdown03);
final Button button4=(Button)findViewById(R.id.startdown04);
final Button button5=(Button)findViewById(R.id.startdown05);
      button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int state=0;
boolean netflag =isNetworkAvailable();
Log.i("TAG", "網絡狀況netflag:   "+netflag);

Map<String, MyThread> threadcache ;
threadcache =DownloadService.threadcache;
String filename=geturlfilename(apkurl1);
if(threadcache.containsKey(apkurl1)| !netflag){
if(!netflag)Toast.makeText(getApplicationContext(), "網絡異常,請檢查你的網絡", 1).show();
else Toast.makeText(getApplication(), filename+"下載下傳運作中---", 1).show();
}else
{
Intent intent=new Intent(ServiceDownLoadActivity.this, DownloadService.class);  
//由intent啟動service,背景運作下載下傳程序,在服務中調用notifycation狀态欄顯示進度條
intent.putExtra("url", apkurl1);
startService(intent);
button1.setText("正在下載下傳中");
buttoncache.put(apkurl1, button1);}

}
}); 
      
      button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean state=true;
boolean netflag =isNetworkAvailable();
Log.i("TAG", "網絡狀況netflag:   "+netflag);

Map<String, MyThread> threadcache ;
threadcache =DownloadService.threadcache;
String filename=geturlfilename(apkurl2);
if(threadcache.containsKey(apkurl2)| !netflag){
if(!netflag)Toast.makeText(getApplicationContext(), "網絡異常,請檢查你的網絡", 1).show();
else Toast.makeText(getApplication(), filename+"下載下傳運作中---", 1).show();
}
else
{
Intent intent=new Intent(ServiceDownLoadActivity.this, DownloadService.class);  
//由intent啟動service,背景運作下載下傳程序,在服務中調用notifycation狀态欄顯示進度條
intent.putExtra("url", apkurl2);
startService(intent);
button2.setText("正在下載下傳中");
buttoncache.put(apkurl2, button2);}
}
}); 
      button3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean state=true;
boolean netflag =isNetworkAvailable();
Log.i("TAG", "網絡狀況netflag:   "+netflag);

Map<String, MyThread> threadcache ;
threadcache =DownloadService.threadcache;
String filename=geturlfilename(apkurl3);
if(threadcache.containsKey(apkurl3)| !netflag){
if(!netflag)Toast.makeText(getApplicationContext(), "網絡異常,請檢查你的網絡", 1).show();
else Toast.makeText(getApplication(), filename+"下載下傳運作中---", 1).show();
}
else
{
Intent intent=new Intent(ServiceDownLoadActivity.this, DownloadService.class);  
//由intent啟動service,背景運作下載下傳程序,在服務中調用notifycation狀态欄顯示進度條
intent.putExtra("url", apkurl3);
startService(intent);
button3.setText("正在下載下傳中");
buttoncache.put(apkurl3, button3);}
}
}); 
      button4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean state=true;
boolean netflag =isNetworkAvailable();
Log.i("TAG", "網絡狀況netflag:   "+netflag);

Map<String, MyThread> threadcache ;
threadcache =DownloadService.threadcache;
String filename=geturlfilename(apkurl4);
if(threadcache.containsKey(apkurl4)| !netflag){
if(!netflag)Toast.makeText(getApplicationContext(), "網絡異常,請檢查你的網絡", 1).show();
else Toast.makeText(getApplication(), filename+"下載下傳運作中---", 1).show();
}
else
{
Intent intent=new Intent(ServiceDownLoadActivity.this, DownloadService.class);  
//由intent啟動service,背景運作下載下傳程序,在服務中調用notifycation狀态欄顯示進度條
intent.putExtra("url", apkurl4);
startService(intent);
button4.setText("正在下載下傳中");
buttoncache.put(apkurl4, button4);}
}
});     
      button5.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean state=true;
boolean netflag =isNetworkAvailable();
Log.i("TAG", "網絡狀況netflag:   "+netflag);
Map<String, MyThread> threadcache ;
threadcache =DownloadService.threadcache;
String filename=geturlfilename(apkurl5);
if(threadcache.containsKey(apkurl5)| !netflag){
if(!netflag)Toast.makeText(getApplicationContext(), "網絡異常,請檢查你的網絡", 1).show();
else Toast.makeText(getApplication(), filename+"下載下傳運作中---", 1).show();
}
else
{
Intent intent=new Intent(ServiceDownLoadActivity.this, DownloadService.class);  
//由intent啟動service,背景運作下載下傳程序,在服務中調用notifycation狀态欄顯示進度條
intent.putExtra("url", apkurl5);
startService(intent);
button5.setText("正在下載下傳中");
buttoncache.put(apkurl5, button5);}
}
});  


IntentFilter mFilter =new IntentFilter();
mFilter.addAction("android.basic.button.click.cancel");
mFilter.addAction("android.basic.button.click.pause");
mFilter.addAction("android.basic.button.click.restart");
registerReceiver(clickReceiver, mFilter);


}


// NETWORK
public boolean isNetworkAvailable() {
Context context = getApplicationContext();
ConnectivityManager connect = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connect == null) {
return false;
} else// get all network info
{
NetworkInfo[] info = connect.getAllNetworkInfo();
if (info != null) {
for (int i = 0; i < info.length; i++) {
if (info[i].getState() == NetworkInfo.State.CONNECTED) {
return true;
}
}
}
}
return false;
}

public String geturlfilename(String url){

String filename;
int first = url.lastIndexOf("/") + 1;
filename = url.substring(first, url.length()).toLowerCase();
return filename;
}

private BroadcastReceiver clickReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
String url = intent.getStringExtra("url");
if (action.equals("android.basic.button.click.cancel")) {
Log.i("avi", "cancel   button中         接收到的 url: "+ url); 
    if(buttoncache.containsKey(url))
    {
    Button button=buttoncache.get(url);
    button.setText("開始下載下傳");}
}

if (action.equals("android.basic.button.click.pause")) {
Log.i("avi", "pause   button中         接收到的 url: "+ url); 
    if(buttoncache.containsKey(url))
    {
    Button button=buttoncache.get(url);
    button.setText("下載下傳暫停");}
}

if (action.equals("android.basic.button.click.restart")) {
Log.i("avi", "restart   button中         接收到的 url: "+ url); 
    if(buttoncache.containsKey(url))
    {
    Button button=buttoncache.get(url);
    button.setText("正在下載下傳中");}
}

}
};


}
           

首先是service服務檔案