Android进阶之路 - 批量下载、缓存图片、视频

之前已经记录过,批量下载图片和缓存本地的方式,此篇主要记录批量下载图片、视频,同时缓存在本地的功能实现

关联篇

在此之前,我记录过一篇 主讲 - 批量下载、缓存图片,此篇可以作为上篇的进阶扩展,优化了调用场景和使用方式~

关于实现批量下载、缓存功能,主要使用了以下几方面的知识

基础配置

加入以下权限

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

build.gradle(app)

	//okHttpUtils网络框架
    implementation 'com.squareup.okhttp3:okhttp:3.11.0'
    implementation 'com.squareup.okio:okio:1.15.0'
    implementation 'com.squareup.okhttp3:logging-interceptor:3.11.0'
 	//glide图片框架
    implementation 'com.github.bumptech.glide:glide:4.3.1'
    annotationProcessor('com.github.bumptech.glide:compiler:4.3.1')
    implementation 'com.github.bumptech.glide:okhttp3-integration:4.3.1'
    //greenDao数据库框架
    implementation 'org.greenrobot:greendao:3.3.0'
    implementation 'org.greenrobot:greendao-generator:3.3.0'

BannerInfo

在下方code中用到的bean,用于区分下载类型、地址、存储状态

package com.nk.machine.shop.model;

import java.io.Serializable;

/**
 * @author MrLiu
 * @date 2021/3/12
 * desc
 */
public class BannerInfo implements Serializable {
    /**
     * 图片地址
     */
    private String picUrl;

    /**
     * type分类 1:图片 2:视屏
     */
    private int type;

    /**
     * 无效的本地资源的状态
     * 0:非本地资源
     * 1:有效的本地资源
     */
    private int validLocalState = 0;

    public int getValidLocalState() {
        return validLocalState;
    }

    public void setValidLocalState(int validLocalState) {
        this.validLocalState = validLocalState;
    }
    
    public String getPicUrl() {
        return picUrl;
    }

    public void setPicUrl(String picUrl) {
        this.picUrl = picUrl;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }
}
图片下载
    /**
     * 优化版 - 单图下载
     */
    public void downAloneImg(int source, BannerInfo info) {
        LogTool.e("提示:开始下载图片");
        String picUrl = info.getPicUrl();
        new Thread(() -> {
            File file = GlideTool.downImageFile(NkApplication.getAppContext(), picUrl);
            Bitmap bitmap = BitmapFactory.decodeFile(file.toString());
           /* 因为我针对不同场景保存图片的地方有所不同,所以做了渠道分配,常规使用的话直接存储固定地址即可
           if (source == 1) {
                saveAloneImg(info, bitmap, Constant.LocalPath.BANNER_PATH);
            } else if (source == 2) {
                saveAloneImg(info, bitmap, Constant.LocalPath.CERTIFICATE_PATH);
            } else {
                saveAloneImg(info, bitmap, Constant.LocalPath.DEFAULT_PATH);
            }*/
            
            saveAloneImg(info, bitmap, Environment.getExternalStorageDirectory().getPath() + "/default");
        }).start();
    }

    /**
     * 优化版 - 保存图片
     */
    public void saveAloneImg(BannerInfo info, Bitmap bitmap, String path) {
        File file = new File(path);
        if (!file.exists()) {
            file.mkdir();
        }
        try {
            String tmpImgPath = path + "/" + System.currentTimeMillis() + ".png";
            FileOutputStream fileOutputStream = new FileOutputStream(tmpImgPath);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
            fileOutputStream.close();

            int type = info.getType();
            String picUrl = info.getPicUrl();
            int interval = info.getInterval();
            LogTool.e("图片保存成功,tmpImgPath=" + tmpImgPath);
            DaoStrategy.getInstance(new LyPicture(1, interval, type, picUrl, tmpImgPath)).insert();
        } catch (Exception e) {
            LogTool.e(e.getMessage());
        }
    }
视频下载
    /**
     * 优化版 -  视频下载
     */
    public void downAloneVideo(int source, BannerInfo info) {
        String picUrl = info.getPicUrl();
        LogTool.e("提示:开始下载视频"+picUrl));
        //定义存储路径
        String path = "";
        //如果不需要分渠道做优化,则可固定一个路径
        /*if (source == 1) {
            path = Constant.LocalPath.BANNER_PATH;
        } else if (source == 2) {
            path = Constant.LocalPath.CERTIFICATE_PATH;
        } else {
            path = Constant.LocalPath.DEFAULT_PATH;
        }*/
        path = Environment.getExternalStorageDirectory().getPath() + "/default";
        //定义存储文件名
        String tmpFileName = System.currentTimeMillis() + ".mp4";
        //开始下载
        OkHttpUtils.get()
                .url(picUrl)
                .build()
                .execute(new FileCallBack(path, tmpFileName) {
                    @Override
                    public void onError(Call call, Exception e, int id) {
                        LogTool.e("视频下载错误:" + e.getMessage());
                        downAloneVideo(source, info);
                    }

                    @Override
                    public void onResponse(File response, int id) {
                        LogTool.e("视频下载成功"+response.getAbsolutePath());
                        //将数据保存到数据库中
                        DaoStrategy.getInstance(new LyPicture(1, interval, info.getType(), picUrl, response.getAbsolutePath())).insert();
                    }
                });
完整封装
public class DownLoadUtil{
 	/**
     * 下载视频、图片
     */
    public static synchronized void downVideoImg(List<BannerInfo> bannerList) {
        //检测本地数据库数据
        List<PictureEntity> localList = (List<PictureEntity>) DaoStrategy.getInstance(new LyPicture()).queryConditionList(1);
        for (int i = 0; i < bannerList.size(); i++) {
            BannerInfo info = bannerList.get(i);
            //检测本地数据库资源,查询是否存在已下载的资源,减少重复下载,提升效率(如不需要可删除)
            if (localList.size() >= 1) {
                for (int j = 0; j < localList.size(); j++) {
                    if (info.getPicUrl().equals(info.getPicUrl())) {
                        LogTool.e("提示:本地已有该资源");
                        return;
                    }
                }
            }
			//必有:主要判断是下载图片还是视频
            if (info.getType() == 2) {
                downAloneVideo(1, bannerList.get(i));
            } else {
                downAloneImg(1, bannerList.get(i));
            }
        }
    }

    /**
     * 优化版 - 单图下载
     */
    public void downAloneImg(int source, BannerInfo info) {
        LogTool.e("提示:开始下载图片");
        String picUrl = info.getPicUrl();
        new Thread(() -> {
            File file = GlideTool.downImageFile(NkApplication.getAppContext(), picUrl);
            Bitmap bitmap = BitmapFactory.decodeFile(file.toString());
            if (source == 1) {
                saveAloneImg(info, bitmap, Constant.LocalPath.BANNER_PATH);
            } else if (source == 2) {
                saveAloneImg(info, bitmap, Constant.LocalPath.CERTIFICATE_PATH);
            } else {
                saveAloneImg(info, bitmap, Constant.LocalPath.DEFAULT_PATH);
            }
        }).start();
    }

    /**
     * 优化版 - 保存图片
     */
    public void saveAloneImg(BannerInfo info, Bitmap bitmap, String path) {
        File file = new File(path);
        if (!file.exists()) {
            file.mkdir();
        }
        try {
            String tmpImgPath = path + "/" + System.currentTimeMillis() + ".png";
            FileOutputStream fileOutputStream = new FileOutputStream(tmpImgPath);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
            fileOutputStream.close();

            int type = info.getType();
            String picUrl = info.getPicUrl();
            int interval = info.getInterval();
            LogTool.e("图片保存成功,tmpImgPath=" + tmpImgPath);
            DaoStrategy.getInstance(new LyPicture(1, interval, type, picUrl, tmpImgPath)).insert();
        } catch (Exception e) {
            LogTool.e(e.getMessage());
        }
    }

    /**
     * 优化版 -  视频下载
     */
    public void downAloneVideo(int source, BannerInfo info) {
        LogTool.e("提示:开始下载视频"+info.getPicUrl());
        String picUrl = info.getPicUrl();
        int interval = info.getInterval();
        String path = "";
        if (source == 1) {
            path = Constant.LocalPath.BANNER_PATH;
        } else if (source == 2) {
            path = Constant.LocalPath.CERTIFICATE_PATH;
        } else {
            path = Constant.LocalPath.DEFAULT_PATH;
        }
        String tmpFileName = System.currentTimeMillis() + ".mp4";
        OkHttpUtils.get()
                .url(picUrl)
                .build()
                .execute(new FileCallBack(path, tmpFileName) {
                    @Override
                    public void onError(Call call, Exception e, int id) {
                        LogTool.e("视频下载错误:" + e.getMessage());
                        downAloneVideo(source, info);
                    }

                    @Override
                    public void onResponse(File response, int id) {
                        LogTool.e("视频下载成功"+response.getAbsolutePath());
                        DaoStrategy.getInstance(new LyPicture(1, interval, info.getType(), picUrl, response.getAbsolutePath())).insert();
                    }
                });
    }
使用方式

使用简单,无需关注内部实现,同时实现了单一原则,统一了下载出口

在需要下载视频、图片的地方直接调用以下代码即可

   //bannerList为需要下载的图片和视频
   DownLoadUtil.downVideoImg(bannerList);
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
感谢您的提问。要实现指南针功能,我们需要使用Android的Sensor(传感器)API。下面是一些基本步骤: 1. 获取SensorManager对象。您可以通过以下方式获取: ```java SensorManager sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); ``` 2. 获取方向传感器。我们需要使用Android设备上的方向传感器来获取设备的方向。您可以使用以下代码获取方向传感器: ```java Sensor orientationSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); ``` 请注意,`Sensor.TYPE_ORIENTATION`在Android API级别20中被弃用。您应该使用`Sensor.TYPE_ROTATION_VECTOR`代替。 3. 创建SensorEventListener。我们需要实现`SensorEventListener`接口来接收传感器数据。您可以使用以下代码来创建一个SensorEventListener: ```java private final SensorEventListener sensorEventListener = new SensorEventListener() { @Override public void onSensorChanged(SensorEvent event) { // 当传感器数据更新时调用此方法 // 在这里更新指南针方向 } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // 当传感器精度发生变化时调用此方法 } }; ``` 4. 注册SensorEventListener。您需要在Activity的生命周期方法(例如`onResume()`)中注册`SensorEventListener`,以便在传感器数据更新时接收通知。您可以使用以下代码进行注册: ```java sensorManager.registerListener(sensorEventListener, orientationSensor, SensorManager.SENSOR_DELAY_UI); ``` 请注意,`SENSOR_DELAY_UI`表示传感器数据应该以与UI线程更新相同的频率更新。您可以使用其他常量来指定更新频率。 5. 实现指南针方向。您需要使用传感器数据来计算设备的方向,并更新指南针方向。您可以使用以下代码来获取设备的方向: ```java float[] orientationValues = new float[3]; SensorManager.getOrientation(event.values, orientationValues); float azimuth = Math.toDegrees(orientationValues[0]); ``` 请注意,`azimuth`表示设备的方向,以度为单位。 6. 更新指南针方向。您需要在UI线程中更新指南针方向。您可以使用以下代码来更新指南针方向: ```java runOnUiThread(new Runnable() { @Override public void run() { compassView.setDirection(azimuth); } }); ``` 请注意,`compassView`是一个自定义视图,用于绘制指南针。 这些是实现指南针功能的基本步骤。您需要根据自己的需求进行调整和修改。祝您好运!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

远方那座山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值