热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【Android内存优化】Android原生API图片压缩代码示例(PNG格式压缩|JPEG格式压缩|WEBP格式压缩|动态权限申请|Android10存储策略)

文章目录一、图片质量压缩二、图片尺寸压缩三、Android10文件访问四、完整源码示例上一篇博客【Android内存优化】图片文件压缩(Android原生API提供的图片压缩功能能


文章目录

  • 一、 图片质量压缩
  • 二、 图片尺寸压缩
  • 三、 Android 10 文件访问
  • 四、 完整源码示例





上一篇博客 【Android 内存优化】图片文件压缩 ( Android 原生 API 提供的图片压缩功能能 | 图片质量压缩 | 图片尺寸压缩 ) 简要介绍了 图片文件压缩格式 , 以及 Android 提供的图片质量 , 尺寸压缩 API , 本博客中使用该 API 进行图片压缩 ;










一、 图片质量压缩





图片质量压缩步骤 :



① 创建输出流 : 创建一个文件输出流 , 也可是是网络输出流 ;

FileOutputStream fos = new FileOutputStream(path);

② 加载文件 : 从 Assets , 资源文件 , SD 卡 , 中 解码图片文件为内存中的 Bitmap 对象 ; 这里从资源文件中加载 ;

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resId);

③ 压缩图片 : 调用 Bitmap 对象的 compress 方法 , 压缩图片 ;

bitmap.compress(compressFormat, quality, fos);









二、 图片尺寸压缩





图片尺寸压缩流程 :



① 加载文件 : 从 Assets , 资源文件 , SD 卡 , 中解码图片文件为内存中的 Bitmap 对象 ; 这里从资源文件中加载 ;

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resId);

② 图片尺寸压缩 : 调用 Bitmap 对象的 createScaledBitmap 方法 , 将目标宽高作为参数传入 , 并使用双线性滤波器算法 , 该算法能大幅度提供压缩后的图片质量 , 并且开销较少 , 官方建议开启该算法 ;

bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);









三、 Android 10 文件访问





文件存储相关官方参考资料 :


  • Android 11 中的存储机制更新
  • Android storage use cases and best practices
  • 应用数据和文件


将图片压缩后 , 存储到 SD 卡中 , 这里 涉及到了在 Android 10 系统中动态申请权限 , 设置旧的存储访问策略 ( 该策略将在 Android 11 中无效 ) ;

这里简要介绍暂时性的解决方案 ;



1. AndroidManifest.xml 中配置 SD 卡权限 , 及旧存储策略 :



① SD 卡权限 : 配置 SD 卡读写权限 ;


<uses-permission android:name&#61;"android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name&#61;"android.permission.WRITE_EXTERNAL_STORAGE" />

② 旧存储策略 : 配置在 application 标签中 , 特别注意该策略将在 Android 11 中废弃 ;

android:requestLegacyExternalStorage&#61;"true"

③ 完整配置 :


<manifest xmlns:android&#61;"http://schemas.android.com/apk/res/android"package&#61;"kim.hsl.pc"><uses-permission android:name&#61;"android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name&#61;"android.permission.WRITE_EXTERNAL_STORAGE" /><applicationandroid:allowBackup&#61;"true"android:icon&#61;"&#64;mipmap/ic_launcher"android:label&#61;"&#64;string/app_name"android:roundIcon&#61;"&#64;mipmap/ic_launcher_round"android:supportsRtl&#61;"true"android:theme&#61;"&#64;style/AppTheme"android:requestLegacyExternalStorage&#61;"true"><activity android:name&#61;".MainActivity"><intent-filter><action android:name&#61;"android.intent.action.MAIN" /><category android:name&#61;"android.intent.category.LAUNCHER" />intent-filter>activity>application>manifest>




2 . 在 Activity 中动态申请权限 : 在 Activity 中调用 initPermissions(); 方法 , 即可动态申请 SD 卡访问权限 ;

/*** 需要获取的权限列表*/private String[] permissions &#61; new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE};/*** 动态申请权限的请求码*/private static final int PERMISSION_REQUEST_CODE &#61; 888;/*** 动态申请权限*/&#64;RequiresApi(api &#61; Build.VERSION_CODES.M)private void initPermissions() {if (isLacksPermission()) {//动态申请权限 , 第二参数是请求吗requestPermissions(permissions, PERMISSION_REQUEST_CODE);}}/*** 判断是否有 permissions 中的权限* &#64;return*/&#64;RequiresApi(api &#61; Build.VERSION_CODES.M)public boolean isLacksPermission() {for (String permission : permissions) {if(checkSelfPermission(permission) !&#61; PackageManager.PERMISSION_GRANTED){return true;}}return false;}


执行完上述三个步骤的操作


  • 配置权限
  • 设置旧存储策略
  • 动态申请权限

即可在 Android 10 中访问 SD 卡 , 如果在 Android 11 访问 , 查看章节开始的文档 ;










四、 完整源码示例





图片压缩源码示例 :

压缩质量 : 下图中的图片压缩都压缩成最低质量的图片 ;

package kim.hsl.pc;import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;import android.Manifest;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.widget.TextView;import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;public class MainActivity extends AppCompatActivity {static {System.loadLibrary("native-lib");}&#64;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);TextView tv &#61; findViewById(R.id.sample_text);tv.setText(stringFromJNI());// 初始化权限if (Build.VERSION.SDK_INT >&#61; Build.VERSION_CODES.M) {initPermissions();}// 将图片压缩成 JPEG 格式, 不缩放compressBitmap(R.drawable.blog, Bitmap.CompressFormat.JPEG, 0,Environment.getExternalStorageDirectory() &#43; "/blog_jpeg.jpeg?s=#34;,0, 0);// 将图片压缩成 WEBP 格式compressBitmap(R.drawable.blog, Bitmap.CompressFormat.WEBP, 0,Environment.getExternalStorageDirectory() &#43; "/blog_webp.webp",0, 0);// 将图片压缩成 PNG 格式compressBitmap(R.drawable.blog, Bitmap.CompressFormat.PNG, 0,Environment.getExternalStorageDirectory() &#43; "/blog_png.png",0, 0);// 将图片宽高各压缩一半compressBitmap(R.drawable.blog, Bitmap.CompressFormat.PNG, 0,Environment.getExternalStorageDirectory() &#43; "/blog_png_half.png",995, 510);}/*** 压缩图片, 并将压缩结果保存到指定文件* &#64;param resId 图片资源* &#64;param compressFormat 图片压缩格式* &#64;param quality 压缩质量* &#64;param path 文件保存路径*/public void compressBitmap(int resId, Bitmap.CompressFormat compressFormat,int quality, String path, int width, int height){// 从资源文件中加载一张图片Bitmap bitmap &#61; BitmapFactory.decodeResource(getResources(), resId);// 如果传入的尺寸参数大于 0, 那么压缩尺寸if(width > 0 && height > 0){bitmap &#61; Bitmap.createScaledBitmap(bitmap, width, height, true);}// 用于写出压缩后的图片到文件中FileOutputStream fos &#61; null;try {// 打开文件输出流fos &#61; new FileOutputStream(path);// 图片压缩操作// 如果图片格式是 PNG 格式, 会忽略 质量 参数bitmap.compress(compressFormat, quality, fos);} catch (FileNotFoundException e) {e.printStackTrace();Log.i("TAG", "文件输出流打开失败");}finally {if(fos !&#61; null){try {fos.close();} catch (IOException e) {e.printStackTrace();Log.i("TAG", "文件输出流关闭失败");}}}}public native String stringFromJNI();/*** 需要获取的权限列表*/private String[] permissions &#61; new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE};/*** 动态申请权限的请求码*/private static final int PERMISSION_REQUEST_CODE &#61; 888;/*** 动态申请权限*/&#64;RequiresApi(api &#61; Build.VERSION_CODES.M)private void initPermissions() {if (isLacksPermission()) {//动态申请权限 , 第二参数是请求吗requestPermissions(permissions, PERMISSION_REQUEST_CODE);}}/*** 判断是否有 permissions 中的权限* &#64;return*/&#64;RequiresApi(api &#61; Build.VERSION_CODES.M)public boolean isLacksPermission() {for (String permission : permissions) {if(checkSelfPermission(permission) !&#61; PackageManager.PERMISSION_GRANTED){return true;}}return false;}
}




压缩结果分析 :



① 压缩后的 PNG 格式 : 2.63 MB ;

② 压缩后的 JPEG 格式 : 119 KB ;

③ 压缩后的 WEBP 格式图片 : 102 KB ;

④ 尺寸压缩图片 : 219 KB ;

在这里插入图片描述

压缩格式中 PNG > JPEG > WEBP 格式 ;

PNG 图片不能压缩 , 这里显示的大小是原图大小 , 非常大 ;


推荐阅读
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • 开发笔记:Java是如何读取和写入浏览器Cookies的
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Java是如何读取和写入浏览器Cookies的相关的知识,希望对你有一定的参考价值。首先我 ... [详细]
  • 前端性能优化无损压缩webp格式的图片
    一、什么是webpWebP格式,谷歌开发的一种旨在加快图片加载速度的图片格式。图片压缩体积大约只有JPEG的23,并能节省大量的服务器宽带资源和数据空 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 在springmvc框架中,前台ajax调用方法,对图片批量下载,如何弹出提示保存位置选框?Controller方法 ... [详细]
  • 国庆节到了,安利一个Android的自动动态授权插件
    Android的老铁都知道申请权限时,除了要在AndroidManifest添加权限,还需要在activity中通过requestpermission对 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板
    本文介绍了在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板的方法和步骤,包括将ResourceDictionary添加到页面中以及在ResourceDictionary中实现模板的构建。通过本文的阅读,读者可以了解到在Xamarin XAML语言中构建控件模板的具体操作步骤和语法形式。 ... [详细]
  • 基于dlib的人脸68特征点提取(眨眼张嘴检测)python版本
    文章目录引言开发环境和库流程设计张嘴和闭眼的检测引言(1)利用Dlib官方训练好的模型“shape_predictor_68_face_landmarks.dat”进行68个点标定 ... [详细]
  • Python爬虫中使用正则表达式的方法和注意事项
    本文介绍了在Python爬虫中使用正则表达式的方法和注意事项。首先解释了爬虫的四个主要步骤,并强调了正则表达式在数据处理中的重要性。然后详细介绍了正则表达式的概念和用法,包括检索、替换和过滤文本的功能。同时提到了re模块是Python内置的用于处理正则表达式的模块,并给出了使用正则表达式时需要注意的特殊字符转义和原始字符串的用法。通过本文的学习,读者可以掌握在Python爬虫中使用正则表达式的技巧和方法。 ... [详细]
  • 树莓派语音控制的配置方法和步骤
    本文介绍了在树莓派上实现语音控制的配置方法和步骤。首先感谢博主Eoman的帮助,文章参考了他的内容。树莓派的配置需要通过sudo raspi-config进行,然后使用Eoman的控制方法,即安装wiringPi库并编写控制引脚的脚本。具体的安装步骤和脚本编写方法在文章中详细介绍。 ... [详细]
  • iOS超签签名服务器搭建及其优劣势
    本文介绍了搭建iOS超签签名服务器的原因和优势,包括不掉签、用户可以直接安装不需要信任、体验好等。同时也提到了超签的劣势,即一个证书只能安装100个,成本较高。文章还详细介绍了超签的实现原理,包括用户请求服务器安装mobileconfig文件、服务器调用苹果接口添加udid等步骤。最后,还提到了生成mobileconfig文件和导出AppleWorldwideDeveloperRelationsCertificationAuthority证书的方法。 ... [详细]
  • SQL Server中TempDB管理(version store的逻辑 ... [详细]
author-avatar
Meloux
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有