Unity 保存图片到相册以及权限管理

一、前言

本文旨在介绍,如何将游戏内的图片保存到Android相册,并实时刷新显示出来(不需要写Android原生项目),另外解决存储权限申请和弹窗隐藏问题

二、保存图片到相册

  1. 修改File->BuildSettings->PlaySettings->OtherSettings写入权限
  • Internal 是内部存储,无需存储权限,可以使用软件目录下的存储,但不可以访问手机目录(如果我们只是想保存图片到相册,选择该方式即可)
  • External(SD) 是外部存储,需要存储权限。(但是从产品的角度考虑,弹窗的转化率是非常的低,大多数用户是不愿意同意该权限申请
    在这里插入图片描述
  1. 图片设置

打开图片的读写功能在这里插入图片描述

  1. 将贴图转化成字节数组时报错,不支持Texture2D压缩格式

File写入贴图时,需要将图片转成字节数组,texture2D.EncodeToPNG(),但是会出现如下报错
在这里插入图片描述

传入目标贴图,返回的图片即可转成字节数组啦

        public Texture2D DeCompress(Texture2D source)
        {
    
    
            RenderTexture renderTex = RenderTexture.GetTemporary(
                        source.width,
                        source.height,
                        0,
                        RenderTextureFormat.Default,
                        RenderTextureReadWrite.Linear);

            Graphics.Blit(source, renderTex);
            RenderTexture previous = RenderTexture.active;
            RenderTexture.active = renderTex;
            Texture2D readableText = new Texture2D(source.width, source.height);
            readableText.ReadPixels(new Rect(0, 0, renderTex.width, renderTex.height), 0, 0);
            readableText.Apply();
            RenderTexture.active = previous;
            RenderTexture.ReleaseTemporary(renderTex);
            return readableText;
        }
  1. 核心代码
/// <summary>
        /// 保存图片
        /// </summary>
        /// <param name="texture"></param>
        /// <returns></returns>
        private void SaveImages(Texture2D texture)
        {
    
    
            string path = Application.streamingAssetsPath;
#if UNITY_ANDROID && !UNITY_EDITOR
            path = "/sdcard/DCIM/Camera"; //设置图片保存到设备的目录.
#endif
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);
            string savePath = path + "/" + m_DailyBgConfigData.Maintitle + ".png";
            try
            {
    
    
                Application.HasUserAuthorization(UserAuthorization.Microphone);
                byte[] data = DeCompress(texture).EncodeToPNG();
                File.WriteAllBytes(savePath, data);
                OnSaveImagesPlartform(savePath);
            }
            catch
            {
    
       
            }
        }
        /// <summary>
        /// 刷新相册(不需要单独创建原生aar或jar)
        /// </summary>
        /// <param name="path"></param>
        private void OnSaveImagesPlartform(string filePath)
        {
    
    
#if UNITY_ANDROID && !UNITY_EDITOR
            string[] paths = new string[1];
            paths[0] = filePath; 
            using (AndroidJavaClass PlayerActivity = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
            {
    
    
                AndroidJavaObject playerActivity = PlayerActivity.GetStatic<AndroidJavaObject>("currentActivity");
                using (AndroidJavaObject Conn = new AndroidJavaObject("android.media.MediaScannerConnection", playerActivity, null))
                {
    
    
                    Conn.CallStatic("scanFile", playerActivity, paths, null, null);
                }
            }
#endif
        }
        /// <summary>
        /// 压缩图片
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        public Texture2D DeCompress(Texture2D source)
        {
    
    
            RenderTexture renderTex = RenderTexture.GetTemporary(
                        source.width,
                        source.height,
                        0,
                        RenderTextureFormat.Default,
                        RenderTextureReadWrite.Linear);

            Graphics.Blit(source, renderTex);
            RenderTexture previous = RenderTexture.active;
            RenderTexture.active = renderTex;
            Texture2D readableText = new Texture2D(source.width, source.height);
            readableText.ReadPixels(new Rect(0, 0, renderTex.width, renderTex.height), 0, 0);
            readableText.Apply();
            RenderTexture.active = previous;
            RenderTexture.ReleaseTemporary(renderTex);
            return readableText;
        }

这里主要说下刷新相册的方法,如果我们不调用刷新的haul,图片是可以在文件管理器中找到的,但是并不会显示在相册中,MediaScannerConnection.scanFile是Android原生的接口,我们不再需要单独再去创建个AS项目,打个aar包

三、存储权限

Plugin->Android->AndroidManifest.xml中添加如写入权限

<manifest>
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
 </manifest>
  1. 上面提到如果我们写入的是外部存储,是需要存储权限的,但是如果在一进入游戏就显示权限申请弹窗,效果是非常不好的,我们可以在标签内添加如下设置,会在一开始跳过申请权限的弹窗
    <meta-data android:name="unityplayer.SkipPermissionsDialog" android:value="true" />
  1. 适当的地方申请权限

比如用户点击下载时,先行判断是否写入权限,没有的话就直接申请好啦

if (!UnityEngine.Android.Permission.HasUserAuthorizedPermission(UnityEngine.Android.Permission.ExternalStorageWrite))
            {
    
    
                UnityEngine.Android.Permission.RequestUserPermission(UnityEngine.Android.Permission.ExternalStorageWrite);
                return;
            }

猜你喜欢

转载自blog.csdn.net/weixin_42186644/article/details/125996868