此方法采用U3D和ios和安卓交互方法完成 具体内容是U3D写出调用IOS和安卓方法 传递录像和照片的沙盒路径 存储由安卓和ios来完成 好了我们先上U3D代码
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
public class SelectPlatform : MonoBehaviour {
#if UNITY_ANDROID
///
/// Android平台接口
///
public static AndroidInterface android=new AndroidInterface();
#elif UNITY_IPHONE
///
/// IOS平台接口
///
public static IOSInterface ios=new IOSInterface();
#endif
///
/// 对Android或IOS接口进行调用
///
public static void SendMessage(string funName,string data)
{
#if UNITY_ANDROID
Type type = typeof(AndroidInterface);
type.GetMethod(funName).Invoke(android,new object[]{data});
#elif UNITY_IPHONE
Type type = typeof(IOSInterface);
type.GetMethod(funName).Invoke(ios,new object[]{data});
#endif
}
}
#if UNITY_ANDROID
using UnityEngine;
using System.Collections;
///
/// 安卓方法列表
///
public class AndroidInterface : AbstractClass {
///
/// 关闭U3D
///
///
public override void CloseUnity(string data)
{
Debug.Log("CloseUnity");
MyAndroidPlayer.SendMessage("CloseUnity", data);
}
///
/// 保存照片
///
///
public override void PreservationSPhoto(string data)
{
Debug.Log("PreservationSPhoto");
MyAndroidPlayer.SendMessage("PreservationSPhoto", data);
}
///
/// 保存录像
///
///
public override void PreservationSvideotape(string data)
{
Debug.Log("PreservationSvideotape");
MyAndroidPlayer.SendMessage("PreservationSvideotape", data);
}
}
#endif
using UnityEngine;
using System.Collections;
///
/// 方法列表
///
public abstract class AbstractClass {
///
/// 关闭U3D
///
///
public abstract void CloseUnity(string data);
///
/// 保存照片
///
///
public abstract void PreservationSPhoto(string data);
///
/// 保存录像
///
///
public abstract void PreservationSvideotape(string data);
}
using UnityEngine;
using System.Collections;
#if UNITY_ANDROID
public class MyAndroidPlayer : MonoBehaviour {
public delegate void ObtainMessageDelegate(string messageType, string message);
public static ObtainMessageDelegate ObtainMessage;
private static AndroidJavaClass androidJavaClass;
private static AndroidJavaObject androidJavaObject;
private char SEPARATOR = '~';
void Awake()
{
if (Application.platform != RuntimePlatform.Android) return;
androidJavaClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
androidJavaObject = androidJavaClass.GetStatic<AndroidJavaObject>("currentActivity");
// androidJavaObject = androidJavaObject.Get("functionUnity");
}
public static void SendMessage(string method, string msgArgs)
{
Debug.Log(method);
androidJavaObject.Call(method, new string[] { msgArgs });
}
}
#endif
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
using System;
public class IOSInterface : AbstractClass {
[DllImport("__Internal")]
private static extern void _CloseUnity(string wenwen);
public override void CloseUnity(string wenwen)
{
_CloseUnity(wenwen);
}
[DllImport("__Internal")]
private static extern void _PreservationSPhoto(string wenwen);
public override void PreservationSPhoto(string wenwen)
{
_PreservationSPhoto(wenwen);
}
[DllImport("__Internal")]
private static extern void _PreservationSvideotape(string wenwen);
public override void PreservationSvideotape(string wenwen)
{
_PreservationSvideotape(wenwen);
}
}
以上是我对调用ios 安卓方法做的一个小模块处理 然后我们在以后的项目里就很好的调用了 例如
public void CloseUnity()
{
SelectPlatform.SendMessage("CloseUnity", "退出U3D");
}
public void PreservationSPhoto(string data)
{
SelectPlatform.SendMessage("PreservationSPhoto",data);
}
public void PreservationSvideotape(string data)
{
SelectPlatform.SendMessage("PreservationSvideotape",data);
}
然后方法的参数 就是我们做完截屏和录屏的路径 截屏代码我就不提供了 百度一堆 录屏各种插件或者自己写 最后传递参数 例如 Debug.Log(“录像存储地址” + Application.persistentDataPath + “/” + filePath);
注意路径 Application.persistentDataPath
写好方法后 我们先来安卓 导出AS项目 这里说明一些 如果公司有安卓 ios程序最好 和他们沟通好接口
如果没有 就需要自己来写了 下面贴代码 找到 java里 UnityPlayerActivity
package com.itemjia.app.bandian;
import com.unity3d.player.*;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class UnityPlayerActivity extends Activity
{
private Context mContext;
protected UnityPlayer mUnityPlayer; // don't change the name of this variable; referenced from native code
public void CloseUnity(String data){
finish();
}
public void PreservationSvideotape(String msg){
File file1=new File(msg);
//获取ContentResolve对象,来操作插入视频
ContentResolver localContentResolver = this.getContentResolver();
//ContentValues:用于储存一些基本类型的键值对
ContentValues localContentValues = getVideoContentValues(this, file1, System.currentTimeMillis());
//insert语句负责插入一条新的纪录,如果插入成功则会返回这条记录的id,如果插入失败会返回-1。
Uri localUri = localContentResolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,localContentValues);
// Log.d(msg, "PreservationSPhoto: .");
}
public ContentValues getVideoContentValues(Context paramContext, File paramFile, long paramLong) {
ContentValues localContentValues = new ContentValues();
localContentValues.put("title", paramFile.getName());
localContentValues.put("_display_name", paramFile.getName());
localContentValues.put("mime_type", "video/3gp");
localContentValues.put("datetaken", Long.valueOf(paramLong));
localContentValues.put("date_modified", Long.valueOf(paramLong));
localContentValues.put("date_added", Long.valueOf(paramLong));
localContentValues.put("_data", paramFile.getAbsolutePath());
localContentValues.put("_size", Long.valueOf(paramFile.length()));
return localContentValues;
}
public void PreservationSPhoto(String msg){
saveImage(msg);
DeleteImage(msg);
}
//保存图片到相册
private void saveImage(String path) {
FileInputStream input = null;
try {
input = new FileInputStream(new File(path));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Bitmap bitmap = BitmapFactory.decodeStream(input);
String fileName = System.currentTimeMillis() + ".png";
ImgUtils.saveBitmap(bitmap, fileName, mContext);
}
private void DeleteImage(String imgPath) {
ContentResolver resolver = getContentResolver();
Cursor cursor = MediaStore.Images.Media.query(resolver, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[]{MediaStore.Images.Media._ID}, MediaStore.Images.Media.DATA + "=?",
new String[]{imgPath}, null);
boolean result = false;
if (cursor.moveToFirst()) {
long id = cursor.getLong(0);
Uri contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
Uri uri = ContentUris.withAppendedId(contentUri, id);
int count = getContentResolver().delete(uri, null, null);
result = count == 1;
} else {
File file = new File(imgPath);
result = file.delete();
}
}
// Setup activity layout
@Override protected void onCreate(Bundle savedInstanceState)
{
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
mContext = this;
mUnityPlayer = new UnityPlayer(this);
setContentView(mUnityPlayer);
mUnityPlayer.requestFocus();
}
@Override protected void onNewIntent(Intent intent)
{
// To support deep linking, we need to make sure that the client can get access to
// the last sent intent. The clients access this through a JNI api that allows them
// to get the intent set on launch. To update that after launch we have to manually
// replace the intent with the one caught here.
setIntent(intent);
}
// Quit Unity
@Override protected void onDestroy ()
{
mUnityPlayer.destroy();
super.onDestroy();
}
// Pause Unity
@Override protected void onPause()
{
super.onPause();
mUnityPlayer.pause();
}
// Resume Unity
@Override protected void onResume()
{
super.onResume();
mUnityPlayer.resume();
}
@Override protected void onStart()
{
super.onStart();
mUnityPlayer.start();
}
@Override protected void onStop()
{
super.onStop();
mUnityPlayer.stop();
}
// Low Memory Unity
@Override public void onLowMemory()
{
super.onLowMemory();
mUnityPlayer.lowMemory();
}
// Trim Memory Unity
@Override public void onTrimMemory(int level)
{
super.onTrimMemory(level);
if (level == TRIM_MEMORY_RUNNING_CRITICAL)
{
mUnityPlayer.lowMemory();
}
}
// This ensures the layout will be correct.
@Override public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
mUnityPlayer.configurationChanged(newConfig);
}
// Notify Unity of the focus change.
@Override public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
mUnityPlayer.windowFocusChanged(hasFocus);
}
// For some reason the multiple keyevent type is not supported by the ndk.
// Force event injection by overriding dispatchKeyEvent().
@Override public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
return mUnityPlayer.injectEvent(event);
return super.dispatchKeyEvent(event);
}
// Pass any events not handled by (unfocused) views straight to UnityPlayer
@Override public boolean onKeyUp(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
@Override public boolean onTouchEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
/*API12*/ public boolean onGenericMotionEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
}
新建一个 .java代码 ImgUtils
package com.itemjia.app.bandian;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class ImgUtils {
/*
* 保存文件,文件名为当前日期
*/
public static void saveBitmap(Bitmap bitmap, String bitName,Context context) {
String fileName;
File file;
if (Build.BRAND.equals("xiaomi")) { // 小米手机
fileName = Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera/" + bitName;
}else if (Build.BRAND.equals("Huawei")){
fileName = Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera/" + bitName;
} else { // Meizu 、Oppo
fileName = Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + bitName;
}
file = new File(fileName);
if (file.exists()) {
file.delete();
}
FileOutputStream out;
try {
out = new FileOutputStream(file);
// 格式为 JPEG,照相机拍出的图片为JPEG格式的,PNG格式的不能显示在相册中
if (bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out)) {
out.flush();
out.close();
// 插入图库
MediaStore.Images.Media.insertImage(context.getContentResolver(), file.getAbsolutePath(), bitName, null);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// 发送广播,通知刷新图库的显示
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + fileName)));
}
}
安卓代码完成 下面来做IOS 如果你写了接口 就必须实现 不然会报错 新创建一个.h文件 就叫 u3dmanage.h吧
//
// u3dmanage.h
// Unity-iPhone
//
// Created by Gy on 2020/4/26.
//
@interface u3dmanage : NSObject
void _CloseUnity(char*msg);
void _PreservationSPhoto(char*msg);
void _PreservationSvideotape(char*msg);
@end
#ifndef u3dmanage_h
#define u3dmanage_h
#endif /* u3dmanage_h */
这个是接口 在写实现代码
创建一个 .m文件 u3dmanage.m
//
// u3dmanage.m
// Unity-iPhone
//
// Created by Gy on 2020/4/27.
//
#import "u3dmanage.h"
@interface u3dmanage ();
@end
@implementation u3dmanage
void _CloseUnity(char* msg){
NSString *string1 = [[NSString alloc] initWithUTF8String:msg];
NSString *string2 = [[NSString alloc] initWithUTF8String:msg];
NSLog(@"###%@", [NSString stringWithFormat:@"%@ %@", string1, string2]);
}
void _PreservationSPhoto(char* msg){
NSString *string1 = [[NSString alloc] initWithUTF8String:msg];
NSString *string2 = [[NSString alloc] initWithUTF8String:msg];
NSString *strReadAddr = [NSString stringWithUTF8String:msg];
UIImage *img = [UIImage imageWithContentsOfFile:strReadAddr];
NSLog([NSString stringWithFormat:@"w:%f, h:%f", img.size.width,img.size.height]);
u3dmanage *instance = [u3dmanage alloc];
UIImageWriteToSavedPhotosAlbum(img, instance,
@selector(imageSaved:didFinishSavingWithError:contextInfo:), nil);
NSLog(@"###%@", [NSString stringWithFormat:@"%@ %@", string1, string2]);
}
void _PreservationSvideotape(char* msg){
NSString *strReadAddr = [NSString stringWithUTF8String:msg];
u3dmanage *instance = [u3dmanage alloc];
UISaveVideoAtPathToSavedPhotosAlbum(strReadAddr, instance, nil, nil);
}
+ (void) savedVedioImage:(UIImage*)image didFinishSavingWithError: (NSError *)error contextInfo: (void *)contextInfo {
NSString* result;
if (error) {
result =@"视频保存失败";
}
else {
result =@"保存视频成功";
}
// UnitySendMessage( "MainScriptHolder", "SaveVedioToPhotosAlbumCallBack", result.UTF8String);
}
- ( void ) imageSaved: ( UIImage *) image didFinishSavingWithError:( NSError *)error
contextInfo: ( void *) contextInfo
{
NSLog(@"保存结束");
if (error != nil) {
NSLog(@"有错误");
}
}
@end
最后测试 录像和截屏完美存储系统相册