Skip to content

I created a script to support Meta Quest 3 and Android Phone! #345

@VR-Jobs

Description

@VR-Jobs

this script is a OnGUI script to support Android phone and VR Meta Quest 3, very useful!

Image

using System.Collections;
using UnityEngine;

public class AndroidImagePicker : MonoBehaviour
{
    [Header("Settings")]
    public int maxImageSize = 1024;
    public string albumName = "MyApp";

    // GUI 相关变量
    private string statusMessage = "点击按钮选择图片";
    private Texture2D currentTexture;
    private Vector2 scrollPosition = Vector2.zero;

    // GUI 样式
    private GUIStyle buttonStyle;
    private GUIStyle labelStyle;
    private GUIStyle boxStyle;
    private bool stylesInitialized = false;

    void Start()
    {
        // 初始化状态信息
        statusMessage = "点击按钮选择图片";
    }

    void OnGUI()
    {
        // 初始化GUI样式
        if (!stylesInitialized)
        {
            InitializeGUIStyles();
            stylesInitialized = true;
        }

        // 开始滚动视图
        scrollPosition = GUILayout.BeginScrollView(scrollPosition);

        // 主容器
        GUILayout.BeginVertical(boxStyle);

        // 标题
        GUILayout.Label("Android 图片选择器", labelStyle);
        GUILayout.Space(10);

        // 状态显示
        GUILayout.BeginHorizontal();
        GUILayout.Label("状态: ", GUILayout.Width(50));
        GUILayout.Label(statusMessage);
        GUILayout.EndHorizontal();
        GUILayout.Space(10);

        // 选择多张图片按钮
        if (GUILayout.Button("选择图片", buttonStyle, GUILayout.Height(50)))
        {
            PickMultipleImages();
        }
        GUILayout.Space(10);

        // 保存按钮(如果有当前图片的话)
        if (currentTexture != null)
        {
            if (GUILayout.Button("保存图片到相册", buttonStyle, GUILayout.Height(35)))
            {
                SaveImageToGallery();
            }
            GUILayout.Space(10);
        }

        // 图片显示区域
        if (currentTexture != null)
        {
            GUILayout.Label("选择的图片:", labelStyle);
            GUILayout.Space(5);

            // 计算显示尺寸,保持宽高比
            float maxDisplayWidth = Screen.width - 40;
            float maxDisplayHeight = Screen.height * 0.4f;

            float aspectRatio = (float)currentTexture.width / currentTexture.height;
            float displayWidth, displayHeight;

            if (aspectRatio > 1) // 横图
            {
                displayWidth = Mathf.Min(maxDisplayWidth, currentTexture.width);
                displayHeight = displayWidth / aspectRatio;
            }
            else // 竖图或正方形
            {
                displayHeight = Mathf.Min(maxDisplayHeight, currentTexture.height);
                displayWidth = displayHeight * aspectRatio;
            }

            // 居中显示图片
            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            GUILayout.Label(currentTexture, GUILayout.Width(displayWidth), GUILayout.Height(displayHeight));
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();

            GUILayout.Space(10);

            // 图片信息
            GUILayout.Label($"图片尺寸: {currentTexture.width} x {currentTexture.height}", labelStyle);
        }

        GUILayout.Space(20);

        // 设置区域
        GUILayout.Label("设置:", labelStyle);

        GUILayout.BeginHorizontal();
        GUILayout.Label("最大图片尺寸:", GUILayout.Width(100));
        string maxSizeStr = GUILayout.TextField(maxImageSize.ToString(), GUILayout.Width(100));
        if (int.TryParse(maxSizeStr, out int newMaxSize))
        {
            maxImageSize = newMaxSize;
        }
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal();
        GUILayout.Label("相册名称:", GUILayout.Width(100));
        albumName = GUILayout.TextField(albumName, GUILayout.Width(150));
        GUILayout.EndHorizontal();

        GUILayout.EndVertical();

        // 结束滚动视图
        GUILayout.EndScrollView();
    }

    /// <summary>
    /// 初始化GUI样式
    /// </summary>
    private void InitializeGUIStyles()
    {
        // 按钮样式
        buttonStyle = new GUIStyle(GUI.skin.button);
        buttonStyle.fontSize = 16;
        buttonStyle.fontStyle = FontStyle.Bold;

        // 标签样式
        labelStyle = new GUIStyle(GUI.skin.label);
        labelStyle.fontSize = 14;
        labelStyle.fontStyle = FontStyle.Bold;

        // 框体样式
        boxStyle = new GUIStyle(GUI.skin.box);
        boxStyle.padding = new RectOffset(10, 10, 10, 10);
    }

    /// <summary>
    /// 选择多张图片(Android 18+,iOS 14+支持)
    /// </summary>
    public void PickMultipleImages()
    {
        // 检查是否已经在选择媒体文件
        if (NativeGallery.IsMediaPickerBusy())
        {
            UpdateStatus("正在选择图片,请稍候...");
            return;
        }

        // 检查设备是否支持多选
        if (!NativeGallery.CanSelectMultipleFilesFromGallery())
        {
            UpdateStatus("当前设备不支持选择多张图片");
            return;
        }

        // 检查权限
        CheckPermissionAndPickImages();
    }

    /// <summary>
    /// 检查权限并选择图片
    /// </summary>
    private void CheckPermissionAndPickImages()
    {
        bool hasPermission = NativeGallery.CheckPermission(NativeGallery.PermissionType.Read, NativeGallery.MediaType.Image);

        if (hasPermission)
        {
            // 有权限,直接选择图片
            PickImages();
        }
        else
        {
            // 需要请求权限
            UpdateStatus("请求权限中...");
            NativeGallery.RequestPermissionAsync(OnPermissionResult, NativeGallery.PermissionType.Read, NativeGallery.MediaType.Image);
        }
    }

    /// <summary>
    /// 权限请求结果回调
    /// </summary>
    /// <param name="permission">权限结果</param>
    private void OnPermissionResult(NativeGallery.Permission permission)
    {
        if (permission == NativeGallery.Permission.Granted)
        {
            UpdateStatus("权限获取成功!");
            PickImages();
        }
        else
        {
            UpdateStatus("权限被拒绝,无法访问相册");

            if (permission == NativeGallery.Permission.Denied)
            {
                // 权限被永久拒绝,提示用户去设置中开启
                UpdateStatus("权限被永久拒绝,请在设置中手动开启相册权限");
            }
        }
    }

    /// <summary>
    /// 执行选择图片操作
    /// </summary>
    private void PickImages()
    {
        UpdateStatus("正在打开相册选择多张图片...");

        NativeGallery.GetImagesFromGallery((paths) =>
        {
            if (paths != null && paths.Length > 0)
            {
                UpdateStatus($"选择了 {paths.Length} 张图片");

                // 输出选择的多张图片
                for (int i = 0; i < paths.Length; i++)
                {
                    Debug.Log($"图片 {i + 1}: {paths[i]}");
                }

                // 显示第一张图片
                if (paths.Length > 0)
                {
                    LoadAndDisplayImage(paths[0]);
                }
            }
            else
            {
                UpdateStatus("已取消选择图片");
            }
        }, "选择图片", "image/*");
    }

    /// <summary>
    /// 加载并显示选择的图片
    /// </summary>
    /// <param name="imagePath">图片路径</param>
    private void LoadAndDisplayImage(string imagePath)
    {
        // 释放之前的纹理以避免内存泄漏
        if (currentTexture != null)
        {
            Destroy(currentTexture);
            currentTexture = null;
        }

        // 从路径加载图片
        currentTexture = NativeGallery.LoadImageAtPath(imagePath, maxImageSize, false, true, false);

        if (currentTexture != null)
        {
            UpdateStatus($"图片加载成功!尺寸: {currentTexture.width}x{currentTexture.height}");

            // 可选:获取图片属性
            GetImageProperties(imagePath);
        }
        else
        {
            UpdateStatus("图片加载失败");
            Debug.LogError("无法从路径加载纹理: " + imagePath);
        }
    }

    /// <summary>
    /// 保存当前图片到相册(可选功能)
    /// </summary>
    public void SaveImageToGallery()
    {
        if (currentTexture == null)
        {
            UpdateStatus("没有图片可保存");
            return;
        }

        UpdateStatus("正在保存图片到相册...");

        NativeGallery.SaveImageToGallery(currentTexture, albumName, "SavedImage.png", (success, path) =>
        {
            if (success)
            {
                UpdateStatus("图片保存成功!路径: " + path);
                Debug.Log("图片保存成功: " + path);
            }
            else
            {
                UpdateStatus("图片保存失败");
                Debug.LogError("图片保存失败");
            }
        });
    }

    /// <summary>
    /// 更新状态文本
    /// </summary>
    /// <param name="message">状态信息</param>
    private void UpdateStatus(string message)
    {
        statusMessage = message;
        Debug.Log("状态: " + message);
    }

    /// <summary>
    /// 获取图片属性信息(可选功能)
    /// </summary>
    /// <param name="imagePath">图片路径</param>
    private void GetImageProperties(string imagePath)
    {
        NativeGallery.ImageProperties properties = NativeGallery.GetImageProperties(imagePath);

        if (properties.width > 0 && properties.height > 0)
        {
            Debug.Log($"图片属性 - 宽度: {properties.width}, 高度: {properties.height}, MIME类型: {properties.mimeType}, 方向: {properties.orientation}");
        }
        else
        {
            Debug.Log("无法获取图片属性");
        }
    }

    /// <summary>
    /// 清理资源
    /// </summary>
    void OnDestroy()
    {
        if (currentTexture != null)
        {
            Destroy(currentTexture);
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions