activity 与 service 之间的通信
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