断点续传 app版本更新

来源:互联网 发布:gitv电视直播软件好吗 编辑:程序博客网 时间:2024/06/11 19:49

版本不同,开启服务,根据判断条件,如果未下载 或未下载完,开启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;
 
//    private String url = "http://123.129.203.149/imtt.dd.qq.com/16891/237CB1256C5982BA4697817845F992A4.apk?mkey=58f4936ac26ff6c9&f=a601&c=0&fsname=com.tianci.xueshengzhuan_9.03_903.apk&csr=1bbd&p=.apk";
    private String url ="http://27.221.28.172/imtt.dd.qq.com/16891/F1B90DFC2A91F2E7F54D3F2919C7383B.apk?mkey=58f5f2bbc26ff6c9&f=b208&c=0&fsname=com.mfxsjd_1.3.01.10493_1010301.apk&csr=1bbd&p=.apk";
 
    @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;
 
    private final static String MYURL = "http://123.129.203.149/imtt.dd.qq.com/16891/237CB1256C5982BA4697817845F992A4.apk?mkey=58f4936ac26ff6c9&f=a601&c=0&fsname=com.tianci.xueshengzhuan_9.03_903.apk&csr=1bbd&p=.apk";
 
 
    // 通过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