Unity调用安卓相册并支持多选图片
当在Unity中开发Android应用时,有时需要使用安卓设备的相册功能,以便用户可以选择并上传图片。本篇博客将介绍如何在Unity中调用安卓相册,并支持多选图片。
本来用AndroidStudio打出个aar的包来着,但是老是闪退,没有找到原因,就只能直接调java脚本了。
我Unity版本是2022.1.23;
首先,我们需要创建一个安卓插件,用于在Unity中调用安卓相册功能。在Unity中创建一个C#脚本,命名为ImagePicker.cs,代码如下:
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
public class ImagePicker : MonoBehaviour
{
// 直接拖过来button和按钮上的image
public Button btn;
AndroidJavaObject jo;
public Button getImage;
private void Awake()
{
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
btn.onClick.AddListener(() => {
CallAndroid(123456);
});
getImage.onClick.AddListener(() =>
{
CallAndroid(123666);
});
}
/// <summary>
/// CALL>>>ANDROID>>>打开相册
/// </summary>
void CallAndroid(int num)
{
jo.Call("startPhoto", num);
}
/// <summary>
/// 给Android调用的方法
/// </summary>
/// <param name="str"></param>
public void CallUnity(string str)
{
string[] path = str.Split(',');
jo.Call("CallAndroid", string.Format("图片Address>>>>" + str));
}
public void CallUnityImage(string str)
{
jo.Call("CallAndroid", string.Format("背景图片Address>>>>" + str));
}
}
上述代码定义了一个ImagePicker
类,其中btn
和ImageView
是Unity场景中的按钮和图片组件。Awake
方法初始化了AndroidJavaObject实例,用于与安卓代码进行交互。CallAndroid
方法用于调用安卓相册功能,CallUnity
和CallUnityImage
方法是供安卓代码调用的回调方法,用于在Unity中显示图片。
切记:此C#脚本一定要挂载到java脚本中所传输的物体名的物体上。
接下来,我们需要在安卓环境中创建一个Java类,用于处理相册相关的功能。在安卓项目中创建一个名为MainActivity的类,代码如下:
// 这里是一段安卓代码,用于调用相册和获取选中的图片路径
// 代码中涉及到权限申请、相册调用和获取图片路径的操作
package com.pub.dou;
import android.Manifest;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.widget.Toast;
import android.app.Activity;
import java.net.URI;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;
public class MainActivity extends UnityPlayerActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 获取存储权限,否则无法获取图片
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 100);
}
}
// Unity点击按钮触发这个方法
public void startPhoto(int result) {
Log.d("unity", "打开相册");
Intent intent = null;
if (result == 123456) {
intent = new Intent(Intent.ACTION_GET_CONTENT);
} else if (result == 123666) {
intent = new Intent(Intent.ACTION_GET_CONTENT);
}
intent.setType("image/*");
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(intent, result); // 第二个参数是请求码
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case 123456: // 请求码
Log.d("Unity", "相册返回");
UnityPlayer.UnitySendMessage("Main Camera", "CallUnity", GetManyPath(data));
break;
case 123666: // 请求码
Log.d("Unity", "相册返回");
UnityPlayer.UnitySendMessage("Main Camera", "CallUnityImage", GetManyPath(data));
break;
}
}
}
public String GetManyPath(Intent data) {
Uri[] imageUris = null;
if (data.getClipData() != null) {
int count = data.getClipData().getItemCount();
imageUris = new Uri[count];
for (int i = 0; i < count; i++) {
imageUris[i] = data.getClipData().getItemAt(i).getUri();
}
} else if (data.getData() != null) {
imageUris = new Uri[]{data.getData()};
}
if (imageUris != null) {
StringBuilder uriString = new StringBuilder();
for (Uri uri : imageUris) {
String imagePath;
Cursor cursor = getContentResolver()
.query(uri, new String[]{MediaStore.Images.ImageColumns.DATA},
null, null, null);
if (cursor == null) {
imagePath = uri.getPath();
} else {
cursor.moveToFirst();
int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
imagePath = cursor.getString(index);
cursor.close();
}
uriString.append(imagePath).append(",");
}
if (uriString.length() > 0) {
uriString.deleteCharAt(uriString.length() - 1);
}
return uriString.toString();
}
return null;
}
// 让Unity调用的方法
public void CallAndroid(String Msg) {
Toast.makeText(MainActivity.this, Msg, Toast.LENGTH_SHORT).show();
}
}
上述代码中的MainActivity
类继承自UnityPlayerActivity
,并重写了onCreate
和onActivityResult
方法。在onCreate
方法中,首先调用requestPermissions
方法申请存储权限。在startPhoto
方法中,根据传入的result
参数决定打开相册的类型。在onActivityResult
方法中,根据请求码和结果码处理相册返回的数据,并使用UnityPlayer.UnitySendMessage
方法将图片路径传递给Unity。
切记:例如UnityPlayer.UnitySendMessage(“Main Camera”, “CallUnityImage”, GetManyPath(data)); 此处的Main Camera 是Unity中挂在调用按照脚本的物体名!CallUnityImage是Main Camera物体下脚本中的回参方法。
对了还有AndroidManifest.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.pub.dou">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true">
<activity android:name="com.pub.dou.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
// 和unity交互需要加这一句
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
</application>
</manifest>
MainActivity.java文件与AndroidManifest.xml文件要放在下图位置:
这就可以调起相册进行多个选择啦。
这三个脚本我放在这里了有需要的可以自取。Unity调用安卓相册进行多选