【问题标题】:How to get variables from AndroidJavaObject into a C# class using Unity3D如何使用 Unity3D 从 AndroidJavaObject 获取变量到 C# 类
【发布时间】:2015-11-02 17:22:54
【问题描述】:

我找不到如何在 C# 中从 AndroidJavaObject 获取 ListArray 变量。
我正在尝试使用CountListArray 中存储为AndroidJavaObject 的项目数创建for 函数。但我需要知道如何从AndroidJavaObject 获取Count 以及如何正确使用它。
这就是我用来获取变量的方法,还要注意“包”不是AndroidJavaObject[]

AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject currentActivity = jc.GetStatic<AndroidJavaObject>("currentActivity");
int flag = new AndroidJavaClass("android.content.pm.PackageManager").GetStatic<int>("GET_META_DATA");
AndroidJavaObject pm = currentActivity.Call<AndroidJavaObject>("getPackageManager");
AndroidJavaObject packages = pm.Call<AndroidJavaObject>("getInstalledApplications", flag);

目前还很初级,但感谢How to get installed apps list with Unity3D? 的一些帮助,它可以工作

到目前为止的进展在获取图标时停滞不前,其他一切都很完美,我需要一种方法来获取以某种方式链接到图标的 string,或者获取链接的 Texture2D图标。
另一种选择是使用包含drawableAndroidJavaObject,就好像它是一个Texture2D。我不知道如何完成这些。
我的另一个想法是将它转换为另一个变量,例如 byte[] 可以转移和转换回来,但我还没有找到一种方法在这种情况下工作。

int count = packages.Call<int>("size");
AndroidJavaObject[] links = new AndroidJavaObject[count];
string[] names = new string[count];
Texture2D[] icons = new Texture2D[count];
int ii =0;
for(int i=0; ii<count;){
    //get the object
    AndroidJavaObject currentObject = packages.Call<AndroidJavaObject>("get", ii );
    try{
        //try to add the variables to the next entry
        links[i] = pm.Call<AndroidJavaObject>("getLaunchIntentForPackage", currentObject.Get<AndroidJavaObject>("processName"));
        names[i] = pm.Call<string>("getApplicationLabel", currentObject);
        icons[i] = pm.Call<Texture2D>("getApplicationIcon", currentObject);
        Debug.Log ("(" + ii + ") " + i +" "+ names[i]);
        //go to the next app and entry
        i++;
        ii++;
    }
    catch
    {
        //if it fails, just go to the next app and try to add to that same entry.
        Debug.Log("skipped "+ ii);
        ii++;
    }

}

我真的很讨厌在这里连续问两个问题,我很抱歉不得不这样做,但这是一个困难且看似尴尬的情况,几乎没有文档(我可以找到)。

【问题讨论】:

    标签: java c# android arraylist unity3d


    【解决方案1】:

    首先,关于 Unity3D 和 Android 之间互操作的文档充其量是稀缺的。

    最重要的是,Unity 暴露给 java 对象工作的唯一接口是AndroidJavaObject,并且该接口只有几个方法defined。你只能使用那些,而且只能使用那些。

    这意味着您在使用 java 数组时不会获得 Count 对象,而您仍将使用 AndroidJavaObject

    int count = packages.Call<int>("size"); //getting the size of the array
    
    for( int i = 0; i < count; i++ )
    {
     //getting the object at location i
     AndroidJavaObject currentObject = packages.Call("get", i );
    
     //use currentObject using the same methods as before: Call, CallStatic, Get, GetStatic
    }
    

    我知道这很冗长,而且编写这样的代码很难测试,您需要制作和 apk 并将其部署到设备上以检查它是否运行。

    可能一种更快的方法是创建自己的 java 类,在 java 端完成所有这些工作,并公开一个从 Unity 端调用的方法。通过这种方式,您在制作将添加到Plugins/Android 文件夹中的 jar 时,至少可以获得静态类型的好处。

    【讨论】:

    • 不幸的是,您描述的获取计数的方法不起作用,我尝试获取并调用,静态和非,资本和非。在这一点上,我已经习惯了每次小改动后重新部署,哈哈。我不介意使用AndroidJavaObject,只要我得到我需要长期运行的变量。要做到这一点,我可能最终不得不进行一个不返回任何内容的调用,而是通过 java 将变量保存到我可以用 C# 解析的文件中,我还必须学习 java 和 Eclipse 之类的我几乎没有这两个方面的经验。我将编辑我的帖子以使用您的示例。
    • 我已经更新了我的答案,你需要调用的方法是size
    • 这似乎很完美,在获取变量时遇到/遇到了麻烦,必须通过pm.Call&lt;string&gt;("getApplicationLabel", currentObject) 来获得名称。我想我需要将链接字符串更改为AndroidJavaObject,这样我就可以存储一个启动意图,以便以后弄清楚如何使用something.Call("startActivity", intent)。我会更新这篇文章到目前为止的进展情况,如果你有任何想法,我会很高兴听到它们,但我必须在早上再次检查。
    • 更新了我的帖子,进步很大,在最后可能的事情上停滞不前。
    • 我会投正确的票,我放弃了,只是参加了 Java 速成课程,然后在 Android Studio 中完成。
    【解决方案2】:

    我在这里尝试做同样的事情,但我的启动器只能显示 CardBoard 应用程序。我决定用java制作一个库并将其作为插件导入Unity:

    这是我的 Java 类:

    public class Launcher extends UnityPlayerActivity {
    
    private List<ApplicationInfo> cbApps;
    
    @Override
    protected void onStart() {
        super.onStart();
    
        PackageManager pm= getPackageManager();
        List<ApplicationInfo> lista = pm.getInstalledApplications(PackageManager.GET_META_DATA);
        cbApps= new LinkedList<ApplicationInfo>();
    
        for(ApplicationInfo ai : lista){
            Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
            intentToResolve.addCategory("com.google.intent.category.CARDBOARD");
            intentToResolve.setPackage(ai.packageName);
            if(pm.resolveActivity(intentToResolve, 0)!=null) {
                cbApps.add(ai);
            }
        }
    }
    
    
    public int getListSize(){
        return cbApps.size();
    }
    

    这里是我的 C# 方法:

    void Start () {
        AndroidJavaClass unity = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
        AndroidJavaObject currentActivity = unity.GetStatic<AndroidJavaObject> ("currentActivity");
        texto.text=""+currentActivity.Call<int> ("getListSize");
    
    }
    

    这样,我可以在 Java 中创建访问列表所需的每个方法。我仍然遇到的问题是尝试获取图标的 Texture2D。我已经尝试从 Java 返回 Drawable 并像您一样使用 Call 进行访问,但它根本不起作用。我已经解决了 2 天,如果我找到解决方案,我会告诉你。

    编辑: 终于可以得到图片了:

    我首先在 Java 中创建了这个方法:

    public byte[] getIcon(int i) {
            BitmapDrawable icon= (BitmapDrawable)context.getPackageManager().getApplicationIcon(cbApps.get(i));
            Bitmap bmp = icon.getBitmap();
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
            byte[] byteArray = stream.toByteArray();
            return byteArray;
        }
    

    这样我就可以从 Unity 访问表示 Drawable 的 Byte 数组,并将其显示为平面的主要纹理:

    void Start () {
        using (AndroidJavaClass unity = new AndroidJavaClass ("com.unity3d.player.UnityPlayer")) {
            context = unity.GetStatic<AndroidJavaObject> ("currentActivity");
        }
        using (AndroidJavaClass pluginClass=new AndroidJavaClass("com.droiders.launcher.Launcher")) {
            launcher= pluginClass.CallStatic<AndroidJavaObject>("getInstance", context);
            byte[] bytes= launcher.Call<byte[]>("getIcon",0);
            Texture2D tex= new Texture2D(2,2);
            tex.LoadImage(bytes);
            plane.GetComponent<Renderer>().material.mainTexture=tex;
        }
    
    }
    

    希望对您有所帮助。这很难,但这只野兽已被驯服:P 也感谢大家的想法。

    【讨论】:

    • 如果您有新问题,请点击 按钮提出问题。如果有助于提供上下文,请包含指向此问题的链接。
    • 这不是一个新问题,他问了 2 个问题,我回答了第一个问题,但我告诉他我没有第二个问题的答案。不过谢谢,我会按照你的建议去做。
    • 是的,图标部分非常棘手。我知道如果你通过java将Drawable转换为图像字节数组,然后在C#中将字节数组转换为Texture2D,可以做到这一点,但我不知道该怎么做。而且我不知道是否有更简单和/或更有效的方法。老实说,通过 Android Studio 构建它可能更有效。
    • 是的,用 Java 可能会更容易,但我必须让我的启动器完全使用纸板,我想做一些我不知道如何做的其他东西用Java做。而且这是我第一次学习如何制作插件的好机会:P
    • 感谢字节数组的想法,我正在尝试
    猜你喜欢
    • 2014-08-16
    • 2020-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多