Android 文件断点下载和通知栏的提示及apk更新安装

第一步:创建一张表用来保存下载信息

public class DbHelper extends SQLiteOpenHelper {

    public static String TABLE = "file";//表名

    public DbHelper(Context context) {
        super(context, "download.db", null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table file(fileName varchar,url varchar,length integer,finished integer)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

}

第二步:DbHelper.class中来写公用方法

/**
 * 插入一条下载信息
 */
public void insertData(SQLiteDatabase db, FileInfo info) {
    ContentValues values = new ContentValues();
    values.put("fileName", info.getFileName());
    values.put("url", info.getUrl());
    values.put("length", info.getLength());
    values.put("finished", info.getFinished());
    db.insert(TABLE, null, values);
    db.close();
}

/**
 * 更新一条下载信息
 */
public void updateData(SQLiteDatabase db, FileInfo info) {
    ContentValues values = new ContentValues();
    values.put("fileName", info.getFileName());
    values.put("length", info.getLength());
    values.put("finished", info.getFinished());
    db.update(TABLE, values, "url = ?", new String[]{info.getUrl()});
    db.close();
}

/**
 * 是否已经插入这条数据
 */
public boolean isExist(SQLiteDatabase db, FileInfo info) {
    Cursor cursor = db.query(TABLE, null, "url = ?", new String[]{info.getUrl()}, null, null, null, null);
    boolean exist = cursor.moveToNext();
    cursor.close();
    db.close();
    return exist;
}

/**
 * 查询已经存在的一条信息
 */
public FileInfo queryData(SQLiteDatabase db, String url) {
    Cursor cursor = db.query(TABLE, null, "url = ?", new String[]{url}, null, null, null, null);
    FileInfo info = new FileInfo();
    if (cursor != null) {
        while (cursor.moveToNext()) {
            String fileName = cursor.getString(cursor.getColumnIndex("fileName"));
            int length = cursor.getInt(cursor.getColumnIndex("length"));
            int finished = cursor.getInt(cursor.getColumnIndex("finished"));
            info.setStop(false);
            info.setFileName(fileName);
            info.setUrl(url);
            info.setLength(length);
            info.setFinished(finished);
        }
        cursor.close();
        db.close();
    }
    return info;
}

第三步:创建FileInfo对象,一个下载任务实体类,set和get

private String fileName;//文件名
private String url;//下载地址
private int length;//文件大小
private int finished;//下载以已完成进度
private boolean isStop = false;//是否暂停下载
private boolean isDownLoading = false;//是否正在下载

第四步:创建DownLoaderManger来管理下载任务,包括添加下载任务、开始下载、暂停下载、重新下载

public class DownLoaderManger {

    public static String FILE_PATH = Environment.getExternalStorageDirectory() + "/cjy";
    private DbHelper helper;//数据库帮助类
    private SQLiteDatabase db;
    private OnProgressListener listener;//进度回调监听
    private Map<String, FileInfo> map = new HashMap<>();//保存正在下载的任务信息
    private static DownLoaderManger manger;

    private DownLoaderManger(DbHelper helper, OnProgressListener listener) {
        this.helper = helper;
        this.listener = listener;
        db = helper.getReadableDatabase();
    }

    /**
     * 单例模式
     *
     * @param helper   数据库帮助类
     * @param listener 下载进度回调接口
     * @return
     */
    public static synchronized DownLoaderManger getInstance(DbHelper helper, OnProgressListener listener) {
        if (manger == null) {
            synchronized (DownLoaderManger.class) {
                if (manger == null) {
                    manger = new DownLoaderManger(helper, listener);
                }
            }
        }
        return manger;
    }

    /**
     * 开始下载任务
     */
    public void start(String url) {
        db = helper.getReadableDatabase();
        FileInfo info = helper.queryData(db, url);
        map.put(url, info);
        //开始任务下载
        new DownLoadTask(map.get(url), helper, listener).start();
    }

    /**
     * 停止下载任务
     */
    public void stop(String url) {
        map.get(url).setStop(true);
    }

    /**
     * 重新下载任务
     */
    public void restart(String url) {
        stop(url);
        try {
            File file = new File(FILE_PATH, map.get(url).getFileName());
            if (file.exists()) {
                file.delete();
            }
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        db = helper.getWritableDatabase();
        helper.resetData(db, url);
        start(url);
    }

    /**
     * 获取当前任务状态
     */
    public boolean getCurrentState(String url) {
        return map.get(url).isDownLoading();
    }

    /**
     * 添加下载任务
     *
     * @param info 下载文件信息
     */
    public void addTask(FileInfo info) {
        //判断数据库是否已经存在这条下载信息
        if (!helper.isExist(db, info)) {
            db = helper.getWritableDatabase();
            helper.insertData(db, info);
            map.put(info.getUrl(), info);
        } else {
            //从数据库获取最新的下载信息
            db = helper.getReadableDatabase();
            FileInfo o = helper.queryData(db, info.getUrl());
            if (!map.containsKey(info.getUrl())) {
                map.put(info.getUrl(), o);
            }
        }
    }
}

第五步:OnProgressListenter接口

public interface OnProgressListener {

    void updateProgress(int max, int progress, String path);

}

第六步:重点---下载线程

/**
 * 下载文件线程
 * 从服务器获取需要下载的文件大小
 */
public class DownLoadTask extends Thread {
    private FileInfo info;
    private SQLiteDatabase db;
    private DbHelper helper;//数据库帮助类
    private int finished = 0;//当前已下载完成的进度
    private OnProgressListener listener;//进度回调监听

    public DownLoadTask(FileInfo info, DbHelper helper, OnProgressListener listener) {
        this.info = info;
        this.helper = helper;
        this.db = helper.getReadableDatabase();
        this.listener = listener;
        info.setDownLoading(true);
    }

    @Override
    public void run() {
        getLength();
        HttpURLConnection connection = null;
        RandomAccessFile rwd = null;
        try {
            URL url = new URL(info.getUrl());
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(3000);
            //从上次下载完成的地方下载
            int start = info.getFinished();
            //设置下载位置(从服务器上取要下载文件的某一段)
            connection.setRequestProperty("Range", "bytes=" + start + "-" + info.getLength());//设置下载范围
            //设置文件写入位置
            File file = new File(DownLoaderManger.FILE_PATH, info.getFileName());
            rwd = new RandomAccessFile(file, "rwd");
            //从文件的某一位置开始写入
            rwd.seek(start);
            finished += info.getFinished();
            if (connection.getResponseCode() == 206) {//文件部分下载,返回码为206
                InputStream is = connection.getInputStream();
                byte[] buffer = new byte[1024 * 4];
                int len;
                while ((len = is.read(buffer)) != -1) {
                    //写入文件
                    rwd.write(buffer, 0, len);
                    finished += len;
                    info.setFinished(finished);
                    //更新界面显示
                    Message msg = new Message();
                    msg.what = 0x123;
                    msg.arg1 = info.getLength();
                    msg.arg2 = info.getFinished();
                    handler.sendMessage(msg);
                    //停止下载
                    if (info.isStop()) {
                        info.setDownLoading(false);
                        //保存此次下载的进度
                        helper.updateData(db, info);
                        db.close();
                        return;
                    }
                }
                //下载完成
                info.setDownLoading(false);
                helper.updateData(db, info);
                db.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
            try {
                if (rwd != null) {
                    rwd.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 首先开启一个线程去获取要下载文件的大小(长度)
     */
    private void getLength() {
        HttpURLConnection connection = null;
        try {
            //连接网络
            URL url = new URL(info.getUrl());
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(3000);
            int length = -1;
            if (connection.getResponseCode() == 200) {//网络连接成功
                //获得文件长度
                length = connection.getContentLength();
            }
            if (length <= 0) {
                //连接失败
                return;
            }
            //创建文件保存路径
            File dir = new File(DownLoaderManger.FILE_PATH);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            info.setLength(length);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //释放资源
            try {
                if (connection != null) {
                    connection.disconnect();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 更新进度
     */
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 0x123:
                    if (listener != null) {
                        listener.updateProgress(msg.arg1, msg.arg2,DownLoaderManger.FILE_PATH);
                    }
                    break;
            }
        }
    };
}

第七步:使用,通知栏的提示及apk更新安装

public class MainActivity extends AppCompatActivity implements OnProgressListener {

    private NotificationManager notificationManager;

    private NotificationCompat.Builder builder;

    private NumberProgressBar pb;//进度条
    private DownLoaderManger downLoader = null;
    private FileInfo info;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        pb = (NumberProgressBar) findViewById(R.id.pb);
        final Button start = (Button) findViewById(R.id.start);//开始下载
        final Button restart = (Button) findViewById(R.id.restart);//重新下载
        final DbHelper helper = new DbHelper(this);
        downLoader = DownLoaderManger.getInstance(helper, this);
        info = new FileInfo("chuanglifeng.apk", "http://116.62.162.56:80/pjriver/chuanglifeng/app-release.apk");
        downLoader.addTask(info);
        start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (downLoader.getCurrentState(info.getUrl())) {
                    initNofication("暂停下载","创利丰");
                    downLoader.stop(info.getUrl());
                    start.setText("开始下载");
                } else {
                    initNofication("开始下载","创利丰");
                    downLoader.start(info.getUrl());
                    start.setText("暂停下载");
                }
            }
        });
        restart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                initNofication("重新下载","创利丰");
                downLoader.restart(info.getUrl());
                start.setText("暂停下载");
            }
        });
    }

    @Override
    public void updateProgress(final int max, final int progress, String path) {
        pb.setMax(max);
        pb.setProgress(progress);
        int percent = (int) (div(progress,max,2)*100);

        builder.setProgress(max,progress,false);

        notificationManager.notify(0x3,builder.build());
        //下载进度提示
        builder.setContentText("下载"+percent+"%");
        if(percent==100) {    //下载完成后点击安装
            Intent it = new Intent(Intent.ACTION_VIEW);
            it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            it.setDataAndType(Uri.fromFile(new File(path,info.getFileName())), "application/vnd.android.package-archive");
            builder.setContentText("点击安装")
                    .setContentInfo("下载完成")
                    .setDefaults(Notification.DEFAULT_SOUND)
                    .setOngoing(false);
            startActivity(it);
            notificationManager.notify(0x3, builder.build());
        }

    }

    private void initNofication(String cticker, String title) {

        notificationManager = (NotificationManager) getSystemService(Activity.NOTIFICATION_SERVICE);
        builder = new NotificationCompat.Builder(this);
        builder.setSmallIcon(R.mipmap.logo)
                .setTicker(cticker)
                .setContentInfo("下载中...")
                .setContentTitle(title)
                .setOngoing(true);//设置为不可清除模式
    }

    public static double div(double v1, double v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }
}

Dome地址:http://download.csdn.net/download/qq_39735504/10271919

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值