需要实现的效果: 多任务下载时,当点击通知中的某个进度条时,出来该应用的下载节界面,下载界面的进度条和单击的进度条进度保持一致
要求:不能用广播 / 最好是设计一个回调方法来实现DetailViewActivity界面进度条的更新 / 其它好的方法也可下载过程:
在DownloadService中通过下载器FileDownloader.download()进行通知中进度条更新:
在DownloadService中通过hander进行下载界面: 在DetailViewActivity中进行
DownloadService代码:
package cn.innofidei.android.innoet.service;import java.io.File;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
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.ProgressBar;
import android.widget.RemoteViews;
import android.widget.Toast;
import cn.innofidei.android.innoet.net.download.DownloadProgressListener;
import cn.innofidei.android.innoet.net.download.FileDownloader;
import cn.innofidei.android.innoet.net.download.UpdateProgress;import com.innofidei.android.innoet.DetailViewActivity;
import com.innofidei.android.innoet.InnoMarketApplication;
import com.innofidei.android.innoet.InnoMarketDataModelAdapter;
import com.innofidei.android.innoet.R;
import com.innofidei.android.innoet.utils.Constant;
public class DownloadService extends Service{
private static final String TAG = "DownloadService";
private NotificationManager nManager;
private Notification notification;
private Map<Integer, Integer> downloading;
private String pathText;
private String path;
private boolean flag = false;//标记是否退出应用
//private Map<Integer, FileDownloader> fileDownloaders;
private ProgressBar progressBar;
@Override
public IBinder onBind(Intent intent) {
return null;
} @Override
public void onCreate() {
nManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
//fileDownloaders = new HashMap<Integer, FileDownloader>();
downloading = new HashMap<Integer, Integer>();
super.onCreate();
} @Override
public void onStart(Intent intent, int startId) {
Log.e(TAG, "-----------onStart----in------"); String apk = intent.getStringExtra("apk");
int appId = intent.getIntExtra("appId", -1);
downloading.put(appId, appId);// 将正在下载的应用id放入map
Log.e(TAG, "appID=" + appId);
pathText = InnoMarketDataModelAdapter.DOWNLOAD_URI;
notification = new Notification(R.drawable.icon, "开始下载了...", System.currentTimeMillis());
// 通过RemoteViews 设置notification中View 的属性
System.out.println("getApplication()-----" + getApplication());
notification.contentView = new RemoteViews(getApplication().getPackageName(), R.layout.notification);
notification.contentView.setProgressBar(R.id.notification_progress, 100, 0, false);
notification.contentView.setTextViewText(R.id.tv, "进度" + 0 + "%");
path = pathText + apk;
Log.e(TAG, "download_path="+path);
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
Intent mIntent = new Intent(DownloadService.this, DetailViewActivity.class);
mIntent.setAction(Constant.DOWNLOAD_ACTION);
mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mIntent.putExtra("appId", appId);
PendingIntent contentIntent = PendingIntent.getActivity(DownloadService.this, 0, mIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
notification.setLatestEventInfo(this, "正在下载", "下载详情,请点击查看", contentIntent);
nManager.notify(appId, notification);
File saveDir = new File(Constant.DOWNLOAD_APKS_DIR);
download(path, saveDir, appId);
}
super.onStart(intent, startId);
} /**
* 下载文件
*
* @param path
* 下载路径
* @param saveDir
* 文件保存目录
*/
// 对于Android的UI控件,只能由主线程负责显示界面的更新,其他线程不能直接更新UI控件的显示
public void download(final String path, final File saveDir, final int appId) {
new Thread(new Runnable() {
public void run() {
FileDownloader downer = null;
try {//捕捉初始化FileDownloader时抛出的异常
downer = new FileDownloader(DownloadService.this, path, saveDir, 3);
} catch (Exception e) {
nManager.cancel(appId);// 取消下载通知
downloading.remove(appId);
Toast.makeText(DownloadService.this, "服务器响应错误", Toast.LENGTH_SHORT).show();
return;
}
final int filesize = downer.getFileSize();
try {
downer.download(new DownloadProgressListener() {
public void onDownloadSize(int size) {
Message msg = new Message();
msg.what = 1;
Bundle bundle = msg.getData();
bundle.putInt("size", size);
bundle.putInt("appId", appId);
bundle.putInt("filesize", filesize);
handler.sendMessage(msg);// 发送消息进行notification中进度条的更新
// //发送广播,用于DetailViewActivity界面进度条的更新
// Intent myintent = new Intent();
// myintent.setAction(Constant.DOWNLOAD_ACTION)
// .putExtra("size", size)
// .putExtra("appId", appId)
// .putExtra("filesize", filesize);
// sendBroadcast(myintent);
InnoMarketApplication.addDownload(appId, size, filesize);
}
});
} catch (Exception e) {
Message msg = new Message();
msg.what = -1;
msg.getData().putString("error", "下载失败");
handler.sendMessage(msg);
}
}
}).start();
} private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (!Thread.currentThread().isInterrupted()) {
int appId = msg.getData().getInt("appId");
int filesize = msg.getData().getInt("filesize");
if (flag) {//退出应用程序,停止notification的更新操作
return;
}
switch (msg.what) {
case 1:
int size = msg.getData().getInt("size");// 获取当前文件下载的数量
if (filesize == size) {
Toast.makeText(DownloadService.this, "文件下载完成", 1).show();
nManager.cancel(appId);
InnoMarketApplication.removeDownload(appId);//下载完成后从缓存中去除下载信息信息
String name = path.substring(path.toString().lastIndexOf("/") + 1);
Log.e(TAG, "name=" + name+";path=" + path); notification.tickerText = "下载完毕,请点击安装";
notification.flags = Notification.FLAG_AUTO_CANCEL; Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse(Constant.DOWNLOAD_URI_PRE+ name);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.setDataAndType(uri, "application/vnd.android.package-archive"); PendingIntent pendingIntent = PendingIntent.getActivity(DownloadService.this, appId, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
notification.setLatestEventInfo(DownloadService.this, "安装通知", "下载完毕,请点击安装。", pendingIntent);
nManager.notify(appId, notification);
downloading.remove(appId);// 下载完毕从正在下载的map中除去
} else {
notification.contentView = new RemoteViews(getApplication().getPackageName(),
R.layout.notification);
int result_ = (int) (((float) size / (float) filesize) * 100);
notification.contentView.setProgressBar(R.id.notification_progress, 100, result_, false);
notification.contentView.setTextViewText(R.id.tv, "进度" + result_ + "%");
if(progressBar!=null && (Integer)progressBar.getTag(R.id.download_progress)==appId){
progressBar.setMax(filesize);
progressBar.setProgress(size);
}
Intent intent = new Intent(DownloadService.this, DetailViewActivity.class);
intent.setAction(Constant.DOWNLOAD_ACTION)//设置下载标记,用于区分notification点击事件
.putExtra("appId", appId)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
notification.contentIntent = PendingIntent.getActivity(DownloadService.this, appId, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
nManager.notify(appId, notification);
}
break; case -1:
String error = msg.getData().getString("error");
Toast.makeText(DownloadService.this, error, 1).show();
break;
}
}
super.handleMessage(msg);
}
};
@Override
public void onDestroy() {
Log.e(TAG, "--------onDestroy-------");
flag = true;//停止service前将退出标志设为true,用于停止notification的更新,从而将正在下载的通知清除
Collection<Integer> collection = downloading.values();
Iterator<Integer> it = collection.iterator();
for(;it.hasNext();){
nManager.cancel(it.next());
}
android.os.Process.killProcess(android.os.Process.myPid());
super.onDestroy();
}}下载器下载部分关键代码: boolean notFinish = true;//下载未完成
while (notFinish) {// 循环判断是否下载完毕
Thread.sleep(1000);
notFinish = false;//假定下载完成
for (int i = 0; i < this.threads.length; i++){
if (this.threads[i] != null && !this.threads[i].isFinish()) {
notFinish = true;//下载没有完成
if(this.threads[i].getDownLength() == -1){//如果下载失败,再重新下载
RandomAccessFile randOut = new RandomAccessFile(this.saveFile, "rw");
randOut.seek(this.data.get(i+1));
this.threads[i] = new DownloadThread(this, this.url, randOut, this.block, this.data.get(i+1), i+1);
this.threads[i].setPriority(7);
this.threads[i].start();
}
}
}
if(listener!=null) listener.onDownloadSize(this.downloadSize);
解决方案 »
- android openGL
- button的监听方法selector与setOnTouchListener的关系
- 一个简单的handler的进程停止问题,望高手帮帮小弟···
- android手机的实体音量键的长按功能源码是在哪里实现的啊?
- andorid 布局时插入ListView
- 自己用CXF+spring+hibernate写了个简单的webservice,用android虚拟机连接老是报错
- Android源码编译
- android图片太大无法分享
- 照片内存优化的办法
- No JNI_OnLoad found 求大神解答!!!!
- android真机测试问题
- 当服务随着Activity创建而创建销毁而销毁的时候,有什么用?
import java.io.InputStream;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class AsyncTaskActivity extends Activity {
/**执行Timer进度**/
public final static int LOAD_PROGRESS = 0;
/**关闭Timer进度**/
public final static int CLOSE_PROGRESS = 1;
/** 开始StartAsync按钮 **/
Button mButton0 = null;
/** 显示内容 **/
TextView mTextView = null;
Context mContext = null;
/**Timer对象**/
Timer mTimer = null;
/**TimerTask对象**/
TimerTask mTimerTask = null;
/**记录TimerID**/
int mTimerID = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.async);
mContext = this;
/** 拿到button 与 TextView 对象 **/
mButton0 = (Button) findViewById(R.id.button0);
mTextView = (TextView) findViewById(R.id.textView0);
//开始
mButton0.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
//开始执行StartAsync
StartAsync();
}
});
super.onCreate(savedInstanceState);
}
public void StartAsync() {
new AsyncTask<Object, Object, Object>() {
@Override
protected void onPreExecute() {
//首先执行这个方法,它在UI线程中 可以执行一些异步操作
mTextView.setText("开始加载进度");
super.onPreExecute();
}
@Override
protected Object doInBackground(Object... arg0) {
//异步后台执行 ,执行完毕可以返回出去一个结果object对象
//得到开始加载的时间
Long startTime = System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
// 这里循环加载图片100遍
ReadBitMap(mContext, R.drawable.bg);
//执行这个方法会异步调用onProgressUpdate方法,可以用来更新UI
publishProgress(i);
}
//得到结束加载的时间
Long endTime = System.currentTimeMillis();
//将读取时间返回
return endTime - startTime;
}
@Override
protected void onPostExecute(Object result) {
//doInBackground之行结束以后在这里可以接收到返回的结果对象
mTextView.setText("读取100张图片一共耗时" + result+ "毫秒");
super.onPostExecute(result);
}
@Override
protected void onProgressUpdate(Object... values) {
//时时拿到当前的进度更新UI
mTextView.setText("当前加载进度" + values[0]);
super.onProgressUpdate(values);
}
}.execute();//可以理解为执行 这个AsyncTask
}
/**
* 读取本地资源的图片
*
* @param context
* @param resId
* @return
*/
public Bitmap ReadBitMap(Context context, int resId) {
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPreferredConfig = Bitmap.Config.RGB_565;
opt.inPurgeable = true;
opt.inInputShareable = true;
// 获取资源图片
InputStream is = context.getResources().openRawResource(resId);
return BitmapFactory.decodeStream(is, null, opt);
}
}
activity和service之间,你用什么通信的?