需要实现的效果:     多任务下载时,当点击通知中的某个进度条时,出来该应用的下载节界面,下载界面的进度条和单击的进度条进度保持一致
要求:不能用广播  /   最好是设计一个回调方法来实现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);

解决方案 »

  1.   

    使用多线程AsyncTask  下面带了一个AsyncTask  使用的一个小例子
        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);  
            }  
        }  
      

  2.   

    LZ 这个问题搞定了吗?
    activity和service之间,你用什么通信的?
      

  3.   

    service通过广播来通知activity更新进度
      

  4.   

    哥们,能给个demo吗?我邮箱 [email protected]