admin 管理员组文章数量: 887016
Unity调用android相册获取图片或视频
(此文章对有unity基础和对环境配置有基础的童嚡容易看懂)
因为项目上用到,在百度了很多大佬的文章后,陆陆续续踩了很多坑,可能是我哪里设置的不对,大部分都没成功,后面捣鼓捣鼓着就出来了,如有哪里不对,还请各位大佬多多指教,下面进入正题
创建一个unity项目,设置unity的包名(例:com.公司名.项目包名)
在assets路径下创建一个Plugins文件夹,这个文件夹一般用来放置需要调用的dll文件,然后在Plugins路径下创建一个Android文件夹(为后面放置aar文件使用),代码后面一起添加。
我是用的AndroidStudio3.5.2版本,安装Android Studio及环境配置教程比较多,就直接带过,打开Android studio,新建项目
然后点击Next下一步
然后点击finish完成,项目构建中,需要几秒钟完成后的出现这个窗口
不用理会,直接Close掉就可以了,创建完成,显示是这样的
然后点击Android图标切换样式,选择Project模式
选完后如下图
打开src文件夹下的main,里面有项目自带的类MyActivity,可以删掉自己建,但我个人比较懒,缩直接修改自带的,打开myactivity然后删掉里面的方法,复制下面的代码到myactivity类中(直接在网上复制了其他博主的,手动狗头)
package com.Companys.Test;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import com.unity3d.player.UnityPlayerActivity;
public class MainActivity extends UnityPlayerActivity{
private static String LOG_TAG = "LOG_My";
Context mContext = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = this;
}
//Unity中会调用这个方法,用于打开本地相册
public void TakePhoto(String str)
{
Log.d(LOG_TAG,str);
Intent intent = new Intent(mContext,WebViewActivity.class);
this.startActivity(intent);
}
}
TakePhoto这个方法要在unity里面调用的,可以改为自己喜欢的名称,不过在android中改了,在unity也要修改,否则无法调用,复制完后如下
注意第一行的Package包名不用复制,每个人的对应自己建的包名就可以了,复制完后你会发现报错了,这是因为类里面引用unity的类,但这个引用为空,这时就要导入一个jar引用,类似于unity里的dll一样,这个jar文件在unity的安装目录下,要注意你当前创建的unity项目所使用的版本,不是那个版本都可以,我用的是2018.3.8版本,路径为Unity2018.3.8\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes下有个Class.jar,将这个jar文件复制一份,放到刚刚android的项目文件libs文件夹下,如下图
放置完后,文件就在libs文件夹中,但你会发现代码还是报错的,因为还需要再设置下,选中class.jar,然后右键选择Add as Library,如下图
添加后,你会发现很多的报错都没了,但还有一个地方报错,那是因为有个被调用的类不存在,我们直接创建就好了,选中MyActivity所在的文件夹,然后右键New—Java Class,创建一个java类,类名为WebViewActivity,创建完后报错信息就没了,修改WebViewActivity类,将下面的代码复制到WebViewActivity类中,选择图片或视频都在这里,仔细看呦
package com.Companys.Test;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import com.unity3d.player.UnityPlayer;
import java.io.IOException;
//import android.view.KeyEvent;
public class WebViewActivity extends Activity
{
public static final int NONE = 0;
public static final int PHOTORESOULT = 3;
public static final String IMAGE_UNSPECIFIED = "video/*"/*;"image/*"*/;//划重点,这里指定视频或图片
private String LOG_TAG = "LOG_ZDQ";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(Intent.ACTION_PICK, null);
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_UNSPECIFIED);
startActivityForResult(intent, PHOTORESOULT);
Log.d(LOG_TAG, "打开相册!");
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(LOG_TAG, "resultCode :" + resultCode);
if (resultCode == NONE)
{
if (data == null)
{
this.finish();
UnityPlayer.UnitySendMessage("InputURL","GetPhoto","");
}else
{
if(this.isFinishing() == false)
{
this.finish();
}
UnityPlayer.UnitySendMessage("InputURL","GetPhoto","");
}
return;
}
if (data == null)
{
this.finish();
UnityPlayer.UnitySendMessage("InputURL","GetPhoto","");
}
ContentResolver resolver = getContentResolver();
Bitmap bm=null;
Uri originalUri = data.getData();
try {
bm = MediaStore.Images.Media.getBitmap(resolver, originalUri);
} catch (IOException e) {
e.printStackTrace();
}
String[] proj = {MediaStore.Images.Media.DATA};
Cursor cursor= getContentResolver().query(originalUri,proj,null,null,null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
String _path = cursor.getString(column_index);
UnityPlayer.UnitySendMessage("InputURL", "GetPhoto", _path);
super.onActivityResult(requestCode, resultCode, data);
this.finish();
}
}
有个地方注意下,代码块中有个 “InputURL”,找不到可以复制这个然后按F12查找,这个名称是你在unity里面挂载脚本的物体名称,后面unity模块会提下。
然后不需要再修改当前app目录文件夹下其他文件,直接右键当前的总项目名称,选择New-----Module,新建一个Module
选择Android Library样式,点击Next下一步
然后点击finish完成,等几秒钟就可以编译完成,然后将app里的刚才修改和新建的脚本拷贝到新建的android library中的同样路径下
然后也同样将class.jar文件也拷贝到libs文件夹中,然后右键选择add as library,默认点确定就可以了,不用改啥,完成后是这样
然后找到新建library中的AndroidManifest.xml,打开进行修改
<manifest xmlns:android="http://schemas.android/apk/res/android"
package="com.Companys.Test" >
<!--读取相册权限 (必须)-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application >
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".WebViewActivity">
</activity>
</application>
</manifest>
将上面的代码复制到xml中,注意不要复制包名,这是我的包名,如果你的包名和我不一样,不要复制包名…
然后找到build.gradle,如图
双击打开它进行修改(其实这我也不知道要不要修改,因为这是打jar包中的设置,而我这是打aar包…狗头)
在
task makejar(type: Copy){
//delete 'libs/test.jar'
from('build/intermediates/packaged-classes/release/')//这个路径应该已经改了,反正我的是没有
into('libs')
include('classes.jar')
rename('classes.jar','FarmGetAndroidPhoto.jar')
}
makejar.dependsOn(build)
改完后找到总项目结构目录下的gradle.properties文件,然后双击进行修改,如图
找到org.gradle.jvmargs这句,后面的xms可能不一样,但改它就对了,将这行代码注释掉,直接这行开头添加#号就可以了,然后保存下,接着打开androidstudio的安装目录,看看你Android Studio\bin下的studio.exe.vmoptions还是studio64.exe.vmoptions,然后打开进行修改,长这个样子的,直接对应着改就可以了
-Xms2048m
-Xmx2048m
-XX:ReservedCodeCacheSize=2048m
编辑完以后就基本上完成了,然后选择菜单栏里的Build选项下的Rebuild project,如图
点击Rebuild project后等待一会,等构建完后打开项目目录节点下的build文件夹,子文件夹outputs,里面有个aar文件夹,下面就是已经打包好的aar文件,如图
然后将这个aar文件和图中圈住的xml一起复制出来,接下来是unity篇了,先将这两个文件放到之前unity里面建好的Plugins/android下面,然后编辑这两个文件。
首先是xml文件,将xml的application<中添加打包后的包名,之前一直被这里坑>,设置完后保存关掉
然后用压缩工具打开aar文件,这里面的相对复杂点,首先将libs下的class.jar文件删除掉,因为这个是重复的
然后将androidmanifest.xml也删掉,外面已经有一个了
然后再双击打开这包里面的class.jar,找到最下级目录,删掉BuildConfig.class,这个在unity打包时会起冲突的,改完后然后关掉就好了,然后就是关于unity去掉用android部分了,看下面代码
using UnityEngine;
using System.IO;
using UnityEngine.UI;
using System.Collections;
using UnityEngine.Networking;
using UnityEngine.Video;
using UnityEngine.Android;
public class GetAndroidPhoto : MonoBehaviour
{
public Button button;
public RawImage rawImage;
void Start ()
{
button.onClick.AddListener(OpenLibery);
Permission.RequestUserPermission(Permission.ExternalStorageRead);
Permission.RequestUserPermission(Permission.ExternalStorageWrite);
}
private void OpenLibery()
{
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
jo.Call("TakePhoto", Application.persistentDataPath);
}
public void GetPhoto(string path)
{
Debug.Log("android give path ==> " + path);
FileGetTex(path);
}
private void FileGetTex(string path)
{
FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);
fileStream.Seek(0, SeekOrigin.Begin);
byte[] bye = new byte[fileStream.Length];
fileStream.Read(bye, 0, bye.Length);
fileStream.Close();
Texture2D texture2D = new Texture2D((int)rawImage.rectTransform.rect.width, (int)rawImage.rectTransform.rect.height);
texture2D.LoadImage(bye);
rawImage.texture = texture2D;
}
public IEnumerator DownloadTexture(string url, RawImage rawImage)//这些都可以
{
using (UnityWebRequest request = UnityWebRequestTexture.GetTexture("file://" + url))
{
yield return request.SendWebRequest();
if (request.error == null)
{
Texture2D texture = (request.downloadHandler as DownloadHandlerTexture).texture;
rawImage.texture = texture;
}
}
}
}
复制完代码后,将脚本拖到场景中指定的物体上,上面有提到过的呦,跟java代码里的名称设置一至才能调用
放置完后,创建canvas这些就不写,将脚本需要拖拽赋予的都放上去就KO了,然后就可以打包了,这里还有坑,那就是打包设置的Build System必须要设置为Gradle模式,否则会打包失败,而且即使选了也不一定能打包。。。。。,因为Gradle模式打包需要下载一些包,而软件本身的下载路径为国外的,所以你懂得,首先直接找到Unity2018.3.8\Unity2018\Editor\Data\PlaybackEngines\AndroidPlayer\Tools\GradleTemplates路径,路径下有三个gradle后缀文件,都打开,然后找到有repositories块的就在里面添加下面这行代码
maven{ url 'http://maven.aliyun/nexus/content/repositories/central/'}
改完后再用Gradle模式打包,基本就KO了,测试打开相册KO,其实打开相册选图片和视频都一样,都是返回路径,然后unity里根据路径去获取,所以要相册的读写权限,可能不一定所有都成功,我的是2018.3.8版就KO,第一次写,有点渣,请见谅…狗头
生活不易,且行且珍惜,让自己每天过的充实些
如需转载请注明出处,码字也不易,谢谢!
版权声明:本文标题:Unity调用android相册获取图片或视频 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1726386237h950179.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论