最近项目需要实现一个功能:用户在系统相册里选择并更换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全局背景图片相关推荐

  1. android+代码调用+相册+小米,Android调用系统相册选择图片,支持小米4云相册

    用小米4调用系统相册选择照片时,如果云相册功能开启的话.云相册中的图片也会显示在选择列表中.经过测试,选择到云相册中的图片的话,uri的scheme是file,而不再试content.本文支持云相册的 ...

  2. android 调用相册功能吗,Android调用系统相册选择图片,支持小米4云相册

    用小米4调用系统相册选择照片时,如果云相册功能开启的话.云相册中的图片也会显示在选择列表中.经过测试,选择到云相册中的图片的话,uri的scheme是file,而不再试content.本文支持云相册的 ...

  3. 学习笔记之Android调用系统相册选择图片

    文章目录 前言 使用步骤 小结 参考资料 前言 在相册里选择图片上传也是很常见的功能了例如微信朋友圈等等.但是他们是自定义的选择器,可以选择多张图片并修改.这里我们讲一个最简单的:调用系统的相册选择一 ...

  4. AndroidStudio调用系统相册选择图片并显示、将图片保存到私有空间

    有时候为了能让用户自定义软件的背景,我们需要实现从系统相册选择一张图片并将其进行保存,在后面打开的时候继续使用该图片充当背景.为什么要保存到私有空间呢?保存和到读取私有空间的内容是不需要权限的.由于实 ...

  5. MUI 拍照和从系统相册选择图片上传

    要完成用MUI 拍照和从系统相册选择图片上传的功能,可以理解成有三个功能 1 调用手机相机的功能(可以查看官方API  http://www.html5plus.org/doc/zh_cn/camer ...

  6. Android 拍照和相册选择

    前几天一直在想写一个简单干净的关于Android 拍照和相册选择的dome,直到今天才有时间去写,下面是图片介绍,资源代码会有上传!供初学者学习指教(代码是Android studio) 1.控件 0 ...

  7. android拍照所需的权限,eclipse --- Android拍照,相册选择图片以及Android6.0权限管理...

    [实例简介] eclipse --- Android拍照,相册选择图片以及Android6.0权限管理 [实例截图] [核心代码] camreainandroidm └── camreainandro ...

  8. 关于小米手机从系统相册选择图片的一个bug

    在开发应用的时候碰到一个问题,拍照或者从系统相册选择图片并上传,首先从相机或者相册获取图片并压缩处理,最后再上传,代码写好并基本测试通过,然而深度测试的时候却发现有一个问题. 在小米手机,即MIUI系 ...

  9. Android 刷新系统相册

    Android 刷新系统相册 最近在做项目时,发现把照片保存到手机指定路径后,有些手机打开系统相册居然看不到,像三星 S3.小米2.sony lt26i和HTC等部分机型!但是中兴N881f.魅族 3 ...

最新文章

  1. 服务器开启虚拟机就死机,解决ESXi服务器上磁盘锁导致虚拟机卡死的问题
  2. APP上线后,去除Log打印的问题
  3. 【Selenium 小知识】获取 token 和 cookies
  4. boost::interprocess::message_queue用法的测试程序
  5. Go Modules 的智障版本选择
  6. java技术论坛的毕业设计_基于java的bbs论坛设计,软件毕业设计
  7. oa中获取当前用户信息
  8. sharepoint 2013 sp1 patch安装后的手工运行
  9. 海康威视ivms-4200图文说明
  10. 嵌入式入门必去的网站 —— 介绍的非常详细
  11. adb安装apk文件时的常见的错误及解决方法
  12. HPE Microserver GEN10升级BIOS
  13. Power Apps 应用实战|轻松用 Power Apps 开发员工休假考勤管理小程序
  14. 未能加载文件或程序集什么原因
  15. Arduino 驱动TM1638显示十位的共阳数码管
  16. 华为云王红新_华为云新加坡峰会多家公司签署MoU,伙伴联合展示云+AI创新应用...
  17. 关于相对论的一个猜想——二维空间理论
  18. 无线网卡m2 ngff keyakeye接口改转多口有线网卡实现软路由
  19. 论文阅读: (ICDAR2021 海康威视)LGPMA(表格识别算法)及官方源码对应解读
  20. Java能抵挡住JavaScript的进攻吗?【转载】

热门文章

  1. 1.计算机语言(computer language)
  2. FFmpeg AVPacket 剖析以及使用
  3. p级数敛散性积分方式证明
  4. 智慧养老——让夕阳更美好
  5. ArcSDE配置与使用
  6. 使用pandas GroupBy获取每个组的统计信息(例如计数,均值等)?
  7. 上海交大采购ZJ-4型压电D33电压及电流信号采集系统
  8. 基于Vue的问卷调查app页面的开发
  9. GRE隧道是什么?他的作用是什么?
  10. mysql 测试快生产慢_MySQL太慢?试试这些诊断思路和工具