Android 文件存储-图片存储

简介: 因 Android1 1谷歌禁止使用requestLegacyExternalStorage ,故将存储方式分为两种方式来进行文件存储。 存储你的应用打算与其他应用共享的文件,包括媒体、文档和其他文件。在这里咱们将图片保存至图库(共享文件)。

 因 Android1 1谷歌禁止使用requestLegacyExternalStorage ,故将存储方式分为两种方式来进行文件存储。

       存储你的应用打算与其他应用共享的文件,包括媒体、文档和其他文件。在这里咱们将图片保存至图库(共享文件)。


需要存储权限


    private void saveBitmap() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            // 检查该权限是否已经获取
            int i = ContextCompat.checkSelfPermission(FileStorageActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
            // 权限是否已经 授权 GRANTED---授权  DINIED---拒绝
            if (i != PackageManager.PERMISSION_GRANTED) {
                // 如果没有授予该权限,就去提示用户请求
                startRequestPermission();
            } else {
                resourceBitmap();
            }
        } else {
            resourceBitmap();
        }
    }


保存数据


    private void resourceBitmap() {
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ceshi);
        boolean isSave = PictureStorageUtils.isSaveImage(this, bitmap, "sccgx");
        Log.e("File","isSave:"+isSave);
    }
/**
 * 功能描述:将图片文件保存至本地
 */  
public class PictureStorageUtils {
    public static boolean isSaveImage(Context context, Bitmap bm, String name) {
        boolean isSave;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            //大于等于android 10
            isSave = saveImageQ(context, bm, name);
        } else {
            isSave = saveImage(context, bm, name);
        }
        return isSave;
    }
    private static boolean saveImage(Context context, Bitmap outB, String name) {
        String imgName = name.isEmpty()?String.valueOf(System.currentTimeMillis()):name;
        //File.separator就是文件路径
        String fileName = Environment.getExternalStorageDirectory() + File.separator + "DCIM"
                + File.separator + "demo" + File.separator;
        try {
            File file = new File(fileName);
            if (!file.exists()) {
                file.mkdirs();
            }
            Log.e("File","saveAndGetImage:" + file);
            File filePath = new File(file + "/" + imgName + ".png");
            Log.e("File","filePath:" + filePath);
            FileOutputStream out = new FileOutputStream(filePath); //保存到本地,格式为JPEG
            if (outB.compress(Bitmap.CompressFormat.PNG, 100, out)) {
                out.flush();
                out.close();
            }
            Log.e("File","saveAndGetImage:END");
            //刷新图库
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {//高于22版本要手动授权
                // 检查该权限是否已经获取
                int i = ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE);
                // 权限是否已经 授权 GRANTED---授权  DINIED---拒绝
                if (i != PackageManager.PERMISSION_GRANTED) {
                    // 提示用户应该去应用设置界面手动开启权限
                } else {
                    context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(filePath)));
                }
            } else {
                context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(filePath)));
            }
            return true;
        } catch (FileNotFoundException e) {
            Log.e("File","FileNotFoundException e.toString: " + e.toString());
            e.printStackTrace();
            return false;
        } catch (IOException e) {
            Log.e("File","IOException e.toString: " + e.toString());
            e.printStackTrace();
            return false;
        }
    }
    //功能描述:Android10及以上保存图片到相册
    @RequiresApi(api = Build.VERSION_CODES.Q)
    private static boolean saveImageQ(Context context, Bitmap image, String name) {
        long mImageTime = System.currentTimeMillis();
        String mImageFileName = name.isEmpty()?String.valueOf(mImageTime):name;
        final ContentValues values = new ContentValues();
        values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM
                + File.separator + "demo"); //图库(DCIM)中显示的文件夹名。
        values.put(MediaStore.MediaColumns.DISPLAY_NAME, mImageFileName);
        values.put(MediaStore.MediaColumns.MIME_TYPE, "image/png");
        values.put(MediaStore.MediaColumns.DATE_ADDED, mImageTime / 1000);
        values.put(MediaStore.MediaColumns.DATE_MODIFIED, mImageTime / 1000);
        values.put(MediaStore.MediaColumns.DATE_EXPIRES, (mImageTime + DateUtils.DAY_IN_MILLIS) / 1000);
        values.put(MediaStore.MediaColumns.IS_PENDING, 1);
        Log.e("File",values.get(MediaStore.MediaColumns.RELATIVE_PATH).toString());
        ContentResolver resolver = context.getContentResolver();
        final Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
        try {
            //写下我们文件的数据
            try (OutputStream out = resolver.openOutputStream(uri)) {
                if (!image.compress(Bitmap.CompressFormat.PNG, 100, out)) {
                    throw new IOException("Failed to compress");
                }
            }
            //一切都很顺利
            values.clear();
            values.put(MediaStore.MediaColumns.IS_PENDING, 0);
            values.putNull(MediaStore.MediaColumns.DATE_EXPIRES);
            resolver.update(uri, values, null, null);
            return true;
        } catch (IOException e) {
            Log.e("File",e.getMessage());
            return false;
        }
    }
}


测试机:Galaxy A8s


       图片保存路径:Galaxy A8s\Phone\DCIM\demo

image.png


测试机:Pixel XL API 31(AS模拟器)


       图片保存路径:/storage/emulated/0/DCIM/demo/sccgx.png


image.png



相关文章
|
2月前
|
ARouter Android开发
Android不同module布局文件重名被覆盖
Android不同module布局文件重名被覆盖
|
4月前
|
Java Android开发 C++
Android Studio JNI 使用模板:c/cpp源文件的集成编译,快速上手
本文提供了一个Android Studio中JNI使用的模板,包括创建C/C++源文件、编辑CMakeLists.txt、编写JNI接口代码、配置build.gradle以及编译生成.so库的详细步骤,以帮助开发者快速上手Android平台的JNI开发和编译过程。
325 1
|
6月前
|
存储 数据库 Android开发
安卓Jetpack Compose+Kotlin,支持从本地添加音频文件到播放列表,支持删除,使用ExoPlayer播放音乐
为了在UI界面添加用于添加和删除本地音乐文件的按钮,以及相关的播放功能,你需要实现以下几个步骤: 1. **集成用户选择本地音乐**:允许用户从设备中选择音乐文件。 2. **创建UI按钮**:在界面中创建添加和删除按钮。 3. **数据库功能**:使用Room数据库来存储音频文件信息。 4. **更新ViewModel**:处理添加、删除和播放音频文件的逻辑。 5. **UI实现**:在UI层支持添加、删除音乐以及播放功能。
|
3月前
|
存储 缓存 编解码
Android经典面试题之图片Bitmap怎么做优化
本文介绍了图片相关的内存优化方法,包括分辨率适配、图片压缩与缓存。文中详细讲解了如何根据不同分辨率放置图片资源,避免图片拉伸变形;并通过示例代码展示了使用`BitmapFactory.Options`进行图片压缩的具体步骤。此外,还介绍了Glide等第三方库如何利用LRU算法实现高效图片缓存。
72 20
Android经典面试题之图片Bitmap怎么做优化
|
2月前
|
ARouter Android开发
Android不同module布局文件重名被覆盖
Android不同module布局文件重名被覆盖
147 0
|
4月前
|
存储 安全 API
Android经典实战之存储方案对比:SharedPreferences vs MMKV vs DataStore
本文介绍了 Android 开发中常用的键值对存储方案,包括 SharedPreferences、MMKV 和 DataStore,并对比了它们在性能、并发处理、易用性和稳定性上的特点。通过实际代码示例,帮助开发者根据项目需求选择最适合的存储方案,提升应用性能和用户体验。
130 1
|
4月前
|
开发工具 git 索引
repo sync 更新源码 android-12.0.0_r34, fatal: 不能重置索引文件至版本 ‘v2.27^0‘。
本文描述了在更新AOSP 12源码时遇到的repo同步错误,并提供了通过手动git pull更新repo工具来解决这一问题的方法。
158 1
|
4月前
|
数据处理 开发工具 数据安全/隐私保护
Android平台RTMP推送|轻量级RTSP服务|GB28181接入之文字、png图片水印的精进之路
本文探讨了Android平台上推流模块中添加文字与PNG水印的技术演进。自2015年起,为了满足应急指挥及安防领域的需求,逐步发展出三代水印技术:第一代为静态文字与图像水印;第二代实现了动态更新水印内容的能力,例如实时位置与时间信息;至第三代,则优化了数据传输效率,直接使用Bitmap对象传递水印数据至JNI层,减少了内存拷贝次数。这些迭代不仅提升了用户体验和技术效率,也体现了开发者追求极致与不断创新的精神。
|
4月前
|
自然语言处理 定位技术 API
Android经典实战之如何获取图片的经纬度以及如何根据经纬度获取对应的地点名称
本文介绍如何在Android中从图片提取地理位置信息并转换为地址。首先利用`ExifInterface`获取图片内的经纬度,然后通过`Geocoder`将经纬度转为地址。注意操作需在子线程进行且考虑多语言支持。
267 4
|
4月前
|
存储 监控 数据库
Android经典实战之OkDownload的文件分段下载及合成原理
本文介绍了 OkDownload,一个高效的 Android 下载引擎,支持多线程下载、断点续传等功能。文章详细描述了文件分段下载及合成原理,包括任务创建、断点续传、并行下载等步骤,并展示了如何通过多种机制保证下载的稳定性和完整性。
134 0