Android实现系统相册选择APP全局背景图片
最近项目需要实现一个功能:用户在系统相册里选择并更换APP全部界面的背景图片。
基本思路:
1,用户点击“选择背景图片”按钮后,跳转到系统相册中选择图片。APP把选择的图片压缩后单独保存到一个文件夹并取名background.jpg(下次保存则覆盖旧文件),并把图片的绝对路径保存到SharedPerference。
2,在所有Activity的基类BaseActivity的onStart()中,从SharedPerference取出background.jpg的路径并转换为BitMap再转换成Drawable,把Drawable加载到BaseActivity的DecorView中。
3,处理背景图片损坏的情况和内存溢出OOM
下面贴上代码
首先是“选择背景图片”按钮的点击事件(跳转到系统相册)
mBtnBackground.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Intent photoPickerIntent = new Intent(Intent.ACTION_PICK, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI);photoPickerIntent.setType("image/*");startActivityForResult(photoPickerIntent, IMAGE_CODE);}});
待用户选择完图片后,在onActivityResult()中把选择的图片取出并压缩
@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (resultCode != RESULT_OK) return;switch (requestCode) {case IMAGE_CODE:if (resultCode == RESULT_OK) {Uri selectedImage = data.getData();//返回的是uriString[] filePathColumn = {MediaStore.Images.Media.DATA};Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);cursor.moveToFirst();int columnIndex = cursor.getColumnIndex(filePathColumn[0]);String path = cursor.getString(columnIndex);File file = new File(path);if (!file.exists()) return;//使用第三方库进行图片压缩Bitmap bitmap = new CompressHelper.Builder(this).setMaxWidth(1280) // 默认最大宽度为720.setMaxHeight(754) // 默认最大高度为960.setQuality(80) // 默认压缩质量为80.setFileName("lejukang_background.jpg") // 设置你需要修改的文件名.setCompressFormat(Bitmap.CompressFormat.JPEG) // 设置默认压缩为jpg格式.setDestinationDirectoryPath(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath()).build().compressToBitmap(file);//背景图片加载到当前界面RelativeLayout layout1 = (RelativeLayout) findViewById(R.id.rl);Drawable drawable = new BitmapDrawable(bitmap);layout1.setBackground(drawable);try {//判断BitMap是否成功生成bitmap.getWidth();} catch (Exception e) {Toast.makeText(AlbumActivity.this,"图片太大,无法设为背景",Toast.LENGTH_SHORT).show();//为当前界面加载默认的背景图片//layout1.setBackgroundResource(R.mipmap.common_img);return;}saveBitmap(bitmap);break;}}}
saveBitmap(Bitmap bitmap)方法,单独保存选择的图片
public void saveBitmap(Bitmap bitmap) {// 首先保存图片File appDir = new File(Environment.getExternalStorageDirectory(), "background"); //目录名if (!appDir.exists()) {appDir.mkdir();}String fileName = "background" + ".jpg"; //背景图片文件名File file = new File(appDir, fileName);if (file.exists()) { //每次保存都把旧的背景图片覆盖成新的try {file.delete();file.createNewFile();} catch (IOException e) {e.printStackTrace();}}try {FileOutputStream fos = new FileOutputStream(file);bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);Hawk.put(HawkKey.BACKGROUND, file.getAbsolutePath()); //把背景图片的路径保存下来,待加载时取出fos.flush();fos.close();} catch (Exception e) {e.printStackTrace();}}
接下来在所有Activity的基类BaseActivity的onStart()方法中,调用setBackGround()来加载背景图片。
private void setBackground() {View view = this.getWindow().getDecorView(); //getmeiDecorView 获得window最顶层的ViewString path = Hawk.get("background",“”);//取出背景图片路径if (TextUtils.isEmpty(path)) { //没有背景图片的路径缓存时,加载默认图片view.setBackgroundResource(R.drawable.common_img);return;}Bitmap bitmap = BitmapFactory.decodeFile(path);try {//检查BitMap是否成功生成bitmap.getWidth();} catch (Exception e) {e.printStackTrace();//图片已损坏,加载默认图片view.setBackgroundResource(R.drawable.common_img);return;}//背景图片没有损坏,成功加载背景图片Drawable drawable = new BitmapDrawable(bitmap);view.setBackgroundDrawable(drawable);}
功能是实现了,但是当背景图片太大时,容易造成内存溢出OOM从而导致软件Crash。
解决内存溢出的方法有几个方法,第一个方法是图片压缩,在上面做了。
第二个方法是在BaseActivity的onStop()方法中取消背景图片的加载
@Overrideprotected void onStop() {super.onStop();View view = this.getWindow().getDecorView(); //getDecorView 获得window最顶层的Viewview.setBackgroundResource(0); //取消背景图片System.gc(); //通知系统回收}
如果把背景图片的加载和回收放到onCreate()和onDestroy(),当用户打开多个界面时,背景图片就会加载多张,不能及时回收,极易造成内存溢出OOM。现在放到onStart()和onStop()中,打开下一个界面时回收上一个界面的背景图片的所占用内存,就能保证内存中只有一张图片。
第三个方法:申请更大的内存 +关闭硬件加速以节省内存。
具体做法是在AndroidManifest.xml中加入
android:hardwareAccelerated="false"android:largeHeap="true"
特别鸣谢以下参考博客
https://blog.csdn.net/springsky_/article/details/25212419
https://blog.csdn.net/bigtree_mfc/article/details/55049501#commentsedit
Android实现系统相册选择APP全局背景图片相关推荐
- android+代码调用+相册+小米,Android调用系统相册选择图片,支持小米4云相册
用小米4调用系统相册选择照片时,如果云相册功能开启的话.云相册中的图片也会显示在选择列表中.经过测试,选择到云相册中的图片的话,uri的scheme是file,而不再试content.本文支持云相册的 ...
- android 调用相册功能吗,Android调用系统相册选择图片,支持小米4云相册
用小米4调用系统相册选择照片时,如果云相册功能开启的话.云相册中的图片也会显示在选择列表中.经过测试,选择到云相册中的图片的话,uri的scheme是file,而不再试content.本文支持云相册的 ...
- 学习笔记之Android调用系统相册选择图片
文章目录 前言 使用步骤 小结 参考资料 前言 在相册里选择图片上传也是很常见的功能了例如微信朋友圈等等.但是他们是自定义的选择器,可以选择多张图片并修改.这里我们讲一个最简单的:调用系统的相册选择一 ...
- AndroidStudio调用系统相册选择图片并显示、将图片保存到私有空间
有时候为了能让用户自定义软件的背景,我们需要实现从系统相册选择一张图片并将其进行保存,在后面打开的时候继续使用该图片充当背景.为什么要保存到私有空间呢?保存和到读取私有空间的内容是不需要权限的.由于实 ...
- MUI 拍照和从系统相册选择图片上传
要完成用MUI 拍照和从系统相册选择图片上传的功能,可以理解成有三个功能 1 调用手机相机的功能(可以查看官方API http://www.html5plus.org/doc/zh_cn/camer ...
- Android 拍照和相册选择
前几天一直在想写一个简单干净的关于Android 拍照和相册选择的dome,直到今天才有时间去写,下面是图片介绍,资源代码会有上传!供初学者学习指教(代码是Android studio) 1.控件 0 ...
- android拍照所需的权限,eclipse --- Android拍照,相册选择图片以及Android6.0权限管理...
[实例简介] eclipse --- Android拍照,相册选择图片以及Android6.0权限管理 [实例截图] [核心代码] camreainandroidm └── camreainandro ...
- 关于小米手机从系统相册选择图片的一个bug
在开发应用的时候碰到一个问题,拍照或者从系统相册选择图片并上传,首先从相机或者相册获取图片并压缩处理,最后再上传,代码写好并基本测试通过,然而深度测试的时候却发现有一个问题. 在小米手机,即MIUI系 ...
- Android 刷新系统相册
Android 刷新系统相册 最近在做项目时,发现把照片保存到手机指定路径后,有些手机打开系统相册居然看不到,像三星 S3.小米2.sony lt26i和HTC等部分机型!但是中兴N881f.魅族 3 ...
最新文章
- 服务器开启虚拟机就死机,解决ESXi服务器上磁盘锁导致虚拟机卡死的问题
- APP上线后,去除Log打印的问题
- 【Selenium 小知识】获取 token 和 cookies
- boost::interprocess::message_queue用法的测试程序
- Go Modules 的智障版本选择
- java技术论坛的毕业设计_基于java的bbs论坛设计,软件毕业设计
- oa中获取当前用户信息
- sharepoint 2013 sp1 patch安装后的手工运行
- 海康威视ivms-4200图文说明
- 嵌入式入门必去的网站 —— 介绍的非常详细
- adb安装apk文件时的常见的错误及解决方法
- HPE Microserver GEN10升级BIOS
- Power Apps 应用实战|轻松用 Power Apps 开发员工休假考勤管理小程序
- 未能加载文件或程序集什么原因
- Arduino 驱动TM1638显示十位的共阳数码管
- 华为云王红新_华为云新加坡峰会多家公司签署MoU,伙伴联合展示云+AI创新应用...
- 关于相对论的一个猜想——二维空间理论
- 无线网卡m2 ngff keyakeye接口改转多口有线网卡实现软路由
- 论文阅读: (ICDAR2021 海康威视)LGPMA(表格识别算法)及官方源码对应解读
- Java能抵挡住JavaScript的进攻吗?【转载】