Unity llama a la interfaz de Android para obtener la lista de aplicaciones

I. Introducción

        Encapsule y obtenga la interfaz de la lista de aplicaciones en Android Studio, incluido el ícono de la aplicación, el nombre de la aplicación y el nombre del paquete de la aplicación, etc., y exporte el paquete AAR para que Unity lo llame; Unity llama a la interfaz encapsulada dentro de AAR a través del script C# y muestra la aplicación. listar a través de UGUI.gestionar.

2. Paquete de funciones interactivas de Android

        Utilice Android Studio para encapsular la interfaz de llamada relacionada con la obtención de la lista de aplicaciones en un paquete AAR para llamadas posteriores de Unity.

1. Crea un nuevo proyecto de Android

        No entraré en detalles aquí, consulte: Uso de Android WebView

2. Crea un módulo

         No entraré en detalles aquí, consulte: Uso de Android WebView

3. Creación de clases Java

(1) Crear una clase de llamada a método

        Esta clase se utiliza para crear un método para que Unity lo llame, el código específico es el siguiente:

import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.provider.Settings;

import java.util.ArrayList;
import java.util.List;

public class ObtainApplicationListUtils {
    private final String tag = "ObtainApplicationListUtils";
    private Context mContext;
    private PackageManager packageManager;
    private static ObtainApplicationListUtils mObtainApplicationListUtils = null;

    public ObtainApplicationListUtils(Context context) {
        this.mContext = context;
        packageManager = mContext.getPackageManager();
    }


    public static ObtainApplicationListUtils getInstance(Context context){
        if (mObtainApplicationListUtils == null) {
            mObtainApplicationListUtils = new ObtainApplicationListUtils(context);
        }
        return mObtainApplicationListUtils;
    }

    //获取所有应用列表
    public List<AppInfo> getAllApplicationList(boolean isFilterSystem){
        List<AppInfo> allAppInfoList = new ArrayList<>();
        if(allAppInfoList != null){
            allAppInfoList.clear();
        }
        AppInfo appInfo = null;

        List<PackageInfo> packageInfoList = packageManager.getInstalledPackages(0);
        for(PackageInfo packageInfo : packageInfoList){
            appInfo = new AppInfo();
            appInfo.setAppName(packageManager.getApplicationLabel(packageInfo.applicationInfo).toString());
            appInfo.setPackageName(packageInfo.applicationInfo.packageName);
            appInfo.setAppIcon(AppIconConverter.getAppIcon(packageInfo,packageManager));
            int flags = packageInfo.applicationInfo.flags;
            //判断是否是属于系统的应用,过滤系统应用
            if((flags & ApplicationInfo.FLAG_SYSTEM) != 0 && isFilterSystem){

            }
            else{
                allAppInfoList.add(appInfo);
            }
        }
        
        return allAppInfoList;
    }

    //获取特定应用列表
    public List<AppInfo> getSpecificApplicationList(boolean isFilterSystem){
        List<AppInfo> specificAppInfoList = new ArrayList<>();
        if(specificAppInfoList != null){
            specificAppInfoList.clear();
        }

        AppInfo appInfo = null;

        List<PackageInfo> packageInfoList = packageManager.getInstalledPackages(0);
        for(PackageInfo packageInfo : packageInfoList){
            appInfo = new AppInfo();
            appInfo.setAppName(packageManager.getApplicationLabel(packageInfo.applicationInfo).toString());
            appInfo.setPackageName(packageInfo.applicationInfo.packageName);
            appInfo.setAppIcon(AppIconConverter.getAppIcon(packageInfo,packageManager));
            int flags = packageInfo.applicationInfo.flags;
            //判断是否是属于系统的应用,过滤系统应用
            if((flags & ApplicationInfo.FLAG_SYSTEM) != 0 && isFilterSystem){

            }
            else{
                //过滤其他应用,只保留指定包名格式的应用
                if(appInfo.getPackageName().contains("被保留应用的包名前两部分,即com.xx")){
                    specificAppInfoList.add(appInfo);
                }
            }
        }

        return specificAppInfoList;
    }

    //通过包名打开应用
    public void startApp(String packageName) {
        try {
            Intent intent = packageManager.getLaunchIntentForPackage(packageName);
            mContext.startActivity(intent);
        } catch (Exception exception) {}
    }

    //打开系统设置
    public void openSystemSettings(){
        try {
            Intent intent = new Intent(Settings.ACTION_SETTINGS);
            mContext.startActivity(intent);
        }catch (Exception exception){}
    }
}

(2) Cree una clase de conversión de íconos de aplicaciones

        Después de obtener el ícono de la aplicación, obtendrá los datos en formato Drawable, que debe convertirse en un mapa de bits y luego convertirse nuevamente en una matriz de bytes para llamadas posteriores de Unity. Notas para la adquisición de íconos: Android obtiene información de la aplicación por nombre del paquete y abre la aplicación

import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;

import java.io.ByteArrayOutputStream;

public class AppIconConverter {

    //获取应用图标
    public static byte[] getAppIcon(PackageInfo packageInfo,PackageManager packageManager){
        try{
            Drawable drawable;
            drawable = packageInfo.applicationInfo.loadIcon(packageManager);
            Bitmap bitmap = drawableToBitmap(drawable);
            byte[] appIcon;
            appIcon = bitmapToByte(bitmap);
            return appIcon;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    //Drawable转Bitmap
    private static Bitmap drawableToBitmap(Drawable drawable){
        //取drawable的长宽
        int width = drawable.getIntrinsicWidth();
        int height = drawable.getIntrinsicHeight();
        //取drawable的颜色格式
        Bitmap.Config config = Bitmap.Config.ARGB_8888;
        //创建对应Bitmap
        Bitmap bitmap = Bitmap.createBitmap(width,height,config);
        //建立对应Bitmap的画布
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0,0,width,height);
        //把drawable内容画到画布中
        drawable.draw(canvas);
        return bitmap;
    }

    //Bitmap转Byte
    private static byte[] bitmapToByte(Bitmap bitmap){
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
        return stream.toByteArray();
    }
}

(3) Crear una clase de almacenamiento de información de la aplicación

        Se utiliza para guardar información como el nombre de la aplicación, el nombre del paquete y el icono.

public class AppInfo {
    public String appName;    //应用名称
    public String packageName;//应用包名
    public byte[] appIcon;    //应用图标,这里以字节数组形式存储,便于Unity端进行解析

    public AppInfo(){
        appName = "";
        packageName = "";
        appIcon = null;
    }

    public void setAppName(String _appName){
        this.appName = _appName;
    }

    public void setPackageName(String _packageName){
        this.packageName = _packageName;
    }
    public String getPackageName(){
        return this.packageName;
    }

    public void setAppIcon(byte[] _appIcon){
        this.appIcon = _appIcon;
    }
}

4. Configuración del archivo AndroidManifest.xml

        Agregue un permiso para evitar el acceso incompleto a la aplicación, de la siguiente manera:

<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>

5. Modifique la variable de compilación para liberar

        Haga clic en Generar-->Seleccionar variante de compilación... y seleccione la variante de compilación del módulo como versión en la interfaz abierta.

6. Procesamiento de ofuscación de paquetes AAR

(1) modificación de build.gradle

        En el módulo, busque y abra el archivo build.gradle y modifique minifyEnabled del bloque de lanzamiento en buildTypes a verdadero. 

(2) Modificación de archivos confusa

        En el módulo, busque y abra el archivo proguard-rules.pro y escriba lo siguiente:

-keep class 包名.ObtainApplicationListUtils{public <methods>;}
-keepclasseswithmembers class 包名.AppInfo{<fields>;}

        La primera línea indica que los métodos públicos de la clase ObtainApplicationListUtils no están ofuscados y la segunda línea indica que los miembros (variables) de la clase AppInfo no están ofuscados. Todos estos se llaman del lado de Unity.

7. Cree el paquete AAR

        Seleccione el módulo, haga clic en Construir-->Crear módulo, o directamente Construir-->Reconstruir proyecto.

        Una vez completada la compilación, el paquete AAR compilado se puede encontrar en el módulo -->build-->outputs-->aar.

3. Llamado a la unidad

1. Colocación del paquete AAR

        Arrastre y suelte el paquete AAR directamente en Activos de Unity-->Complementos-->ruta de Android.

2. Cree un script C# y llame al paquete AAR.

(1) Clase de llamada

        Escriba el siguiente contenido para llamar a la interfaz de función en el paquete AAR.

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

public class ObtainApplicationListManager : MonoBehaviour
{
    public GameObject appItemPrefab;//每一个应用信息预制件
    public Transform[] appListParent; //应用列表父物体

    private AndroidJavaObject getApplicationListUtils;
    private List<AppInfo> appInfoLists = new List<AppInfo>();

    //应用信息结构体
    public struct AppInfo
    {
        public string appName;
        public string packageName;
        public byte[] appIcon;

        public AppInfo(string _appName,string _packageName,byte[] _appIcon)
        {
            appName = "";
            packageName = "";
            appIcon = null;
        }

        public void SetAppName(string _appName)
        {
            appName = _appName;
        }

        public void SetPackageName(string _packageName)
        {
            packageName = _packageName;
        }

        public void SetAppIcon(byte[] _appIcon)
        {
            appIcon = _appIcon;
        }
    }

    private void Awake()
    {
        AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
        AndroidJavaClass getApplicationListUtilsClass = new AndroidJavaClass("包名.ObtainApplicationListUtils");
        getApplicationListUtils = getApplicationListUtilsClass.CallStatic<AndroidJavaObject>("getInstance", currentActivity);
    }
    // Start is called before the first frame update
    void Start()
    {
        //开始默认设置所有应用列表
        SetAllApplicationList();
    }

    IEnumerator AppListSpawn(int action)
    {
        yield return 0;

        //查找已存在的应用列表,若有,销毁
        GameObject[] apps;
        apps = GameObject.FindGameObjectsWithTag("App");
        if (apps != null)
        {
            for(int i = 0; i < apps.Length; i++)
            {
                Destroy(apps[i]);
            }
            apps = null;
        }

        //在UI界面展示应用列表
        for (int i = 0; i < appInfoLists.Count; i++)
        {
            int index = i;//对于每一个i重新开辟内存空间,在按钮添加委托事件时防止自动闭包
            
            //生成应用UI
            GameObject app = Instantiate(appItemPrefab);
            app.tag = "App";
            app.transform.SetParent(appListParent[action]);
            app.transform.localScale = Vector3.one;

            //设置应用信息
            var appItem = app.GetComponent<AppItem>();
            if (appItem != null)
            {
                //设置应用名称
                appItem.appNameText.text = appInfoLists[i].appName;
                //设置应用图标
                Texture2D texture2D = new Texture2D(100, 100);
                texture2D.LoadImage(appInfoLists[i].appIcon);
                appItem.appIcon.texture = texture2D;
                
                //设置应用图标点击事件,打开自身
                appItem.openAppButton.onClick.AddListener(delegate ()
                {
                    OpenApplication(appInfoLists[index].packageName);
                });
            }
        }
    }

    /// <summary>
    /// 获取除系统应用以外的所有应用列表
    /// </summary>
    /// <param name="isFilterSystem"> 是否过滤系统应用 </param>
    /// <returns></returns>
    public List<AppInfo> GetAllApplicationList(bool isFilterSystem)
    {
        AndroidJavaObject[] appInfoList = getApplicationListUtils.Call<AndroidJavaObject>("getAllApplicationList", isFilterSystem).Call<AndroidJavaObject[]>("toArray");
        List<AppInfo> appInfos = new List<AppInfo>();
        foreach(AndroidJavaObject obj in appInfoList)
        {
            appInfos.Add(UnpackAppInfoObj(obj));
        }
        return appInfos;
    }

    /// <summary>
    /// 获取除系统应用以外的指定应用列表
    /// </summary>
    /// <param name="isFilterSystem"> 是否过滤系统应用 </param>
    /// <returns></returns>
    public List<AppInfo> GetSpecificApplicationList(bool isFilterSystem)
    {
        AndroidJavaObject[] appInfoList = getApplicationListUtils.Call<AndroidJavaObject>("getSpecificApplicationList", isFilterSystem).Call<AndroidJavaObject[]>("toArray");
        List<AppInfo> appInfos = new List<AppInfo>();
        foreach (AndroidJavaObject obj in appInfoList)
        {
            appInfos.Add(UnpackAppInfoObj(obj));
        }
        return appInfos;
    }

    /// <summary>
    /// 应用信息赋值
    /// </summary>
    /// <param name="appInfoObj"> 安卓端AppInfo </param>
    /// <returns></returns>
    private AppInfo UnpackAppInfoObj(AndroidJavaObject appInfoObj)
    {
        AppInfo appInfo = new AppInfo();
        appInfo.SetAppName(appInfoObj.Get<string>("appName"));
        appInfo.SetPackageName(appInfoObj.Get<string>("packageName"));
        appInfo.SetAppIcon(appInfoObj.Get<byte[]>("appIcon"));
        return appInfo;
    }

    /// <summary>
    /// 打开应用
    /// </summary>
    /// <param name="packageName"> 应用包名 </param>
    public void OpenApplication(string packageName)
    {
        getApplicationListUtils.Call("startApp", packageName);
    }

    /// <summary>
    /// 设置除系统应用以外的所有应用列表
    /// </summary>
    public void SetAllApplicationList()
    {
        //获取应用列表
        appInfoLists = GetAllApplicationList(true);

        //在UI界面展示应用列表
        StartCoroutine(AppListSpawn(0));
    }

    /// <summary>
    /// 设置除系统应用以外的指定应用列表
    /// </summary>
    public void SetSpecificApplicationList()
    {
        //获取应用列表
        appInfoLists = GetSpecificApplicationList(true);

        //在UI界面展示应用列表
        StartCoroutine(AppListSpawn(1));
    }

    /// <summary>
    /// 打开系统设置
    /// </summary>
    public void OpenSystemSettings()
    {
        getApplicationListUtils.Call("openSystemSettings");
    }

    /// <summary>
    /// 退出
    /// </summary>
    public void ExitApp()
    {
        Application.Quit();
    }
}

(2) clase de información de UI

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

public class AppItem : MonoBehaviour
{
    public Text appNameText;    //应用名称显示文本
    public Button openAppButton;//打开应用按钮
    public RawImage appIcon;    //应用图标
}

(3) Clase de inicialización del control deslizante

        En este caso, habrá dos partes de la Vista para mostrar todas las aplicaciones y la aplicación con el nombre del paquete especificado. Para evitar que el control deslizante dentro de una de las Vistas se muestre nuevamente después de que se muestra la otra Vista, el control deslizante no se muestra en la posición superior al principio debido al problema de la operación de deslizamiento anterior, inicialice su posición aquí, de la siguiente manera:

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

public class ScrollbarInitialize : MonoBehaviour
{
    //public Scrollbar scrollbar;
    public RectTransform rectTransform;

    private void OnEnable()
    {
        //scrollbar.value = 0;
        rectTransform.anchoredPosition = new Vector2(rectTransform.anchoredPosition.x, 0);
    }
}

3. Diseño UGUI

(1) Descripción general del diseño

        El diseño de la interfaz de usuario contiene dos Toggles, que se utilizan para llamar a los métodos SetAllApplicationList y SetSpecificApplicationList en el script ObtainApplicationListManager respectivamente para mostrar todas las aplicaciones y aplicaciones con nombres de paquetes específicos;

        Dos vistas de desplazamiento, como objeto principal de la lista de aplicaciones generada;

        Un botón de salida que llama al método ExitApp en el script ObtainApplicationListManager;

        Un botón de configuración del sistema que llama al método OpenSystemSettings en el script ObtainApplicationListManager para abrir la configuración del sistema Android.

        El diseño de la interfaz de usuario se muestra en la siguiente figura:

(2) Alternar configuración

        Cree un objeto vacío y monte el componente Toggle Group, como se muestra a continuación:

        Puede configurar la visualización de la imagen del componente Alternar, como resaltar cuando se hace clic. Asigne un valor al grupo Toggle anterior y llame al método de ejecución en el componente Toggle, como se muestra en la siguiente figura. 

        El componente Imagen del Fondo está configurado como una imagen no resaltada, de modo que cuando se haga clic en otros Toggles, dejará de resaltarse de acuerdo con la configuración en el cambio de imagen del componente Toggle. 

        El subobjeto Marca de verificación del Fondo se mostrará cuando se seleccione su propio Alternar, así que configure la imagen de su componente Imagen como una imagen resaltada. 

(3) Configuración de vista de desplazamiento

        Desmarque la opción Horizontal de Scroll Rect y elimine la barra de desplazamiento horizontal debajo de ella. Monte el componente de script ScrollbarInitialize y asigne el contenido que contiene a la variable RectTransform. 

        Monte el componente Grupo de diseño de cuadrícula y el componente Ajustador de tamaño de contenido en el objeto Contenido debajo de él, establezca el Tamaño de celda, el espaciado y la alineación secundaria del componente Grupo de diseño de cuadrícula de acuerdo con las necesidades reales y establezca el Ajuste vertical del componente Ajustador de tamaño de contenido. 

4. Cambie a la plataforma Android, empaquete apk, instálelo y pruebe

4. Entrada de descarga de recursos del paquete AAR

        Si algunos amigos no saben cómo empaquetar después de leer el tutorial anterior, pueden descargar directamente el siguiente paquete AAR y usarlo directamente: contiene el nombre del paquete del complemento, simplemente reemplace el "nombre del paquete" en el script ObtenerApplicationListManager.

        Obtenga el paquete de complementos AAR de la lista de aplicaciones en el lado de Android

Supongo que te gusta

Origin blog.csdn.net/qq_40364278/article/details/132171465
Recomendado
Clasificación