activity和service通信:通过binder
举个我实际项目中的例子:在service中下载更新应用
首先是下载更新apk的service:
public class UpdateVersionService extends Service { private final String tag = "young";
private Context context = this;
private BaseApplication application;
private DownloadBinder binder;
private String apkUrl;// apk下载地址
private String saveFileName;// 下载安装包路径
private Thread downLoadThread;// 下载apk线程
private int progress;// 进度条
private final int NOTIFY_ID = 0;
private NotificationManager notificationManager;
private Notification notification;// 消息通知
private Builder builder = null;
private boolean canceled;
private boolean serviceIsDestory = false;
private int lastRate = 0; private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case 0:
// Log.v(tag, "success---");下载完成并安装
application.setDownload(false);
notificationManager.cancel(NOTIFY_ID);
installApk();
break;
case 1:
int rate = msg.arg1;
// Log.v(tag, "rate---");刷新进度
application.setDownload(true);
if (rate < 100) {
RemoteViews remoteView = notification.contentView;
remoteView.setTextViewText(R.id.tv_progress, rate + "%");
remoteView.setProgressBar(R.id.progressbar, 100, rate,
false);
} else {
// Log.v(tag, "下载完成");
notification.flags = Notification.FLAG_AUTO_CANCEL;
Intent intent = new Intent(context, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(
context, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentTitle(getResources().getString(
R.string.download_finish_title));
builder.setContentText(getResources().getString(
R.string.download_finish_text));
notification.contentIntent = contentIntent;
serviceIsDestory = true;
stopSelf();
}
notificationManager.notify(NOTIFY_ID, notification);
break;
case 2:
// Log.v(tag, "cancel---");取消下载
application.setDownload(false);
notificationManager.cancel(NOTIFY_ID);
break;
case 3:
// Log.v(tag, "error---");出现异常
application.setDownload(true);
notificationManager.cancel(NOTIFY_ID);
Toast.makeText(context,
getResources().getString(R.string.download_alter),
Toast.LENGTH_SHORT).show();
stopSelf();
break;
} };
}; /**
* 安装APK
*/
private void installApk() {
File apkfile = new File(saveFileName);
if (!apkfile.exists()) {
ToastUtil.toasts(context,
getResources().getString(R.string.download_alter));
return;
}
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(Uri.parse("file://" + apkfile.toString()),
"application/vnd.android.package-archive");
startActivity(intent);
} @Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
// Log.v(tag, "onCreate");
application = (BaseApplication) getApplication();
this.binder = new DownloadBinder();
notificationManager = (NotificationManager) this
.getSystemService(android.content.Context.NOTIFICATION_SERVICE);
} @Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
// Log.v(tag, "onStartCommand");
apkUrl = intent.getStringExtra("apkUrl");
if (!StringUtil.isEmpty(apkUrl)) {
saveFileName = FileUtils.getAppPath(context, apkUrl).getPath();
}
return super.onStartCommand(intent, flags, startId); } @Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
//Log.v(tag, "onDestroy");
application.setDownload(false);
} @Override
public IBinder onBind(Intent intent) {
// Log.v(tag, "onBind");
return binder;
} @Override
public boolean onUnbind(Intent intent) {
// Log.v(tag, "onUnbind");
return super.onUnbind(intent);
} @Override
public void onRebind(Intent intent) {
// Log.v(tag, "onRebind");
super.onRebind(intent);
} /**
* 下载binder
*
* @author Administrator
*
*/
public class DownloadBinder extends Binder { public void start() {
if (downLoadThread == null || !downLoadThread.isAlive()) {
setNotification();
canceled = false;
startDownloadApk();
}
} public void cancel() {
canceled = true;
} public int getProgress() {
return progress;
} public boolean getCanceled() {
return canceled;
} public boolean isDestoryService() {
return serviceIsDestory;
} public void cancleNotification() {
handler.sendEmptyMessage(2);
}
} /**
* 下载apk
*/
private void startDownloadApk() {
downLoadThread = new Thread(downApkRunnable);
downLoadThread.start();
} private Runnable downApkRunnable = new Runnable() { @Override
public void run() {
try {
URL url = new URL(apkUrl);
// Log.v(tag, "apkUrl---" + apkUrl);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.connect();
int length = connection.getContentLength();
InputStream inputStream = connection.getInputStream();
String apkUrls = saveFileName;
// Log.v(tag, "apkUrls---" + apkUrls);
File apkFile = new File(apkUrls);
if(apkFile.exists()){
Log.v(tag, "true---" + apkFile.getAbsolutePath());
}
FileOutputStream outputStream = new FileOutputStream(apkFile);
int count = 0;
byte[] buffer = new byte[1024];
do {
int readNum = inputStream.read(buffer);
count += readNum;
progress = (int) (((float) count / length) * 100);
Message msg = new Message();
msg.what = 1;
msg.arg1 = progress;
if (progress > lastRate + 1) {
handler.sendMessage(msg);
lastRate = progress;
}
if (readNum <= 0) {
handler.sendEmptyMessage(0);
canceled = true;
break;
}
outputStream.write(buffer, 0, readNum);
} while (!canceled);
if (outputStream != null) {
outputStream.close();
}
if (inputStream != null) {
inputStream.close();
}
} catch (Exception e) {
Log.d("young","Exception...."+ e.toString()) ;
handler.sendEmptyMessage(3);
} }
}; /**
* 设置下载通知栏
*/
private void setNotification() {
// String tickerText = getResources().getString(R.string.download_start);
String tickerText = "开始下载";
long when = System.currentTimeMillis();
builder = new Builder(this);
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setWhen(when);
builder.setTicker(tickerText);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
notification = builder.build();
}
notification.flags = Notification.FLAG_ONGOING_EVENT;
RemoteViews contentView = new RemoteViews(getPackageName(),
R.layout.download_notification_layout);
contentView.setTextViewText(R.id.tv_name,
getResources().getString(R.string.download_title));
notification.contentView = contentView;
Intent intent = new Intent(this, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
notification.contentIntent = contentIntent;
notificationManager.notify(NOTIFY_ID, notification);
} }
调用如上service:
声明binder对象:
private UpdateVersionService.DownloadBinder binder;
通过intent绑定service:
Intent intent =new Intent(mContext, UpdateVersionService.class);
intent.putExtra("apkUrl",apk_url);
mContext.startService(intent);
mContext.bindService(intent,conn, Context.BIND_AUTO_CREATE);
ServiceConnection conn = new ServiceConnection() { @Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
} @Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
binder = (UpdateVersionService.DownloadBinder) service;
// 开始下载
binder.start();
}
};
如上在onserviceConnected中调用binder.start(),也就是调用DownloadBinder的start()方法;
start方法里面调用startDownloadApk()开启下载应用的线程,在线程里面通过hander控制Notifition上面进度显示,下载完成调用安装apk程式。
注意在mainfest文件中注册service:
<service android:name="com.chexiu.service.UpdateVersionService" >
</service>
service与activity通信:通过广播
public class TestService extends Service {
/**
* 进度条的最大值
*/
public static final int MAX_PROGRESS = 100;
/**
* 进度条的进度值
*/
private int progress = 0; private Intent intent = new Intent("com.soyoungboy.communication.RECEIVER"); /**
* 模拟下载任务,每秒钟更新一次
*/
public void startDownLoad(){
new Thread(new Runnable() { @Override
public void run() {
while(progress < MAX_PROGRESS){
progress += 1;
//发送Action为com.example.communication.RECEIVER的广播
intent.putExtra("progress", progress);
sendBroadcast(intent); }
}
}).start();
} @Override
public int onStartCommand(Intent intent, int flags, int startId) {
startDownLoad();
return super.onStartCommand(intent, flags, startId);
} @Override
public IBinder onBind(Intent intent) {
return null;
} }
/**
* 广播接收器
* @author len
*
*/
public class MsgReceiver extends BroadcastReceiver { @Override
public void onReceive(Context context, Intent intent) {
//拿到进度,更新UI
int progress = intent.getIntExtra("progress", 0);
Toast.makeText(context,"progress = "+progress,Toast.LENGTH_LONG).show();
} }
mainfest文件:
<receiver android:name=".service.MsgReceiver">
<intent-filter>
<action android:name="com.soyoungboy.communication.RECEIVER"></action>
</intent-filter>
</receiver>
<service android:name=".service.TestService">
<intent-filter>
<action android:name="com.soyoungboy.communication.MSG_ACTION"/>
</intent-filter>
</service>
当然也可以使用EventBus或者RxJava