网络知识 娱乐 Unity与Android的简单交互,Unity打开Android相册并调用(Unity2019以后)

Unity与Android的简单交互,Unity打开Android相册并调用(Unity2019以后)

在开发安卓软件的时候,Unity和Android之间的交互是非常有必要的,使用Android调用Unity相对来说比较简单,然而用Unity调用Android却是非常麻烦的事,这对于一个Android小白的我来说却是无比头大的,在网上我们能找到各种各样的Unity调用Android的方法,不过大同小异,无非都是AndroidStudio导出.jar/.aar包,看起来都没有什么问题,然而,自己照搬过来却总是花样报错。本人也是被受AndroidStudio的折磨。(Unity2019以后与Android的交互,从此告别.aar和.jar)

优势:

1.不要需要导包,告别.aar和.jar

2.打包不需要大量设置,名字随便填

3.方法简单易懂

准备:Unity2019及以后版本的Unity

废话不多说,我们直接上方法

一,Unity与Android的交互

1.新建两个txt文件,将它们分别命名为MainActivity和Androidmanifest

2. 将下面的脚本代码复制到txt文本中去

MainActivity

package com.pub.dou;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.widget.Toast;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;

public class MainActivity extends UnityPlayerActivity  {

    public String MName="Dou";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
    //让Unity调用的方法
    public String CallAndroid()
    {
        String Msg="HELLO UNITY, This is android";
        Toast.makeText(MainActivity.this, Msg, Toast.LENGTH_SHORT).show();
        return Msg;
    }
    //让Unity调用的方法
    public void ShowToast(Context context, String Msg)
    {
        Toast.makeText(context, Msg, Toast.LENGTH_SHORT).show();
    }
    public void ShowName()
    {
        //调用Unity上物体Canvas上的callunity方法,MName是参数
        UnityPlayer.UnitySendMessage("Canvas", "callunity",MName);
    }

    //需要调用什么都在这个MainActivity类里面写就好了,一些需要引用的别忘了在前面添加
    

}

package的名字可以自己随便写一个自己喜欢的就行,只要在Androidmanifest中做出相应的修改进行,不过不建议修改,因为这不会对自己Build apk设置有任何影响的。

Androidmanifest


    
   
        
            
                
                
            
            // 调用Unity
            
        
    
    // 需要的权限,也可以Unity上UnityEngine.Android里面弄
    
    

3.修改上面两个文本的后缀名

至此,Android方面的工作暂时是完成了,接下来就是Unity了。 

4.打开Unity,随便创建一个新的项目,并将平台设置成Android。

5.新建文件夹Plugins/Android,并将上面改好名字的两个文件放置在Android文件夹下。

6.创建Canvas,并在Canvas下创建三个按钮,分别改名字为CallAndroid、ShowToast和ShowName(改名字和调用Android没直接联系,主要是我的编码习惯,方便使用)。

 7.新建一个C#脚本,并添加在Canvas上,代码如下:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Test : MonoBehaviour
{
    private Button[] btns;
    AndroidJavaObject jo;
    AndroidJavaObject context;

    public Text tex;
    private string str;
    private void Start()
    {
        Init();
       
        btns = transform.GetComponentsInChildren

8.新建一个text,拖拽到脚本上,用于显示Android调用Unity。

9.打包,随便设置一下公司名和产品名,开始Build。

10.使用安卓设备安装刚刚打包好的apk,运行 。下面是我的运行结果(按钮从上至下):

 

 二,调用Android相册并获取

1.在网上找到unity调用Android相册获取路径的代码。

2.将代码整合到MainActivity里面(先将后缀名改为txt,整合后再改回来,也可以直接使用Java的编译工具打开MainActivity.java,Androidmanifest.xml需要添加权限),代码如下:

MainActivity.java

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 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() {
        Log.d("unity","打开相册");
        Intent intent = new Intent(Intent.ACTION_PICK);
        intent.setType("image/*");
        startActivityForResult(intent, 123456);  // 第二个参数是请求码
    }

    @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", GetPath(data));
                    break;
            }
        }
    }


    public String GetPath(Intent data) {
        Uri uri = data.getData();
        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();
        }
        return imagePath;  // 返回图片地址
    }


    //让Unity调用的方法
    public void CallAndroid(String Msg)
    {

        Toast.makeText(MainActivity.this, Msg, Toast.LENGTH_SHORT).show();

    }


}


Androidmanifest.xml




    
        
            
                

                
            
            // 和unity交互需要加这一句
            
        
    
    // 获取权限
    
    

3.新建场景,创建Canvas并创建一个Test脚本挂在Main Camera上(别忘了将准备好的Android文件放置到Android目录下)。

 4.Test脚本代码如下:

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public class Test : MonoBehaviour
{
    // 直接拖过来button和按钮上的image
    public Button btn;
    public Image ImageView;
    AndroidJavaObject jo;
    private void Awake()
    {
        AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        jo = jc.GetStatic("currentActivity");
        btn.onClick.AddListener(CallAndroid);
    }
    /// 
    /// CALL>>>ANDROID>>>打开相册
    /// 
    void CallAndroid()
    {
        jo.Call("startPhoto");
    }
    /// 
    /// 给Android调用的
    /// 
    /// 
    public void CallUnity(string str)
    {
        ShowImage(str);
        jo.Call("CallAndroid", string.Format("图片Address>>>>" + str));

        //string path = "file://"  + str;
        //StartCoroutine(LoadTexturePreview(path));
    }
    //使用www方式获取图片
    IEnumerator LoadTexturePreview(string path)
    {
        UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(path);
        yield return uwr.SendWebRequest();
        Debug.Log("图片地址:" + path);
        if (uwr.isNetworkError || uwr.isHttpError)
        {
            Debug.Log("错误" + uwr.error);
        }
        else
        {
            Texture2D texture = DownloadHandlerTexture.GetContent(uwr);
            // 图片显示在按钮上
            Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(.5f, .5f));
            ImageView.sprite = sprite;
        }
    }
    //使用文件流读取图片
    private void ShowImage(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, (int)bye.Length);
        fileStream.Close();
        fileStream.Dispose();
        fileStream = null;

        Texture2D texture = new Texture2D(100,50);
        texture.LoadImage(bye);
        Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
        ImageView.sprite = sprite;
        // Destroy(texture,4);
    }





}

至于为什么没有使用WWW的方式获取图片,主要是这种方式不知道为啥速度特别慢,至少要3秒,而且模拟器上能用,真机上却会报错:HTTP1.1 404,知道原因的请告诉我。

5.在Canvas下添加一个button和一个Image,拖拽至脚本。

6.打包收工。运行结果如下: 

代码思路大概是这样:Unity.Button>>>Android.打开相册>>>Android.获取选中图片>>>Android.处理>>>Android.图片路径>>>CallUnity>>>Unity.读取>>>Unity.贴图