使用远程service下载能够分摊应用的压力,实现模块化,减少程序的耦合性
首先是aidl文件,通过aidl来进行进程间交互
package com.server;
import com.server.DownCallBack;
对外提供的接口aidl
interface SupportFunction {
String getAppListUrl();
void regCallback(in DownCallBack callBack);
void unregCallback(in DownCallBack callBack);
void startDown(String url);
}
下面是回调进度的aidl
package com.server;
interface DownCallBack {
void progress(String key,float porg);
}
这个aidl有服务的调用端实现,来实现进度的传输
下面是service实现
package com.server;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import android.app.Service;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.SparseArray;
/**
* 提供服务的实现类
* @author Jack
*
*/
public class MyServer extends Service {
private RemoteCallbackList<DownCallBack> mCallback = new RemoteCallbackList<DownCallBack>();
private List<String> downs = new ArrayList<String>();
private ReentrantLock lock = new ReentrantLock();
private MyThreadPool pool = null;
private SparseArray<DownLoadThread> tasks = new SparseArray<DownLoadThread>();
private boolean isRunningTask = false;
private Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
String finshTask = (String) msg.obj;
tasks.put(downs.indexOf(finshTask), null);
tasks.size();
isRunningTask = false;
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(Uri.parse("file://"+msg.getData().getString("file")), "application/vnd.android.package-archive");
startActivity(intent);
executorTask();
}
};
@Override
public void onCreate() {
super.onCreate();
pool = MyThreadPool.getInstance();
}
class FunctionImpl extends SupportFunction.Stub{
@Override
public String getAppListUrl() throws RemoteException {
return "你的app下载列表";
}
@Override
public void startDown(String url) throws RemoteException {
if(!downs.contains(url)){
downs.add(url);
tasks.append(downs.indexOf(url), new DownLoadThread(url,mCallback,lock,handler));//添加任务
executorTask();
}
}
@Override
public void regCallback(DownCallBack callBack) throws RemoteException {
if(callBack!=null){
mCallback.register(callBack);
}
}
@Override
public void unregCallback(DownCallBack callBack) throws RemoteException {
if(callBack!=null){
mCallback.unregister(callBack);
}
}
}
private void executorTask(){
if(isRunningTask){
return;
}
for(int i = 0;i<tasks.size();i++){
DownLoadThread t = tasks.get(i);
if(t!=null){//当前有任务,执行当前任务并且中断当前循环
pool.exector(t);
isRunningTask = true;
break;
}
}
}
private FunctionImpl function = new FunctionImpl();
@Override
public IBinder onBind(Intent intent) {
System.out.println("bind server");
return function;
}
}
下面是提供下载的线程<pre name="code" class="java">package com.server;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.locks.ReentrantLock;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
public class DownLoadThread implements Runnable {
private String urlString;
private RemoteCallbackList<DownCallBack> mCallLists;
private ReentrantLock lock;
private Handler handler;
public DownLoadThread(String url,RemoteCallbackList<DownCallBack> mCallLists,ReentrantLock lock,Handler handler) {
this.urlString = url;
this.mCallLists = mCallLists;
this.lock = lock;
this.handler = handler;
}
@Override
public void run() {
try {
URL url = new URL(urlString);
URLConnection conn = url.openConnection();
String name = getFileName();
File file = new File("/mnt/sdcard/" + name);
int fileLength = conn.getContentLength();
System.out.println(file.toString());
conn.setConnectTimeout(6000);
InputStream is = conn.getInputStream();
FileOutputStream fos = new FileOutputStream(file);
byte[] buf = new byte[1024*8];
int len = 0;
int count = 0;
lock.lock();//当前只有一个线程能同步进度
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);
float progress = (float)(count+=len)/fileLength;
sendProgress(progress, fileLength);
if(progress==1){
System.out.println("完成,需要发送消息");
Message msg = handler.obtainMessage();
msg.getData().putString("file", file.getAbsolutePath());
msg.obj = urlString;
handler.sendMessage(msg);
}
}
fos.close();
is.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
lock.unlock();
}
}
public void sendProgress(float len,int fileLength){
int i = mCallLists.beginBroadcast();
// while(i >0){
// i--;
try {
mCallLists.getBroadcastItem(0).progress(urlString,len);
} catch (RemoteException e) {
e.printStackTrace();
}
// }
mCallLists.finishBroadcast();
}
public String getFileName() {
String temp = urlString.split("//")[1];
String[] names = temp.split("/");
return names[names.length - 1];
}
}
由线程池来执行任务
<pre name="code" class="java">package com.server;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class MyThreadPool {
private static MyThreadPool pool = new MyThreadPool();
private ExecutorService service;
private MyThreadPool(){
service =Executors.newFixedThreadPool(1);
}
public static MyThreadPool getInstance(){
return pool;
}
public void exector(Runnable task){
service.execute(task);
}
public void shutDownThread() throws InterruptedException{
service.awaitTermination(5, TimeUnit.SECONDS);
List<Runnable> tasks = service.shutdownNow();//执行任务后的剩下的未执行的任务
if(tasks.size()==0){
//当前没有执行中的任务
}
}
}
只提供了单任务的下载,并没有提供多任务同时下载,同步起来比较麻烦,有时间在完善