Android service 后台更新

在主线程创建一个线程 判断是否更新

    

Runnable runnable = new Runnable() {
    @Override
    public void run() {
        //从资源文件获取服务器 地址
        String path = getResources().getString(R.string.serverurl);
        info = SmallTools.getUpdateInfo(path);
        int verCode = SmallTools.getVerCode();
        if(info.getVersionCode()>verCode) {
          
              //更新
              Message msg = new Message();
              msg.what = UPDATE_TRUE;
              mHandler.sendMessage(msg);
          
        }
    }
};
new Thread(runnable).start();
/**
 * 获取版本号
 *
 * @return
 */
public static int getVerCode() {
    int verCode = -1;
    try {
        verCode = SellerApplication.getOverAllContext().getPackageManager().getPackageInfo("包名", 0).versionCode;
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }
    return verCode;
}
/**
 * 获取更新对象
 * @param path 服务器xml地址
 * @return
 */
public static UpdateInfo getUpdateInfo(String path){
    try {
        URL url=new URL(path);
        //创建连接对象
        HttpURLConnection conn= (HttpURLConnection) url.openConnection();
        //设置超时时间
        conn.setConnectTimeout(5000);
        conn.setRequestMethod("GET");
        //如果连接成功,获取输入流
        if(conn.getResponseCode()==200){
            return getUpdateInfo(conn.getInputStream());
        }
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (XmlPullParserException e) {
        e.printStackTrace();
    }
    return null;
}

根据xml流 获取对象 (可根据自己情况设置对应数据)

public static UpdateInfo getUpdateInfo(InputStream is) throws XmlPullParserException, IOException {
    XmlPullParser parser= Xml.newPullParser();
    parser.setInput(is,"utf-8");
    int type=parser.getEventType();
    UpdateInfo info=new UpdateInfo();
    while (type!=XmlPullParser.END_DOCUMENT){
        switch (type){
            case XmlPullParser.START_TAG:
                if(parser.nextText().equals("version")){
                    info.setVersionCode(Integer.parseInt(parser.nextText()));
                }else if(parser.nextText().equals("url")){
                    info.setUrl(parser.nextText());
                }else if(parser.nextText().equals("message")){
                    info.setMessage(parser.nextText());
                }
                break;
        }
        type=parser.next();
    }
    return info;
}

 

更新消息实体类

public class UpdateInfo {
    private int versionCode; //版本号
    private String url;//apk下载地址
    private String message;//更新消息

    public int getVersionCode() {
        return versionCode;
    }

    public void setVersionCode(int versionCode) {
        this.versionCode = versionCode;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

如果当前版本号低于服务器版本号 就行更新 (弹窗提示)

Handler mHandler = new android.os.Handler() {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case UPDATE_TRUE:
                showUpdataDialog();
                break;
        }

        super.handleMessage(msg);
    }
};

 

/**
     * 展示弹窗
     */
    private void showUpdataDialog() {
        AlertDialog.Builder builer = new AlertDialog.Builder(this);
        builer.setTitle("版本升级");
    builer.setMessage(info.getMessage());
        //当点确定按钮时从服务器上下载 新的apk 然后安装
        builer.setPositiveButton("确定", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                //下载
                downApk();
            }
        });
        //当点取消按钮时进行登录
        builer.setNegativeButton("取消", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                // TODO Auto-generated method stub
                dialog.dismiss();
            }
        });
        AlertDialog dialog = builer.create();
        dialog.show();
    }

点击更新 启动后台服务下载apk

 

/**
 * 后台下载apk
 */
private void downApk() {

    Intent it = new Intent(MainActivity.this, DownloadService.class);
    startService(it);
    bindService(it, conn, Context.BIND_AUTO_CREATE);
}

 

ServiceConnection conn = new ServiceConnection() {

    @Override
    public void onServiceDisconnected(ComponentName name) {
        // TODO Auto-generated method stub
        isBinded = false;
    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        // TODO Auto-generated method stub
        binder = (DownloadService.DownloadBinder) service;
        System.out.println("服务启动!!!");
        Log.e("服务启动", "服务启动----------------------------");
        // 开始下载
        isBinded = true;
        binder.addCallback(callback);
        binder.start();

    }
};

回调方法

private DownloadService.ICallbackResult callback = new DownloadService.ICallbackResult() {

        @Override
        public void OnBackResult(Object result) {
            // TODO Auto-generated method stub
            if ("finish".equals(result)) {
                finish();
                return;
            }
            int i = (Integer) result;
//            mProgressBar.setProgress(i);
            // tv_progress.setText("当前进度 =>  "+i+"%");
            // tv_progress.postInvalidate();
//            mHandler.sendEmptyMessage(i);
        }

    };

 

//服务类

public class DownloadService extends Service {
   private static final int NOTIFY_ID = 0;
   private int progress;
   private NotificationManager mNotificationManager;
   private boolean canceled;
   // 返回的安装包url
   private String apkUrl = "http://softfile.3g.qq.com:8080/msoft/179/24659/43549/qq_hd_mini_1.4.apk";
   // private String apkUrl = MyApp.downloadApkUrl;
   /* 下载包安装路径 */
   private static final String savePath = "/sdcard/updateApkDemo/";

   private static final String saveFileName = savePath + "3GQQ_AppUpdate.apk";
   private ICallbackResult callback;
   private DownloadBinder binder;
   private SellerApplication app;
   private boolean serviceIsDestroy = false;

   private Context mContext = this;
   private Handler mHandler = new Handler() {

      @SuppressLint("NewApi")
      @Override
      public void handleMessage(Message msg) {
         // TODO Auto-generated method stub
         super.handleMessage(msg);
         switch (msg.what) {
            case 0:
               app.setDownload(false);
               // 下载完毕
               // 取消通知
               mNotificationManager.cancel(NOTIFY_ID);
               installApk();
               break;
            case 2:
               app.setDownload(false);
               // 这里是用户界面手动取消,所以会经过activity的onDestroy();方法
               // 取消通知
               mNotificationManager.cancel(NOTIFY_ID);
               break;
            case 1:
               int rate = msg.arg1;
               app.setDownload(true);
               if (rate < 100) {
                  RemoteViews contentview = mNotification.contentView;
                  contentview.setTextViewText(R.id.tv_progress, rate + "%");
                  contentview.setProgressBar(R.id.progressbar, 100, rate, false);
               } else {
                  System.out.println("下载完毕!!!!!!!!!!!");
                  // 下载完毕后变换通知形式
                  mNotification.flags = Notification.FLAG_AUTO_CANCEL;
                  mNotification.contentView = null;
                  Intent intent = new Intent(mContext, MainActivity.class);
                  // 告知已完成
                  intent.putExtra("completed", "yes");
                  // 更新参数,注意flags要使用FLAG_UPDATE_CURRENT
                  PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, intent,
                        PendingIntent.FLAG_UPDATE_CURRENT);
//                mNotification.setLatestEventInfo(mContext, "下载完成", "文件已下载完毕", contentIntent);
                  mNotification=new Notification.Builder(mContext).setContentTitle("下载完成")
                        .setContentText("文件已下载完毕").setContentIntent(contentIntent).build();
                  serviceIsDestroy = true;
                  stopSelf();// 停掉服务自身
               }
               mNotificationManager.notify(NOTIFY_ID, mNotification);
               break;
         }
      }
   };

   //
   // @Override
   // public int onStartCommand(Intent intent, int flags, int startId) {
   // // TODO Auto-generated method stub
   // return START_STICKY;
   // }

   @Override
   public IBinder onBind(Intent intent) {
      // TODO Auto-generated method stub
      System.out.println("是否执行了 onBind");
      return binder;
   }

   @Override
   public void onDestroy() {
      // TODO Auto-generated method stub
      super.onDestroy();
      System.out.println("downloadservice ondestroy");
      // 假如被销毁了,无论如何都默认取消了。
      app.setDownload(false);
   }

   @Override
   public boolean onUnbind(Intent intent) {
      // TODO Auto-generated method stub
      System.out.println("downloadservice onUnbind");
      return super.onUnbind(intent);
   }

   @Override
   public void onRebind(Intent intent) {
      // TODO Auto-generated method stub

      super.onRebind(intent);
      System.out.println("downloadservice onRebind");
   }

   @Override
   public void onCreate() {
      // TODO Auto-generated method stub
      super.onCreate();
      binder = new DownloadBinder();
      mNotificationManager = (NotificationManager) getSystemService(android.content.Context.NOTIFICATION_SERVICE);
      //setForeground(true);// 这个不确定是否有作用
      app = (SellerApplication) getApplication();
   }

   public class DownloadBinder extends Binder {
      public void start() {
         if (downLoadThread == null || !downLoadThread.isAlive()) {

            progress = 0;
            setUpNotification();
            new Thread() {
               public void run() {
                  // 下载
                  startDownload();
               };
            }.start();
         }
      }

      public void cancel() {
         canceled = true;
      }

      public int getProgress() {
         return progress;
      }

      public boolean isCanceled() {
         return canceled;
      }

      public boolean serviceIsDestroy() {
         return serviceIsDestroy;
      }

      public void cancelNotification() {
         mHandler.sendEmptyMessage(2);
      }

      public void addCallback(ICallbackResult callback) {
         DownloadService.this.callback = callback;
      }
   }

   private void startDownload() {
      // TODO Auto-generated method stub
      canceled = false;
      downloadApk();
   }

   //
   Notification mNotification;

   // 通知栏
   /**
    * 创建通知
    */
   private void setUpNotification() {
      int icon = R.drawable.ic_launcher;
      CharSequence tickerText = "开始下载";
      long when = System.currentTimeMillis();
      mNotification = new Notification(icon, tickerText, when);

      // 放置在"正在运行"栏目中
      mNotification.flags = Notification.FLAG_ONGOING_EVENT;

      RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.download_notification_layout);
      contentView.setTextViewText(R.id.name, "我的菜.apk 正在下载...");
      // 指定个性化视图
      mNotification.contentView = contentView;

      Intent intent = new Intent(this, MainActivity.class);
      // 下面两句是 在按home后,点击通知栏,返回之前activity 状态;
      // 有下面两句的话,假如service还在后台下载, 在点击程序图片重新进入程序时,直接到下载界面,相当于把程序MAIN 入口改了 - -
      // 是这么理解么。。。
      // intent.setAction(Intent.ACTION_MAIN);
      // intent.addCategory(Intent.CATEGORY_LAUNCHER);
      PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent,
            PendingIntent.FLAG_UPDATE_CURRENT);

      // 指定内容意图
      mNotification.contentIntent = contentIntent;
      mNotificationManager.notify(NOTIFY_ID, mNotification);
   }

   //
   /**
    * 下载apk
    *
    * @param url
    */
   private Thread downLoadThread;

   private void downloadApk() {
      downLoadThread = new Thread(mdownApkRunnable);
      downLoadThread.start();
   }

   /**
    * 安装apk
    */
   private void installApk() {
      File apkfile = new File(saveFileName);
      if (!apkfile.exists()) {
         return;
      }
      Intent i = new Intent(Intent.ACTION_VIEW);
      i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
      i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive");
      mContext.startActivity(i);
      callback.OnBackResult("finish");

   }

   private int lastRate = 0;
   private Runnable mdownApkRunnable = new Runnable() {
      @Override
      public void run() {
         try {
            URL url = new URL(apkUrl);

            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.connect();
            int length = conn.getContentLength();
            InputStream is = conn.getInputStream();

            File file = new File(savePath);
            if (!file.exists()) {
               file.mkdirs();
            }
            String apkFile = saveFileName;
            File ApkFile = new File(apkFile);
            FileOutputStream fos = new FileOutputStream(ApkFile);

            int count = 0;
            byte buf[] = new byte[1024];

            do {
               int numread = is.read(buf);
               count += numread;
               progress = (int) (((float) count / length) * 100);
               // 更新进度
               Message msg = mHandler.obtainMessage();
               msg.what = 1;
               msg.arg1 = progress;
               if (progress >= lastRate + 1) {
                  mHandler.sendMessage(msg);
                  lastRate = progress;
                  if (callback != null)
                     callback.OnBackResult(progress);
               }
               if (numread <= 0) {
                  // 下载完成通知安装
                  mHandler.sendEmptyMessage(0);
                  // 下载完了,cancelled也要设置
                  canceled = true;
                  break;
               }
               fos.write(buf, 0, numread);
            } while (!canceled);// 点击取消就停止下载.

            fos.close();
            is.close();
         } catch (MalformedURLException e) {
            e.printStackTrace();
         } catch (IOException e) {
            e.printStackTrace();
         }

      }
   };

   public interface ICallbackResult {
      public void OnBackResult(Object result);
   }

}

 

 

通知栏布局文件




    

        

            

            

                

                    

                    
                

                
            
        

    

 

转载于:https://my.oschina.net/u/1377520/blog/725968

你可能感兴趣的:(Android service 后台更新)