├── .gitignore ├── Assets ├── GTSPhotoLibraryTools │ ├── Editor │ │ └── GTSPhotoLibraryToolsCallback.cs │ └── GTSPhotoLibraryToolsUtils.cs └── Plugins │ └── iOS │ └── GTSPhotoLibraryTools.mm └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /[Ll]ibrary/ 2 | /[Tt]emp/ 3 | /[Oo]bj/ 4 | /[Bb]uild/ 5 | /[Bb]uilds/ 6 | /Assets/AssetStoreTools* 7 | 8 | # Visual Studio 2015 cache directory 9 | /.vs/ 10 | 11 | # Autogenerated VS/MD/Consulo solution and project files 12 | ExportedObj/ 13 | .consulo/ 14 | *.csproj 15 | *.unityproj 16 | *.sln 17 | *.suo 18 | *.tmp 19 | *.user 20 | *.userprefs 21 | *.pidb 22 | *.booproj 23 | *.svd 24 | *.pdb 25 | 26 | # Unity3D generated meta files 27 | *.pidb.meta 28 | 29 | # Unity3D Generated File On Crash Reports 30 | sysinfo.txt 31 | 32 | # Builds 33 | *.apk 34 | *.unitypackage 35 | *.meta 36 | *.unity 37 | Demo* 38 | Builds 39 | .csproj 40 | .sln 41 | .vscode 42 | tmp 43 | ProjectSettings 44 | -------------------------------------------------------------------------------- /Assets/GTSPhotoLibraryTools/Editor/GTSPhotoLibraryToolsCallback.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using UnityEditor; 3 | using UnityEditor.Callbacks; 4 | using UnityEditor.iOS.Xcode; 5 | 6 | namespace GTSPhotoLibraryTools 7 | { 8 | class Callback 9 | { 10 | [PostProcessBuild] 11 | public static void OnPostProcessBuild(BuildTarget target, string pathToBuiltProject) 12 | { 13 | if (target == BuildTarget.iOS) 14 | { 15 | ModifyProj(pathToBuiltProject); 16 | ModifyInfoPlist(pathToBuiltProject); 17 | } 18 | } 19 | 20 | private static void ModifyProj(string pathToBuiltProject) 21 | { 22 | var pbxProjectPath = Path.Combine(pathToBuiltProject, "./Unity-iPhone.xcodeproj/project.pbxproj"); 23 | PBXProject pbxProject = new PBXProject(); 24 | pbxProject.ReadFromFile(pbxProjectPath); 25 | 26 | var targetGUID = pbxProject.TargetGuidByName("Unity-iPhone"); 27 | 28 | pbxProject.AddFrameworkToProject(targetGUID, "Photos.framework", weak: false); 29 | File.WriteAllText(pbxProjectPath, pbxProject.WriteToString()); 30 | } 31 | 32 | private static void ModifyInfoPlist(string pathToBuiltProject) 33 | { 34 | var infoPlistPath = Path.Combine(pathToBuiltProject, "./Info.plist"); 35 | PlistDocument plist = new PlistDocument(); 36 | plist.ReadFromString(File.ReadAllText(infoPlistPath)); 37 | 38 | PlistElementDict rootDict = plist.root; 39 | // 相簿權限描述 (iOS10 必須設定) 40 | rootDict.SetString("NSPhotoLibraryUsageDescription", ""); 41 | // 全螢幕 42 | rootDict.SetBoolean("UIRequiresFullScreen", true); 43 | 44 | File.WriteAllText(infoPlistPath, plist.WriteToString()); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Assets/GTSPhotoLibraryTools/GTSPhotoLibraryToolsUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.IO; 6 | using System.Runtime.InteropServices; 7 | using System.Threading; 8 | using UnityEngine; 9 | 10 | namespace GTSPhotoLibraryTools 11 | { 12 | public class Utils 13 | { 14 | [DllImport("__Internal")] 15 | private static extern void RequestPermissionC(string callbackObj, string callbackFunc); 16 | [DllImport("__Internal")] 17 | private static extern void SaveImageToPhotoLibraryC(string imagePath); 18 | 19 | public static void RequestPermission(string callbackObj, string callbackFunc) 20 | { 21 | #if UNITY_IOS 22 | RequestPermissionC(callbackObj, callbackFunc); 23 | #elif UNITY_ANDROID 24 | #endif 25 | } 26 | 27 | public static void SaveImageToPhotoLibrary(Texture2D texture) 28 | { 29 | 30 | #if UNITY_IOS 31 | var filepath = String.Format("{0}/{1}.png", Application.persistentDataPath, DateTime.Now.Ticks); 32 | File.WriteAllBytes(filepath, texture.EncodeToPNG()); 33 | SaveImageToPhotoLibraryC(filepath); 34 | #elif UNITY_ANDROID 35 | #endif 36 | } 37 | 38 | public static IEnumerator CaptureScreen(Action action) 39 | { 40 | yield return new WaitForEndOfFrame(); 41 | 42 | var width = Screen.width; // for Taking Picture 43 | var height = Screen.height; // for Taking Picture 44 | var camera = Camera.main.GetComponent(); 45 | var renderTex = new RenderTexture(width, height, 24); 46 | camera.targetTexture = renderTex; 47 | RenderTexture.active = renderTex; 48 | camera.Render(); 49 | var screenshot = new Texture2D(width, height, TextureFormat.RGB24, false); 50 | screenshot.ReadPixels(new Rect(0, 0, width, height), 0, 0); 51 | screenshot.Apply(); //false 52 | RenderTexture.active = null; 53 | camera.targetTexture = null; 54 | 55 | action(screenshot); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Assets/Plugins/iOS/GTSPhotoLibraryTools.mm: -------------------------------------------------------------------------------- 1 | // 2 | // GTSPhotoLibraryTools.mm 3 | // Unity-iPhone 4 | // 5 | // Created by 默司 on 2017/5/10. 6 | // 7 | // 8 | 9 | #include 10 | #include 11 | 12 | extern "C" { 13 | 14 | void RequestPermissionC(char *callbackObj, char *callbackFunc) { 15 | NSString *obj = [NSString stringWithCString:callbackObj encoding:NSUTF8StringEncoding]; 16 | NSString *func = [NSString stringWithCString:callbackFunc encoding:NSUTF8StringEncoding]; 17 | 18 | if (PHPhotoLibrary.authorizationStatus == PHAuthorizationStatusAuthorized) { 19 | return UnitySendMessage([obj UTF8String], [func UTF8String], ""); 20 | } 21 | 22 | if (PHPhotoLibrary.authorizationStatus == PHAuthorizationStatusNotDetermined) { 23 | [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) { 24 | if (status == PHAuthorizationStatusAuthorized) { 25 | UnitySendMessage([obj UTF8String], [func UTF8String], ""); 26 | } 27 | }]; 28 | } else { 29 | UIAlertController *c = [UIAlertController alertControllerWithTitle:@"相簿權限" message:@"相簿存取已被停用" preferredStyle:UIAlertControllerStyleAlert]; 30 | 31 | // UIAlertActionStyleCancel 32 | // UIAlertActionStyleDefault 33 | [c addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]]; 34 | [c addAction:[UIAlertAction actionWithTitle:@"前往設定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { 35 | [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]; 36 | }]]; 37 | 38 | [UIApplication.sharedApplication.keyWindow.rootViewController presentViewController:c animated:true completion:nil]; 39 | } 40 | } 41 | 42 | void SaveImageToPhotoLibraryC(char* imagePath) { 43 | NSString* path = [NSString stringWithCString:imagePath encoding:kCFStringEncodingUTF8]; 44 | 45 | UIImage* photo = [UIImage imageWithData:[NSData dataWithContentsOfFile:path] scale:1]; 46 | 47 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 48 | UIImageWriteToSavedPhotosAlbum(photo, nil, nil, nil); 49 | 50 | NSFileManager *manager = [NSFileManager defaultManager]; 51 | [manager removeItemAtPath:path error:nil]; 52 | }); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Unity 相簿工具 Plugin 2 | 3 | iOS / Android 相簿相關工具 4 | 5 | ## 目前功能 6 | 7 | - RequestPermission(string callbackObj, string callbackFunc) : 要求相簿存取權限 8 | - SaveImageToPhotoLibrary(Texture2D texture) : 將照片存放到相簿中 9 | - CaptureScreen() : 抓取 mainCamera 截圖 10 | 11 | ## 自動處理 12 | 13 | - iOS 14 | 15 | - 加入 Photos.framework 16 | - 在 info.plist 加入 NSPhotoLibraryUsageDescription = "" 17 | - 在 info.plist 加入 UIRequiresFullScreen = true 18 | 19 | ## 使用方式 20 | 21 | - 複製到專案中 22 | - 範例 23 | 24 | ```csharp 25 | using System.Collections; 26 | using System.Collections.Generic; 27 | using UnityEngine; 28 | using GTSPhotoLibraryTools; 29 | 30 | public class DemoScript : MonoBehaviour 31 | { 32 | 33 | private Texture2D screenshot; 34 | 35 | // Use this for initialization 36 | void Start() 37 | { 38 | 39 | } 40 | 41 | // Update is called once per frame 42 | void Update() 43 | { 44 | 45 | } 46 | 47 | public void OnTestClick() 48 | { 49 | StartCoroutine(CaptureScreen()); 50 | } 51 | 52 | IEnumerator CaptureScreen() 53 | { 54 | GameObject.Find("Canvas").GetComponent().enabled = false; 55 | yield return StartCoroutine(Utils.CaptureScreen((screenshot) => 56 | { 57 | this.screenshot = screenshot; 58 | Utils.RequestPermission(this.name, "OnPermission"); 59 | GameObject.Find("Canvas").GetComponent().enabled = true; 60 | })); 61 | } 62 | 63 | void OnPermission() 64 | { 65 | Utils.SaveImageToPhotoLibrary(screenshot); 66 | } 67 | } 68 | 69 | ``` 70 | --------------------------------------------------------------------------------