• 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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    1. 核心代码
    /// 
            /// 保存图片
            /// 
            /// 
            /// 
            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
                {   
                }
            }
            /// 
            /// 刷新相册(不需要单独创建原生aar或jar)
            /// 
            /// 
            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
            }
            /// 
            /// 压缩图片
            /// 
            /// 
            /// 
            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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

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

    三、存储权限

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

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

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

    if (!UnityEngine.Android.Permission.HasUserAuthorizedPermission(UnityEngine.Android.Permission.ExternalStorageWrite))
                {
                    UnityEngine.Android.Permission.RequestUserPermission(UnityEngine.Android.Permission.ExternalStorageWrite);
                    return;
                }
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    Samba+ldap认证
    C# 语言的面向对象技术
    共话医疗数据安全,美创科技@2023南湖HIT论坛,11月11日见
    WebSocket通讯架构
    自我介绍思考
    【Flutter从入门到入坑】Dart语言基础
    linux安装mysql
    【Python 千题 —— 基础篇】分解数据
    【3D 图像分类】基于 Pytorch 的 3D 立体图像分类4(多人标注的结节立体框合并和特征等级投票)
    用 NEON 实现高效的 FIR 滤波器
  • 原文地址:https://blog.csdn.net/weixin_42186644/article/details/125996868