Unity3d实现拍照功能(截图形式、调取安卓相机)


一、以截图形式实现拍照功能:

使用(NGUI)UITexture或者(UGUI)RawImage显示截图,必须提前在场景中创建。

该脚本实现功能:仿照相机界面,竖屏显示,包括返回键、取消键、确认键。

Unity在不调取移动端的情况下实现拍照功能,就必须有WebCamTexture类,如果不理解,请查看博文,

链接:http://blog.csdn.net/it_yanghui/article/details/78615209


下面附上代码:

TakePhoto(以截图形式实现拍照功能)

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

public class TakePhoto: TakePhotoBase {

    private UIButton[] _btnArr;
    private UIButton _backBtn;
    private UIButton _ensureBtn;
    private UIButton _cancelBtn;
    private UITexture cameraTexture;            //相机画面(需要提前创建(NGUI)UITexture或者(UGUI)RawImage,用来显示截图)
    private WebCamTexture webCameraTexture;     //相机贴图(无需赋值)
    private byte[] bts = null;
    private string photoName = string.Empty;	//用于保存本地使用
    protected override void OnAwake()
    {
        base.OnAwake();
        if (null == _instance)
            _instance = this;
    }
    protected override void OnStart()
    {
        base.OnStart();
        Init();
        photoName = "touxiang";
    }
    void Init()
    {
        //设置屏幕正方向在Home键左边
        Director.GetInstance.SetGameScreenAutoRotation(ScreenOrientation.LandscapeLeft);
        if (null == cameraTexture)
            cameraTexture = GetComponentInChildren<UITexture>();
        _btnArr = GetComponentsInChildren<UIButton>();
        for (int i= 0; i < _btnArr.Length; i++)
        {
            InitBtn(_btnArr[i]);
            UIEventListener.Get(_btnArr[i].gameObject).onClick = delegate (GameObject go)
              {
                  ClickCallBack(go);
              };
        }
        ShowBtnCtr(true, false);//显示返回按钮
        StartCoroutine(StartCamera());//开启相机
    }
    //初始化按钮
    private void InitBtn(UIButton btn)
    {
        switch (btn.name)
        {
            case "Btn_Back":
                _backBtn = btn;
                break;
            case "Btn_Ensure":
                _ensureBtn = btn;
                break;
            case "Btn_Cancel":
                _cancelBtn = btn;
                break;
            default:
                break;
        }
    }
    private void ClickCallBack(GameObject go)
    {
        string btnName = go.name;
        switch (btnName)
        {
            case "Btn_TakePhoto":
                StartCoroutine(GetTexture());//截图
                ShowBtnCtr(false, true);//显示确认按钮
                break;
            case "Btn_Back":
                CloseCamera();
                break;
            case "Btn_Ensure":
                string str1 = "file";
                if (bts != null)
                    StartCoroutine(ServiceMgr.GetInstance.UploadingTexture(Global_Game.postUrl_FileUploading, str1, bts));//上传截图(或者其他操作)
                break;
            case "Btn_Cancel":
                if (bts != null)
                    bts = null;
                if (webCameraTexture != null)
                {
                    webCameraTexture.Play();
                }
                else
                {
                    StartCoroutine(StartCamera());
                }
                ShowBtnCtr(true, false);//显示返回按钮
                break;
            default:
                break;
        }
    }
    IEnumerator StartCamera()//调用移动端相机
    {
        int maxl = Screen.width;
        if (Screen.height > Screen.width) { maxl = Screen.height; }
        yield return Application.RequestUserAuthorization(UserAuthorization.WebCam);
        if (Application.HasUserAuthorization(UserAuthorization.WebCam))
        {
            WebCamDevice[] devices = WebCamTexture.devices;
            string devicename = devices[0].name;
            webCameraTexture = new WebCamTexture(devicename, maxl, maxl, 12);
            webCameraTexture.wrapMode = TextureWrapMode.Repeat;
            cameraTexture.mainTexture = webCameraTexture;
            webCameraTexture.Play();
        }
    }

    IEnumerator GetTexture()//获取截图
    {
        yield return new WaitForEndOfFrame();
        Texture2D tex = new Texture2D(cameraTexture.width, cameraTexture.height, TextureFormat.RGB24, false);
        tex.ReadPixels(new Rect(0, 0, cameraTexture.width, cameraTexture.height), 0, 0, true);
        tex.Apply();
        byte[] bt = tex.EncodeToPNG();
        bts = new byte[bt.Length];
        bts = bt;
        webCameraTexture.Stop();
    }

    /// <summary>
    /// 关闭相机画面
    /// </summary>
    public void CloseCamera()
    {
        if(webCameraTexture != null)
            webCameraTexture.Stop();
        //设置屏幕可以左右旋转
        Director.GetInstance.SetGameScreenAutoRotation(ScreenOrientation.AutoRotation);
    }
    /// <summary>
    /// 控制按钮显示或隐藏
    /// </summary>
    /// <param name="backBtnIsShow"></param>
    /// <param name="otherIsShow"></param>
    private void ShowBtnCtr(bool backBtnIsShow ,bool otherIsShow)
    {
        if (null == _backBtn || null == _ensureBtn || null == _cancelBtn)
            return;
        _backBtn.gameObject.SetActive(backBtnIsShow);
        _ensureBtn.gameObject.SetActive(otherIsShow);
        _cancelBtn.gameObject.SetActive(otherIsShow);
    }
}


二、调取Andriod相机实现拍照功能

注意:1.android包名要和unity保持一致   
            2.unitygameobjectName要对应    
            3.须将unity下的classes.jar拷贝至安卓工程libs下方可正确编译再导出为jar包,
classes.jar 地址:

在Unity安装路径Editor下:在Unity图标右键点击打开文件位置,找到以下路径classes.jar 包,

Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes


建立工程之后,要将res下layout文件下.xml文件删除,因为不需要使用安卓布局。

详细介绍(包括打包导出jar包):之前博文:Unity5与Android交互通信(使用Android Studio2.4)

链接:http://blog.csdn.net/it_yanghui/article/details/78490599

安卓代码:MainActivity.java

package com.xxx.xxx; //对应unity的包名

import android.content.ContentResolver;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;

import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class MainActivity extends UnityPlayerActivity {

    private static final String TAG = MainActivity.class.getSimpleName();
    private static final int PHOTO_REQUEST_CODE = 1;//相册
    public static final int PHOTOHRAPH = 2;// 拍照
    private static final boolean DEBUG = false;
    private String unitygameobjectName = "PersonInfo"; //Unity 中对应挂脚本对象的名称
    public static final int NONE = 0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

//强制设置屏幕方向(根据自己需要)
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }

    //调用相机
    public void takephoto(){

        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "temp.jpg")));
        startActivityForResult(intent, PHOTOHRAPH);
    }


    //调用相册
    public void OpenGallery()
    {
        Intent intent = new Intent(Intent.ACTION_PICK,null);
        intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,"image/*");
        startActivityForResult(intent, PHOTO_REQUEST_CODE);
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // TODO Auto-generated method stub
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == NONE){
            return;
        }
        if(PHOTO_REQUEST_CODE == requestCode){//相册
            if(data == null){
                return;
            }
            Uri uri = data.getData();
            String imagePath = getImagePath(uri);
            if(DEBUG){
                Log.d(TAG, imagePath);
            }
            //调用unity中方法 GetImagePath(imagePath)
            UnityPlayer.UnitySendMessage(unitygameobjectName, "GetImagePath", imagePath);
        }

        if (requestCode == PHOTOHRAPH) {//相机
            String path = Environment.getExternalStorageDirectory() + "/temp.jpg";
            if(DEBUG){
                Log.e("path:", path);
            }
            //调用unity中方法 GetImagePath(path)
            UnityPlayer.UnitySendMessage(unitygameobjectName, "GetImagePath", path);
            try {
                Bitmap bitmap = BitmapFactory.decodeFile(path);
                SaveBitmap(bitmap);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private String getImagePath(Uri uri)
    {
        if(null == uri) return null;
        String path = null;
        final String scheme = uri.getScheme();
        if (null == scheme) {
            path = uri.getPath();
        } else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
            path = uri.getPath();
        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
            String[] proj = { MediaStore.Images.Media.DATA };
            Cursor cursor = getContentResolver().query(uri, proj, null, null,
                    null);
            int nPhotoColumn = cursor
                    .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            if (null != cursor) {
                cursor.moveToFirst();
                path = cursor.getString(nPhotoColumn);
            }
            cursor.close();
        }
        return path;
    }

    public void SaveBitmap(Bitmap bitmap) throws IOException {

        FileOutputStream fOut = null;
        String path = "/mnt/sdcard/DCIM/";
        try {
            //查看这个路径是否存在,
            //如果并没有这个路径,
            //创建这个路径
            File destDir = new File(path);
            if (!destDir.exists())
            {
                destDir.mkdirs();
            }
            String FILE_NAME = System.currentTimeMillis() + ".jpg";
            fOut = new FileOutputStream(path + "/" + FILE_NAME) ;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        //将Bitmap对象写入本地路径中
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
        try {
            fOut.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            fOut.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


AndroidManifest.xml:该文件下不能有注释,拷贝代码后,把注释删掉。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xxx.xxx"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-sdk
        android:minSdkVersion="15"
        android:targetSdkVersion="23" />
    <application
        android:allowBackup="true"
        android:icon="@drawable/app_icon"//此处是在res下的图标资源(用于显示apk图标)
        android:label="xxx"//Library名
        android:supportsRtl="true">
        <activity android:name="com.xxx.xxx.MainActivity"
            android:label="@string/app_name"
            android:screenOrientation="landscape">//此处是限制屏幕只能竖屏
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>


Unity 代码:TakePhoto .cs

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

public class TakePhoto : MonoBehaviour {
    // Use this for initialization  
    void Start()
    {
    }
    //打开相册    
    public void OpenPhoto()
    {

//这三句代码是不变的,只管用就行了(引号内是Andriod端Activity内部方法名
        AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
        jo.Call("OpenGallery");
    }

    //打开相机  
    public void OpenCamera()
    {
        AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
        jo.Call("takephoto");
    }

    //获取图片安卓路径
    public void GetImagePath(string imagePath)
    {
        if (!string.IsNullOrEmpty(imagePath))
        {
            StartCoroutine(LoadImage(imagePath));
        }
    }
    //获取图片
    private IEnumerator LoadImage(string imagePath)
    {
        WWW www = new WWW("file://" + imagePath);
        yield return www;
        if (string.IsNullOrEmpty(www.error))
        {
            //成功读取图片,写自己的逻辑
            //上传图片
            byte[] bts = www.texture.EncodeToPNG();
            if (bts != null)
                StartCoroutine(ServiceMgr.GetInstance.UploadingTexture(Global_Game.postUrl_FileUploading, "file", bts));
            //释放资源
            www.Dispose();
        }
        else
        {
            Debug.LogError("LoadImage>>>www.error:" + www.error);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/it_yanghui/article/details/78614462