2017-09-13 218 views
0

我正在寫一個相當困難的(對我來說)問題。 快速地,我想要獲取設備中的所有已安裝的應用程序(圖標和標籤)。我正在使用一個簡單的代碼來獲取應用程序的名稱。我使用Android Java Class來獲取這些信息。問題在於Android將應用程序圖標視爲「可繪製」。 Unity無法讀取並顯示爲Sprite。我想知道是否有辦法解決這個問題。我試圖將drawable編碼爲base64字符串,但Unity以「無效字符串長度」錯誤回覆我,可能是base64字符串的「無限」長度。我試圖將Drawable轉換爲一個字節數組,然後使用它創建一個Texture.loadImage(byte [])的紋理,但它不起作用。 下面是代碼:在Unity中獲取Android安裝的應用程序圖標

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工作室工作代碼:

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

感謝您的幫助。

+0

我不這樣做Android開發的,但不能你得到的位圖,得到位圖的像素,並使用這些像素創建紋理統一?爲什麼要經歷這個緩衝區轉換? – bpgeck

+0

原因是沒有辦法使用Unity,我必須使用Android Java Class來獲取位圖,並且我不知道如何從Unity中正確調用Java代碼。 –

+0

我假設你的意思是Unity本身並不具備與上述Java功能等效的功能。在這種情況下,您可以使用Java編寫代碼來獲取原始顏色值並使用[AndroidJavaObject.Call](https://docs.unity3d.com/ScriptReference/AndroidJavaObject.Call.html)調用該函數。 – bpgeck

回答

0

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

    } 

感謝您的幫助

相關問題