当前位置:网站首页>Unity 保存图片到相册以及权限管理
Unity 保存图片到相册以及权限管理
2022-07-28 00:55:00 【2080.】
一、前言
本文旨在介绍,如何将游戏内的图片保存到Android相册,并实时刷新显示出来(不需要写Android原生项目),另外解决存储权限申请和弹窗隐藏问题
二、保存图片到相册
- 修改File->BuildSettings->PlaySettings->OtherSettings写入权限
- Internal 是内部存储,无需存储权限,可以使用软件目录下的存储,但不可以访问手机目录(如果我们只是想保存图片到相册,选择该方式即可)
- External(SD) 是外部存储,需要存储权限。(但是从产品的角度考虑,弹窗的转化率是非常的低,大多数用户是不愿意同意该权限申请)
- 图片设置
打开图片的读写功能
- 将贴图转化成字节数组时报错,不支持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;
}
- 核心代码
/// <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>
- 上面提到如果我们写入的是外部存储,是需要存储权限的,但是如果在一进入游戏就显示权限申请弹窗,效果是非常不好的,我们可以在标签内添加如下设置,会在一开始跳过申请权限的弹窗
<meta-data android:name="unityplayer.SkipPermissionsDialog" android:value="true" />
- 适当的地方申请权限
比如用户点击下载时,先行判断是否写入权限,没有的话就直接申请好啦
if (!UnityEngine.Android.Permission.HasUserAuthorizedPermission(UnityEngine.Android.Permission.ExternalStorageWrite))
{
UnityEngine.Android.Permission.RequestUserPermission(UnityEngine.Android.Permission.ExternalStorageWrite);
return;
}
边栏推荐
- Flex布局学习完成PC端
- 软件测试面试题:你认为做好测试用例设计工作的关键是什么?
- LeetCode 热题 HOT 100 -> 3. 无重复字符的最长子串
- APP如何上架App Store?
- Implementation of mongodb/mongotemplate.upsert batch inserting update data
- go 学习02 基础知识
- Promise from introduction to mastery (Chapter 2 understanding and use of promise)
- Product interpretation - Design and distributed expansion of metersphere UI test module
- 小程序毕设作品之微信校园浴室预约小程序毕业设计成品(1)开发概要
- shell正则和元字符
猜你喜欢

Codeforces Round #810 (Div. 2)A~C题解
![53: Chapter 5: develop admin management service: 6: develop [admin administrator exit login, interface]; (one point: when we want to modify a value with a certain coding method, the new value should b](/img/9a/674308c7a21fa2be0943ca7967e274.png)
53: Chapter 5: develop admin management service: 6: develop [admin administrator exit login, interface]; (one point: when we want to modify a value with a certain coding method, the new value should b

Clear the cause of floating and six methods (solve the problem that floating affects the parent element and the global)

小米网站主页面大模块——小模块+导航(浮动案例)

Aike AI frontier promotion (7.14)

Cloud native enthusiast weekly: the evolution of Prometheus architecture

Completely delete MySQL in Linux system

小程序毕设作品之微信校园浴室预约小程序毕业设计成品(1)开发概要

go 学习01

Sample imbalance - entry 0
随机推荐
go 学习02 基础知识
软考 --- 数据库(2)关系模型
执行 Add-Migration 迁移时报 Build failed.
Go learn 02 basic knowledge
对话Atlassian认证专家叶燕秀:Atlassian产品进入后Server时代,中国用户应当何去何从?
【Star项目】小帽飞机大战(六)
Aike AI frontier promotion (7.14)
Promise从入门到精通(第4章 async 和 await)
数据输出-绘制动图
MySQL create stored procedure ------ [hy000][1418] this function has none of deterministic, no SQL
【数据库数据恢复】SQL Server数据库磁盘空间不足的数据恢复案例
go 学习01
Codeforces Round #807 (Div. 2) A-C题解
Appium click operation sorting
Implementation of mongodb/mongotemplate.upsert batch inserting update data
Software testing interview question: why should we carry out testing in a team?
学会这招再也不怕手误让代码崩掉
SFTP file / folder upload server
IT这个岗位,人才缺口百万,薪资水涨船高,上不封顶
Data output - dynamic drawing


