需求:保存图片到系统相册,并能通过微信手动发送该图片给好友。
遇到问题:
1.正常保存图片文件到手机磁盘,但是系统相册APP内看不到图片。
2.通过更新系统扫描后能看到了图片了,但部分国产芯片手机,图片是纯黑色。
解决方案如下:
public void ARSnapCapture(){
isScreenShot = true;
}
void OnPostRender()
{
if (isScreenShot)
{
if (UIGame.instance != null)
UIGame.instance.uiCamera.enabled = false;
Rect rect = new Rect(0, 0, Screen.width, Screen.height);
// 先创建一个的空纹理,大小可根据实现需要来设置
Texture2D screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24, false);
// 读取屏幕像素信息并存储为纹理数据,
screenShot.ReadPixels(rect, 0, 0);
screenShot.Apply();
// 然后将这些纹理数据,成一个png图片文件
byte[] bytes = screenShot.EncodeToPNG();
if (UIGame.instance != null)
UIGame.instance.uiCamera.enabled = true;
isScreenShot = false;
StartCoroutine(SaveTexFile(bytes));
}
}
IEnumerator SaveTexFile(byte[] imagebytes)
{
#if UNITY_EDITOR_OSX
ssPath = Application.persistentDataPath + "/";
#elif UNITY_ANDROID
ssPath = Application.persistentDataPath.Substring(0, Application.persistentDataPath.IndexOf("Android")) + "/DCIM/Camera/";
#endif
snFileName = GeneratePicFileName() + ".png";
if (!Directory.Exists(ssPath))
{
Directory.CreateDirectory(ssPath);
}
File.WriteAllBytes(ssPath + snFileName, imagebytes);//存储png图
yield return new WaitForSeconds(0.1f);
UIGame.instance.ShowToast("已保存到相册");
#if UNITY_ANDROID
string[] paths = new string[1];
paths[0] = ssPath + snFileName;
ScanFile(paths);
#endif
}
//刷新图片,显示到相册中
void ScanFile(string[] path)
{
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, path, null, null);
}
}
}
备注:
1.ReadPixels是从系统缓冲区帧里找像素而不是从图框内找。简单说就是,你的图应该先在Camera渲染完,存进缓冲之后再ReadPixels。所以修改方法就是,把Update换成OnPostRender,这个函数只有在摄像机下才会执行,摄像机每帧渲染完执行。
2.Android 保存图片,保存完毕之后就是要通知相册刷新
在android4.4中:
MediaScannerConnection.scanFile(this, new String[]{SAVE_REAL_PATH+ "/" + fileName}, null, new MediaScannerConnection.OnScanCompletedListener() {
@Override
public void onScanCompleted(String path, Uri uri) {
Log.e( "onScanCompleted: ", path);
Log.e( "onScanCompleted: ", uri.toString());
}
});
在android4.4以上的是发送广播来实现:
Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED); //这是刷新SD卡
// Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); // 这是刷新单个文件
Uri uri = Uri.fromFile(new File(SAVE_REAL_PATH));
intent.setData(uri);
sendBroadcast(intent);
附备忘:Vuforia切换回识别场景后黑屏解决
使用Vuforia SDK开发时,如果从其他非识别场景切换回识别场景,可能会出现黑屏问题。解决方法是在切换到其他场景时,先将当前场景的Tracker信息全部Stop。代码如下:
IEnumerator LoadScenes(string sceneName)
{
if (TrackerManager.Instance.GetTracker<MarkerTracker>() != null)
{
MarkerTracker marker = TrackerManager.Instance.GetTracker<MarkerTracker>();
marker.Stop();
}
if (TrackerManager.Instance.GetTracker<TextTracker>() != null)
{
TextTracker textTracker = TrackerManager.Instance.GetTracker<TextTracker>();
textTracker.Stop();
}
if (TrackerManager.Instance.GetTracker<ObjectTracker>() != null)
{
ObjectTracker objTracker = TrackerManager.Instance.GetTracker<ObjectTracker>();
objTracker.Stop();
}
//此处返回waitForSeconds,因为我是在OnGUI中启动协程,如果不用WaitForSeconds,就会识别两次模型
yield return new WaitForSeconds(0.5f); //WaitForEndOfFrame();
Application.LoadLevel(sceneName);
}