繁体   English   中英

如何在 Unity 中获取 Android 安装的应用程序图标

[英]How to get Android Installed App Icon in Unity

很快,我想获取设备中所有已安装的应用程序(图标和标签)。 我正在使用一个简单的代码来获取应用程序的名称。

我使用 Android Java Class 来获取这些信息。 问题是 Android 选择应用程序图标作为Drawable Unity 无法读取并将其显示为Sprite

我想知道是否有办法解决这个问题。 我试图将 drawable 编码为 base64 字符串,但 Unity“回复”了我“无效的字符串长度”错误,可能是因为 base64 字符串的“无限”长度。

我正在尝试将 Drawable 转换为字节数组,然后使用它来创建带有Texture.loadImage(byte[])的纹理,但它不起作用。 这是代码:

 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);

    int count = packages.Call<int>("size");
    string[] names = new string[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
            names[i] = pm.Call<string>("getApplicationLabel", currentObject);
            AndroidJavaObject icon = pm.Call<AndroidJavaObject>("getApplicationIcon", currentObject);//this part is the Java (Android Studio) code using Android Java Object and Class of Unity. Maybe the error is from here
            AndroidJavaObject bitmap = icon.Call<AndroidJavaObject>("getBitmap");
            AndroidJavaClass stream = new AndroidJavaClass("java.io.ByteArrayOutputStream");
            bitmap.Call("compress",(new AndroidJavaClass("java.io.ByteArrayOutputStream")).Call<AndroidJavaObject>("JPEG"), 100, stream);
            byte[] bitMapData = stream.Call<byte[]>("toByteArray");//to here
            Texture2D mytexture = new Texture2D(50, 50); // no idea what default size would be?? is it important??
            if (!mytexture.LoadImage(bitMapData)) {
                Debug.Log("Failed loading image data!");
            }
            else {
                Debug.Log("LoadImage - Still sane here - size: " + mytexture.width + "x" + mytexture.height);
                GameObject app = (GameObject)Instantiate(App, Vector3.zero, Quaternion.identity);
                app.GetComponent<RawImage>().texture = mytexture;//here is the code should display the icon as texture (sprite would be the best)
            }
            i++;
            ii++;
        }
        catch(Exception e){
            Debug.LogError(e,this);
                //if it fails, just go to the next app and try to add to that same entry.
            ii++;
        }

    }

这里有 Java Android Studio 工作代码:

        Bitmap bitmap = ((BitmapDrawable) item.getIcon()).getBitmap(); //item.getIcon() returns the Drawable correctly
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
        byte[] byteArray = baos.toByteArray();

我在 Android Studio(无活动)上创建了一个 Android Jar 插件,然后我将它导入到 Unity3D(AndroidManifest.xml 和 classes.jar 在 Assets>Plugins>Android>libs 中)。 在插件中,我添加了一个类,然后添加了 void 来获取图标的字节 []。 Java Android 插件类:

public class PluginClass {

public static byte[] getIcon(PackageManager pm, ApplicationInfo applicationInfo) {
    try {
        BitmapDrawable icon = (BitmapDrawable) pm.getApplicationIcon(applicationInfo);
        Bitmap bmp = icon.getBitmap();
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
        byte[] byteArray = stream.toByteArray();
        return byteArray;
    } catch (Exception e) {
        return null;
    }
}

public static boolean isSystem(ApplicationInfo applicationInfo){
    return (applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM ) != 0;
   }
}
Then I have invoked it in Unity C# script:

void Start () {
    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", 0);
    int count = packages.Call<int>("size");
    string[] names = new string[count];
    List<byte[]> byteimg = new List<byte[]>();
    int ii =0;
    for(int i=0; ii<count;){
        AndroidJavaObject currentObject = packages.Call<AndroidJavaObject>("get", ii );
        try{
            names[i] = pm.Call<string>("getApplicationLabel", currentObject);
            var plugin = new AndroidJavaClass("com.mypackagename.PluginClass");
            if(plugin.CallStatic<bool>("isSystem",currentObject)){
                ii++;
                continue;
            }
            byte[] decodedBytes = plugin.CallStatic<byte[]>("getIcon", pm, currentObject);
            Texture2D text = new Texture2D(1, 1, TextureFormat.ARGB32, false);
            text.LoadImage(decodedBytes);
            Sprite sprite = Sprite.Create (text, new Rect(0,0,text.width,text.height), new Vector2(.5f,.5f));
            i++;
            ii++;
        }
        catch(Exception e){
            Debug.LogError(e,this);
            ii++;
        }

    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM