断点续传 app版本更新

版本不同,开启服务,根据判断条件,如果未下载 或未下载完,开启AsyncTast进行断点下载。

将基本数据保存在了SharedPreferences中

其中字段:

dlversion:版本号存储

dlstate:状态,1,下载中,还没下载完,2,已经下载完

Finished:保存下载的进度

isfirst:是否第一次安装,模拟的版本控制,实际应用中并不需要这个字段


经过测试,可以实现,文件断网或清理后台后,再次 下载能够断点下载


还有服务开启一个全局dialog,可是有的手机会禁止悬浮窗,所以下载完后不会弹出dialog,注意手动开启 下,还有实际开发中,不建议用此dialog,可以尝试用下窗口activity.


基本的逻辑思路和需要的资源文件都在下面




部分代码:

MainActivity 

package com.example.tianf.myapplication;
 
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
 
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
 
 
     private Button no_file, file_no_version, file_version;
 
     private String version;
 
 
     private SharedPreferences mSharedPreferences;
     private SharedPreferences.Editor mEditor;
 
 
     private boolean isFirst= true ;
 
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         initView();
         initListen();
 
         mSharedPreferences = getSharedPreferences( "DownloadInfo" ,
                 MODE_PRIVATE);
         mEditor = mSharedPreferences.edit();
         boolean isfirst = mSharedPreferences.getBoolean( "isfirst" true );
 
         if (isfirst){
             mEditor.putString( "dlversion" "1.0" );
             mEditor.putBoolean( "isfirst" , false );
         }
         mEditor.commit();
 
     }
 
     private void initView() {
         no_file = (Button) findViewById(R.id.no_file);
         file_no_version = (Button) findViewById(R.id.file_no_version);
         file_version = (Button) findViewById(R.id.file_version);
 
     }
 
     private void initListen() {
         no_file.setOnClickListener( this );
         file_no_version.setOnClickListener( this );
         file_version.setOnClickListener( this );
     }
 
     @Override
     public void onClick(View v) {
         //从服务器获取的版本号
 
 
         switch  (v.getId()){
             case  R.id.no_file:
 
                 break ;
             case  R.id.file_no_version:
                 version= "1.0" ;
 
                 Intent intent= new  Intent( this ,MyFirstService.class);
                 intent.putExtra( "version" ,version);
                 intent.putExtra( "url" ,url);
                 startService(intent);
 
                 break ;
             case  R.id.file_version:
                 version= "2.0" ;
 
                 Intent intent2= new  Intent( this ,MyFirstService.class);
                 intent2.putExtra( "version" ,version);
                 intent2.putExtra( "url" ,url);
                 startService(intent2);
                 break ;
         }
 
     }
}
MyFirstService 

package com.example.tianf.myapplication;
 
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.Toast;
 
import java.io.File;
import java.io.IOException;
 
import static android.R.attr.version;
import static com.example.tianf.myapplication.Constants.AppName;
 
/**
  * <pre>
  *    Author :  天府萧炎恋熏儿
  *    Time   :  
  *    Usage  :
  *    desc   :
  *    other  :
  * </pre>
  */
 
public class MyFirstService extends Service implements MyTast.DoBackListener {
     MyTast myTast;
     File apkFile;
     private String url =  "" ;
     private String myVersion= "" ;
     private SharedPreferences mSharedPreferences;
     private SharedPreferences.Editor mEditor;
     Handler mHandler= new  Handler();
     String filePath;
 
 
 
     // 通过startService方法启动服务时,该方法不会运行
     @Override
     public IBinder onBind(Intent intent) {
         // TODO Auto-generated method stub
         return  null ;
     }
 
     //当服务对象不存在时,调用此方法
     @Override
     public void onCreate() {
         // TODO Auto-generated method stub
         super .onCreate();
         Log.i( "====" "=========  onCreate" );
     }
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
         // TODO Auto-generated method stub
//        getDialog();
//        showClearDialog();
 
         myVersion=intent.getStringExtra( "version" );
         url=intent.getStringExtra( "url" );
 
 
 
 
         mSharedPreferences = getSharedPreferences( "DownloadInfo" ,
                 MODE_PRIVATE);
         mEditor = mSharedPreferences.edit();
 
 
             int   dlstate = mSharedPreferences.getInt( "dlstate" , 3);
             String dlversion=mSharedPreferences.getString( "dlversion" , "" );
             //首先判断正在下载的版本和服务器版本是否一致
 
             if (!TextUtils.isEmpty(dlversion)&&dlversion.equals(myVersion)){
                 switch  (dlstate){
 
                     //正在下载,但是还没下载完全
                     case  1:
                         //继续下载
                         getTast();
                         Log.i( "state" , "正在下载,但是还没下载完全" );
                         Toast.makeText( this "正在下载,但是还没下载完全" , Toast.LENGTH_SHORT).show();
                         break ;
 
                     //下载完成,拥有完整app包
                     case  2:
                         showClearDialog();
                         Log.i( "state" , "下载完成,拥有完整app包" );
                         Toast.makeText( this "安装版本已是" +myVersion+ ",不需要下载" , Toast.LENGTH_SHORT).show();
                         break ;
                     default :
                         getTast();
                         Log.i( "state" , "其它情况" );
                         Toast.makeText( this "其它情况" , Toast.LENGTH_SHORT).show();
                         break ;
 
                 }
             } else  {
                 //如果服务器版本和本地版本不一致,删除本地重新下载
                 //不同则删除之前的版本,重新下载
                 mEditor.remove( "Finished" );
                 mEditor.remove( "dlstate" );
                 mEditor.remove( "dlversion" );
                 mEditor.commit();
                 getTast();
                 Log.i( "state" "版本不同,重新下载" );
                 Toast.makeText( this "版本不同,重新下载" , Toast.LENGTH_SHORT).show();
             }
         return  START_NOT_STICKY;
     }
 
 
     @Override
     public void onDestroy() {
         // TODO Auto-generated method stub
         Log.i( "====" "=========   onDestroy" );
 
         super .onDestroy();
         stopSelf();
 
     }
     /**
      * @Title: installApk @Description: 安装APP @param @param
      * context @param @param file @return void 返回类型 @throws
      */
     public  void installApk(Context context, File file) {
         if  (!file.exists()) {
             return ;
         }
         Intent intent =  new  Intent();
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         intent.setAction(Intent.ACTION_VIEW);
         intent.setDataAndType(Uri.fromFile(file),  "application/vnd.android.package-archive" );
         context.startActivity(intent);
         stopSelf();
     }
 
 
     public String getApkDownloadPath() {
 
         File sdDir =  null ;
         boolean sdCardExist = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);  // 判断sd卡是否存在
         if  (sdCardExist) {
             sdDir = Environment.getExternalStorageDirectory(); // 获取跟目录
         else  {
             sdDir = Environment.getDownloadCacheDirectory(); //放到系统下载目录
         }
         return  sdDir.toString() + Constants.fileName;
 
     }
 
 
 
     Dialog mclearDialog;
 
     public void showClearDialog() {
 
         if  (mclearDialog ==  null ) {
              mclearDialog =  new  Dialog(getApplicationContext(), R.style.dialog);
 
              mclearDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
 
             View dialogLayout = LayoutInflater.from(getApplicationContext()).inflate(R.layout.dialog_new_version,  null );
             Button next_updata = (Button) dialogLayout.findViewById(R.id.next_updata);
             Button now_updata = (Button) dialogLayout.findViewById(R.id.now_updata);
             next_updata.setOnClickListener( new  View.OnClickListener() {
                 @Override
                 public void onClick(View v) {
                     if  (mclearDialog !=  null ) {
                         mclearDialog.dismiss();
                         mclearDialog =  null ;
                     }
                     stopSelf();
 
                 }
             });
             now_updata.setOnClickListener( new  View.OnClickListener() {
                 @Override
                 public void onClick(View v) {
                     if  (mclearDialog !=  null ) {
                         mclearDialog.dismiss();
                         mclearDialog =  null ;
                     }
                     installApk(getApplicationContext(),apkFile);
                 }
             });
             mclearDialog.setContentView(dialogLayout);
         }
         mclearDialog.setCanceledOnTouchOutside( true );
         mclearDialog.setCancelable( true );
         mclearDialog.show();
     }
 
     public void getTast(){
         myTast =  new  MyTast( this );
         myTast.setContext(getApplicationContext());
         myTast.execute(url,getApkDownloadPath(),Constants.AppName,myVersion);
     }
 
     @Override
     public void onBack() {
         String filePath = getApkDownloadPath() + Constants.AppName;
         apkFile =  new  File(filePath);
         showClearDialog();
     }
}
MyTast

package com.example.tianf.myapplication;
 
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.util.Log;
 
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
 
import static android.content.Context.MODE_PRIVATE;
 
/**
  * <pre>
  *    Author :  天府萧炎恋熏儿
  *    Time   : 
  *    Usage  :
  *    desc   :
  *    other  :
  * </pre>
  */
 
   /*
      * 异步处理
      */
 
class MyTast extends AsyncTask<String, Integer, String> {
 
 
     private Context context;
     private int length;
     private int start;
     private SharedPreferences mSharedPreferences;
     private SharedPreferences.Editor mEditor;
     public int mFinished;
 
 
     // 下载地址
     private String DIRSTR= "" ;
     private String FILENAME =  "" ;
     private String myVersion= "" ;
 
     public interface DoBackListener {
         void onBack();
     }
     DoBackListener listener;
 
     public MyTast(DoBackListener listener) {
         this .listener = listener;
     }
 
 
 
 
     @Override
     protected String doInBackground(String... params) {
         // 获取文件长度
         getFileLength(params[0]);
         DIRSTR=params[1];
         FILENAME=params[2];
         myVersion=params[3];
         // 执行下载任务
         return  download(params[0]);
     }
 
     @Override
     protected void onPostExecute(String result) {
         super .onPostExecute(result);
         Log.i( "mtag" , result);
         if ( "下载完成!" .equals(result)){
             listener.onBack();
         }
     }
 
     @Override
     protected void onProgressUpdate(Integer... values) {
         super .onProgressUpdate(values);
         // 更新进度条
         Log.i( "mtag" , "更新进度====" +values[0]);
     }
 
     /*
      * 获取文件长度
      */
     private void getFileLength(String string) {
         HttpURLConnection connection =  null ;
         try  {
             connection = (HttpURLConnection)  new  URL(string)
                     .openConnection();
             connection.setRequestMethod( "GET" );
             connection.setConnectTimeout(3000);
             if  (connection.getResponseCode() != 200) {
                 return ;
             }
             length = connection.getContentLength();
         catch  (Exception e) {
             e.printStackTrace();
         } finally {
             if  (connection !=  null ) {
                 connection.disconnect();
             }
         }
 
     }
 
     /*
      * 下载任务
      */
     private String download(String string) {
         HttpURLConnection connection =  null ;
         InputStream  in  null ;
         RandomAccessFile raf =  null ;
         try  {
             // 从SharedPreferences取出DownloadInfo里的下载进度值
             mSharedPreferences = context.getSharedPreferences( "DownloadInfo" ,
                     MODE_PRIVATE);
             mEditor = mSharedPreferences.edit();
             start = mSharedPreferences.getInt( "Finished" , 0);
             mEditor.putString( "dlversion" , myVersion);
             mEditor.putInt( "dlstate" , 1);
             mEditor.commit();
             mFinished = start;
             connection = (HttpURLConnection)  new  URL(string)
                     .openConnection();
             connection.setRequestMethod( "GET" );
             connection.setConnectTimeout(3000);
             Log.d( "length: " , length +  "" );
             connection.setRequestProperty( "Range" "bytes="  + start +  "-"
                     + length);
             if  (connection.getResponseCode() != 206) {
                 return  "206" ;
             }
             in  = connection.getInputStream();
             File file =  new  File(DIRSTR, FILENAME);
             raf =  new  RandomAccessFile(file,  "rwd" );
             Log.d( "start:" , start +  "" );
             raf.seek(start);
             byte[] buffer =  new  byte[1024 * 4];
             int len;
             while  ((len =  in .read(buffer)) != -1) {
                 raf.write(buffer, 0, len);
                 mFinished += len;
                 mEditor.putInt( "Finished" , mFinished);
                 mEditor.commit();
                 // 设置进度条的值
                 publishProgress(mFinished * 100 / length);
             }
             // 下载完成,从SharedPreferences移除下载进度
             mEditor.remove( "Finished" );
             mEditor.putInt( "dlstate" , 2);
             mEditor.commit();
             context.stopService( new  Intent(context,MyFirstService.class));
             return  "下载完成!" ;
         catch  (Exception e) {
             e.printStackTrace();
             mEditor.putInt( "Finished" , mFinished);
             mEditor.commit();
             context.stopService( new  Intent(context,MyFirstService.class));
             return  e.getMessage();
         } finally {
             try  {
                 if  (raf !=  null ) {
                     raf.close();
                 }
                 if  ( in  !=  null ) {
                     in .close();
                 }
                 if  (connection !=  null ) {
                     connection.disconnect();
                 }
             catch  (IOException e) {
                 e.printStackTrace();
                 return  e.getMessage();
             }
         }
     }
     public void setContext(Context context){
         this .context=context;
     }
 
 
 
}

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:background="@drawable/white_radius_bg_shape"
    android:orientation="vertical">

    <TextView
        android:id="@+id/exit"
        android:layout_width="250dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_margin="25dp"
        android:gravity="center"
        android:text="APP有更新了!"
        android:textColor="@color/black"
        android:textSize="15sp"
        android:drawableTop="@mipmap/ic_launcher"
        />

    <View
        android:layout_width="match_parent"
        android:layout_height="2px"
        android:background="@color/gray_line"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/next_updata"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@null"
            android:text="下次再说"
            android:padding="15dp"
            android:textColor="@color/black"
            android:textSize="15sp"/>

        <View
            android:layout_width="2px"
            android:layout_height="match_parent"
            android:background="@color/gray_line"/>

        <Button
            android:id="@+id/now_updata"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@null"
            android:text="立即更新"
            android:padding="15dp"
            android:textColor="@color/black"
            android:textSize="15sp"/>

    </LinearLayout>

</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#3F51B5</color>
    <color name="colorPrimaryDark">#5daee7</color>
    <color name="colorAccent">#5daee7</color>

    <!-- 米色 -->
    <color name="wheat">#F5DEB3</color>

    <color name="white">#FFFFFF</color>


    <color name="red">#f10303</color>


    <color name="black">#1e1d1d</color>

    <color name="round_outside_color">#FFFEFF</color>
    <color name="round_inside_color">#FFFEFF</color>

    <color name="theme_blue">#5daee7</color>
    <color name="line_color">#ebebeb</color>
    <color name="hui_1">#666</color>
    <color name="hui_1ban">#3f666666</color>
    <color name="hui2">#888</color>
    <color name="hui2_ban">#ee888888</color>
    <color name="hui3">#ebebeb</color>
    <color name="hui4">#d6d7dc</color>
    <color name="theme_background">@color/white</color>
    <color name="theme_background2">#F3F4F6</color>

    <color name="light_green">#82DA43</color>


    <color name="theme_title">#5daee7</color>


    <color name="side_bar_text">#4A4A4A</color>
    <color name="shadow_bg">#66000000</color>
    <color name="edit_bg">#EFEFF4</color>
    <color name="darker_gray">#9b9b9b</color>

    <color name="navpage">#FFE1E8EB</color>


    <!--灰色分割线-->
    <color name="gray_line">#cccccc</color>

    <!--bigpictrue-->
    <color name="bigpicture_background">#55000000</color>
    <color name="bigpicture_backgroundselcect">#2bc912</color>

    <!--动态圈名字颜色-->
    <color name="dy_namered">#f04f43</color>

    <!--我的页面名字颜色-->
    <color name="mine_name">#2a2a2a</color>

    <!--所有button里面的文字的字体颜色-->
    <color name="all_bt_textcolor">#ffffff</color>

</resources>

<style name="dialog" parent="@android:style/Theme.Dialog">
    <item name="android:windowFrame">@null</item>
    <item name="android:windowIsFloating">true</item>
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:background">@android:color/transparent</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:backgroundDimEnabled">true</item>
    <item name="android:backgroundDimAmount">0.6</item>
</style>



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值