2017-09-13 4 views
0

Ich schreibe für eine ziemlich schwierige (für mich) Problem. Schnell möchte ich alle installierten Apps auf dem Gerät (Icon und Label) bekommen. Ich verwende einen einfachen Code, der funktioniert, um den Namen der App zu erhalten. Ich verwende Android Java Class, um diese Informationen zu erhalten. Das Problem ist, dass Android App-Symbol als "Drawable" bezeichnet. Unity kann es nicht als Sprite lesen und anzeigen. Ich frage mich, ob es eine Möglichkeit gibt, dieses Problem zu lösen. Ich habe versucht, die Zeichenkette zu Base64-String zu codieren, aber Unity "antwortet" mir mit einem "Ungültige String-Länge" Fehler, vielleicht für die "unendliche" Länge der Base64-String. Ich versuche, die Drawable in ein Byte-Array zu konvertieren und dann verwenden, um eine Textur mit Texture.loadImage (Byte []) zu erstellen, aber es funktioniert nicht. Hier ist der Code:Get Android Installierte App Icon in Unity

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++; 
     } 

    } 

Hier ist die Java Android Studio arbeiten Code:

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

Vielen Dank für Hilfe.

+0

I Android Entwicklung nicht tun konnten aber nicht, dass Sie das Bitmap zu erhalten, um die Pixel aus dem Bitmap zu erhalten, und diese Pixel verwenden, um eine Textur zu erstellen in Einheit? Warum diese Pufferkonvertierung durchlaufen? – bpgeck

+0

Der Grund ist, dass es keine Möglichkeit gibt, dies mit Unity zu tun. Ich muss Android Java Class verwenden, um die Bitmap zu erhalten, und ich weiß nicht, wie ich Java-Code richtig von Unity aus aufrufen kann. –

+0

Ich gehe davon aus, dass Sie meinen, dass Unity nicht nativ mit Ihrer obigen Java-Funktionalität vergleichbar ist. In diesem Fall können Sie Ihren Code in Java schreiben, um Ihre rohen Farbwerte zu erhalten, und diese Funktion mit [AndroidJavaObject.Call] (https://docs.unity3d.com/ScriptReference/AndroidJavaObject.Call.html) aufrufen. – bpgeck

Antwort

0

Ich habe ein Android Jar Plugin auf Android Studio (keine Aktivität) erstellt und dann habe ich es in Unity3D importiert (AndroidManifest.xml und classes.jar in Assets> Plugins> Android> libs). Innerhalb des Plugins habe ich eine Klasse und dann die Leere hinzugefügt, um das Byte [] des Icons zu erhalten. Java Android Plugin Klasse:

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++; 
     } 

    } 

Vielen Dank für Hilfe