Unity调用ios的相机相册

2 篇文章 0 订阅

因为最近几天项目中有一个更换头像的需求 之前安卓版的已经写完了 Demo地址在这里 适配了安卓6.0以上

https://download.csdn.net/download/kangying3769/10318615

下面开始正题 调用ios的相机相册 

首先先创建两个Button 一个RawImage 作为我们打开相机相册的按钮 和显示图片的界面


界面搭建完成后 新建文件夹  Plugins--IOS 

新建两个脚本 IOSCameraController.h  IOSCameraController.m 这个是oc的格式 一个是头文件 一个是实现文件


下面开始编写代码

  • iOS 获取图片有三种方法:

    • 直接调用摄像头拍照;
    • 从相册中选择;
    • 从图库中选择。
  • UIImagePickerController 是系统提供的用来获取图片和视频的接口。用 UIImagePickerController 类来获取图片视频,大体分为以下几个步骤:

    • 初始化 UIImagePickerController 类;
    • 设置 UIImagePickerController 实例的数据来源类型;
    • 设置代理;
    • 如果需要做图片修改的话设置 allowsEditing = YES。
IOSCameraController.h 的代码如下:
//import 引用头文件 相当远Using 
#import<QuartzCore/CADisplayLink.h>
//声明一个IOSCameraController类  继承自UIViewController <>里面是是协议/代理的调用声明 可以理解为c#的接口
@interface IOSCameraController : UIViewController<UIImagePickerControllerDelegate,UINavigationControllerDelegate>
@end
IOSCameraController.m的代码如下:
#import "IOSCameraController.h"

@implementation IOSCameraController
-(void)OpenTarget:(UIImagePickerControllerSourceType)type{
	//创建UIImagePickerController实例
    UIImagePickerController *picker;
    picker= [[UIImagePickerController alloc]init];
    //设置代理
    picker.delegate = self;
    //是否允许编辑 (默认为NO)
    picker.allowsEditing = YES;
    //设置照片的来源
    // UIImagePickerControllerSourceTypePhotoLibrary,      // 来自图库
    // UIImagePickerControllerSourceTypeCamera,            // 来自相机
    // UIImagePickerControllerSourceTypeSavedPhotosAlbum   // 来自相册
    picker.sourceType = type;
    
    //这里需要判断设备是iphone还是ipad  如果使用的是iphone并没有问题 但是如果 是在ipad上调用相册获取图片 会出现没有确定(选择)的按钮 所以这里判断
    //了一下设备,针对ipad 使用另一种方法 但是这种方法是弹出一个界面 并不是覆盖整个界面 需要改进 试过另一种方式 重写一个相册界面 
    //(QQ的ipad选择头像的界面 就使用了这种方式 但是这里我们先不讲 (因为我也不太懂 但是我按照简书的一位老哥的文章写出来了 这里放一下这个简书的链接
    //https://www.jianshu.com/p/0ddf4f7476aa)
    if (picker.sourceType == UIImagePickerControllerSourceTypePhotoLibrary &&[[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
        // 设置弹出的控制器的显示样式
        picker.modalPresentationStyle = UIModalPresentationPopover;
        //获取这个弹出控制器
        UIPopoverPresentationController *popover = picker.popoverPresentationController;
        //设置代理
        popover.delegate = self;
        //下面两个属性设置弹出位置
        popover.sourceRect = CGRectMake(0, 0, 0, 0);
        popover.sourceView = self.view;
        //设置箭头的位置
        popover.permittedArrowDirections = UIPopoverArrowDirectionAny;
        //展示选取照片控制器
        [self presentViewController:picker animated:YES completion:nil];
    } else {
        //展示选取照片控制器
        [self presentViewController:picker animated:YES completion:^{}];
    }
   
}
//选择完成,点击界面中的某个图片或者选择(Choose)按钮时触发
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
    //关闭界面
    [picker dismissViewControllerAnimated:YES completion:^{}];
    //得到照片
    UIImage *image = [info objectForKey:@"UIImagePickerControllerEditedImage"];
    if (image == nil) {
        image = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
    }
    //有些时候我们拍照后经常发现导出的照片方向会有问题,要么横着,要么颠倒着,需要旋转才适合观看。但是在ios设备上是正常的
    //所以在这里处理了图片  让他旋转成我们需要的
    if (image.imageOrientation != UIImageOrientationUp) {
    //图片旋转
        image = [self fixOrientation:image];
    }
    //获取保存图片的地址
    NSString *imagePath = [self GetSavePath:@"Temp.jpg"];
    //保存图片到沙盒路径 对应unity中的Application.persistentDataPath 之后我们取图片就需要在这个路径下取  这是一个可读可写的路径
    [self SaveFileToDoc:image path:imagePath];
}
//获取保存文件的路径 如果有返回路径 没有创建一个返回
-(NSString*)GetSavePath:(NSString *)filename{
    NSArray *pathArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *docPath = [pathArray objectAtIndex:0];
    return [docPath stringByAppendingPathComponent:filename];
}
//将图片保存到沙盒路径
-(void)SaveFileToDoc:(UIImage *)image path:(NSString *)path{
    NSData *data;
    if (UIImagePNGRepresentation(image)==nil) {
        data = UIImageJPEGRepresentation(image, 1);
    }else{
        data = UIImagePNGRepresentation(image);
    }
    [data writeToFile:path atomically:YES];
    //保存之后通知unity 执行对应的回调 
    //UnitySendMessage 是用来给unity发消息的  有三个参数 1.挂载对应回调脚本的物体名 2.回调函数的名称 3.对应回调上的参数
    UnitySendMessage("Canvas", "Message", "Temp.jpg");
}
#pragma mark 图片处理方法
//图片旋转处理
- (UIImage *)fixOrientation:(UIImage *)aImage {
    CGAffineTransform transform = CGAffineTransformIdentity;
    
    switch (aImage.imageOrientation) {
        case UIImageOrientationDown:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.width, aImage.size.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;
            
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
            transform = CGAffineTransformRotate(transform, M_PI_2);
            break;
            
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, 0, aImage.size.height);
            transform = CGAffineTransformRotate(transform, -M_PI_2);
            break;
        default:
            break;
    }
    
    switch (aImage.imageOrientation) {
        case UIImageOrientationUpMirrored:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
            
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.height, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
        default:
            break;
    }
    
    // Now we draw the underlying CGImage into a new context, applying the transform
    // calculated above.
    CGContextRef ctx = CGBitmapContextCreate(NULL, aImage.size.width, aImage.size.height,
                                             CGImageGetBitsPerComponent(aImage.CGImage), 0,
                                             CGImageGetColorSpace(aImage.CGImage),
                                             CGImageGetBitmapInfo(aImage.CGImage));
    CGContextConcatCTM(ctx, transform);
    switch (aImage.imageOrientation) {
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            // Grr...
            CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.height,aImage.size.width), aImage.CGImage);
            break;
            
        default:
            CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.width,aImage.size.height), aImage.CGImage);
            break;
    }
    // And now we just create a new UIImage from the drawing context
    CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
    UIImage *img = [UIImage imageWithCGImage:cgimg];
    CGContextRelease(ctx);
    CGImageRelease(cgimg);
    return img;
}
@end
//由于C++编译器需要支持函数的重载,会改变函数的名称,因此dll的导出函数通常是标准C定义的。
//这就使得C和C++的互相调用变得很常见。但是有时可能又会直接用C来调用,不想重新写代码,
//让标准C编写的dll函数定义在C和C++编译器下都能编译通过,通常会使用以下的格式:(这个格式在很多成熟的代码中很常见)
#if defined(__cplusplus)
extern "C" {
#endif
    //导出接口供unity使用
    void IOS_OpenCamera(){
        IOSCameraController *app = [[IOSCameraController alloc]init];
        UIViewController *vc = UnityGetGLViewController();
        [vc.view addSubview:app.view];
        [app OpenTarget:UIImagePickerControllerSourceTypeCamera];
    }
    void IOS_OpenAlbum(){
        IOSCameraController *app = [[IOSCameraController alloc]init];
        UIViewController *vc = UnityGetGLViewController();
        [vc.view addSubview:app.view];
        [app OpenTarget:UIImagePickerControllerSourceTypePhotoLibrary];
    }
#if defined(__cplusplus)
}
#endif

在ios边的代码就写完了 回到unity这边 

创建一个脚本 名为OpenCameraOrAlbum

OpenCameraOrAlbum代码如下:

using System.Collections;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public class OpenCameraOrAlbum : MonoBehaviour {
    [SerializeField] private Button _openCamera; //打开相机按钮
    [SerializeField] private Button _openAlbum; //打开相册按钮
    [SerializeField] private RawImage _image; //用于显示的图片
    //引入在oc中定义的那两个方法
    [DllImport("__Internal")]
    private static extern void IOS_OpenCamera();
    [DllImport("__Internal")]
    private static extern void IOS_OpenAlbum();

    void Awake()
    {
        //为两个button添加点击事件
        _openCamera.onClick.AddListener(IOS_OpenCamera);
        _openAlbum.onClick.AddListener(IOS_OpenAlbum);
    }
    //ios回调unity的函数
    void Message(string filenName)
    {
        //我们传进来的只是文件名字 这里合成路径
         string filePath = Application.persistentDataPath + "/" + filenName;
        //开启一个协程加载图片
        StartCoroutine(HttpGetTexture(filePath));
    }
    IEnumerator HttpGetTexture(string url)
    {
        using (UnityWebRequest request = UnityWebRequestTexture.GetTexture(url))
        {
            yield return request.SendWebRequest();
            Texture2D tex = new Texture2D(128, 128);
            tex.LoadImage(request.downloadHandler.data);
            _image.texture = tex;

        }
    }

}

将对应的button和rawimage添加到inspector界面上

现在就大功告成了 可以打包测试了

最后特别感谢 群友 津巴布韦-买买提 老哥 因为我对oc ios开发不是很懂帮我解决了很多问题

下面附上我的Demo工程

https://download.csdn.net/download/kangying3769/10423964

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 24
    评论
Unity调用Android相册可以通过编写本地插件来实现。以下是一种方法: 首先,创建一个Java类作为我们的本地插件。在Android Studio中,创建一个新的Java类文件,并添加以下代码: ```java import android.content.Intent; import android.net.Uri; import android.provider.MediaStore; public class GalleryPlugin { public static void OpenGallery() { Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); intent.setType("image/*"); intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[]{"image/jpeg", "image/png"}); UnityPlayer.currentActivity.startActivityForResult(intent, 1); } } ``` 然后,在Unity中创建一个C#脚本来调用这个本地插件。在脚本中,我们将使用`DllImport`来导入Android库,并定义一个静态方法来调用Java类中的方法: ```csharp using System.Runtime.InteropServices; public class AndroidGallery : MonoBehaviour { [DllImport("gallery_plugin")] private static extern void OpenGallery(); public void OpenAndroidGallery() { OpenGallery(); } } ``` 在Unity中创建一个UI按钮,并将其连接到`OpenAndroidGallery`方法。这样,当我们点击按钮时,将调用本地插件的方法。 最后,将生成的Java类文件和C#脚本文件分别放在对应的目录中,并导出到Android项目中。 通过这种方式,我们可以在Unity调用Android相册,并允许用户选择图片。一旦用户选择了图片,可以使用Unity的处理方法进行后续操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值