1. 程式人生 > >開啟安卓手機相簿和相機並裁剪圖片上傳到unity

開啟安卓手機相簿和相機並裁剪圖片上傳到unity

1、建立一個空的安卓工程

2、在unity安裝目錄下找到classes.jar檔案並匯入到工程中的libs資料夾下(classes.jar目錄為:unity安裝目錄\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\il2cpp\Development\Classes)

3、右鍵工程中的classes.jar-->BuildPath-->Add to Build Path

4、修改MainActivity.java的程式碼

package com.player.fish;這裡是自己的包名

 

import java.io.File;  

import java.io.FileNotFoundException;  

import java.io.FileOutputStream;  

import java.io.IOException;  

  

import com.unity3d.player.UnityPlayer;  

import com.unity3d.player.UnityPlayerActivity;  

  

import android.app.Activity;  

import android.content.ContentResolver;  

import android.content.Intent;  

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 android.widget.Toast;

 

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;// 拍照  

    public static final int PHOTOZOOM=3;//裁剪

    private static final boolean DEBUG = true;  

    private String savePath=""; //圖片儲存路徑

    private String picturePath=""; //最終上傳的檔案路徑

    private String unitygameobjectName = "BGPlane"; //Unity 中對應掛指令碼物件的名稱  

    public static final int NONE = 0;  

    @Override  

    protected void onCreate(Bundle savedInstanceState) {  

        super.onCreate(savedInstanceState);  

    }  

      

    //呼叫相機  

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

    }  

     

  //裁剪圖片

    public void CropPhoto(Uri uri) {

        //呼叫裁剪器

        Intent intent = new Intent("com.android.camera.action.CROP");

        intent.setDataAndType(uri, "image/*");

        // 開啟裁剪功能

        intent.putExtra("crop", "true");

        //設定寬高的比例

        intent.putExtra("aspectX", 1);

        intent.putExtra("aspectY", 1);

        //裁剪圖片寬高

        intent.putExtra("outputX", 100);

        intent.putExtra("outputY", 100);

        //請求返回資料

        intent.putExtra("return-data", true);

 

        startActivityForResult(intent, PHOTOZOOM);  

    }

   

    @Override  

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {  

    // TODO Auto-generated method stub  

     super.onActivityResult(requestCode, resultCode, data);  

         if (resultCode == NONE){  

             return;  

         }  

         //相簿

         else if(PHOTO_REQUEST_CODE == requestCode){  

             if(data == null){  

                 return;  

             }  

             Uri uri = data.getData();  

             savePath = getImagePath(uri);

             if(DEBUG){  

                 Log.d(TAG, savePath);  

             }  

             CropPhoto(uri);

         }  

           //相機

         else if (requestCode == PHOTOHRAPH) {   

         savePath = Environment.getExternalStorageDirectory() + "/temp.jpg";

             if(DEBUG){  

                 Log.e("path:", savePath);  

             }  

             CropPhoto(Uri.fromFile(new File(savePath)));

             try {  

                 Bitmap bitmap = BitmapFactory.decodeFile(savePath);    

                 SaveBitmap(bitmap);  

              } catch (IOException e) {  

                  e.printStackTrace();  

              }  

         }   

         //裁剪

         else if(PHOTOZOOM == requestCode){

         Bundle extras = data.getExtras();

         if(extras!=null)

         {

         try{

         Bitmap photo=extras.getParcelable("data");

         SaveBitmap(photo);

         }catch(IOException e)

         {

         e.printStackTrace();

         }

         

         }

         

         UnityPlayer.UnitySendMessage(unitygameobjectName, "GetImagePath", picturePath);  

         }

    }  

      

  

    

    

    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";

             picturePath=path + "/" + FILE_NAME;

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

         }  

     }  

      

}

 

5、修改AndrlidManifest.xml,設定許可權及相關資訊

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

    package="com.player.fish"

    android:versionCode="1"

    android:versionName="1.0" >

 

    <!-- 連線網際網路的許可權 -->

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

    <!-- SDCard中建立與刪除檔案許可權 -->

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

    <!-- SDCard寫入資料許可權 -->

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

    

    <uses-sdk

        android:minSdkVersion="14"

        android:targetSdkVersion="21" />

 

    <application

        android:allowBackup="true"  

        android:icon="@drawable/ic_launcher"

        android:label="@string/app_name">

        <activity

            android:name="com.player.fish.MainActivity"

            android:screenOrientation="landscape"鎖定橫屏,豎屏的可以把這行刪掉(注意橫豎屏不匹配會導致閃退)

            android:label="@string/app_name" >

            <intent-filter>

                <action android:name="android.intent.action.MAIN" />

 

                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

        

    </application>

    

</manifest>

6、點選Project-->把Build Automatically前面的勾去掉,-->點選Clean-->Clean All Project-->OK

7、點選Project-->BuildProject

8、Win+R調出執行視窗-->CMD

9、將控制檯地址改為安卓工程中classes資料夾地址(安卓工程目錄\bin\classes)

更改方式為:目標磁碟+“:”-->回車變更磁碟地址

Cd\+磁碟後面的地址-->回車變更後面的資料夾地址

比如我的classes資料夾地址為D:\AndroidSDK\FishTest\bin\classes

 

 

10、將地址改為classes資料夾下後,將classes資料夾下面的所有jar包打包在一起,具體命令為 jar -vcf 壓縮包名.jar *

比如我將jar包壓縮為class.jar,那麼命令為 jar -vcf class.jar *,打出來的包就在classes資料夾倆面

 

11、開啟剛剛打出來的jar包(不是解壓縮),按照包名的路徑開啟資料夾(我的包名為com.player.fish,所以資料夾結構為com-->player-->fish),刪除裡面所有帶R和$的檔案,否則打包回報錯

 

12、在Unity工程中建立Plugins-->Android資料夾,將安卓工程中的AndroidManifest.xml檔案以及assets資料夾還有res資料夾匯入到Android資料夾下面,在Android資料夾下新建bin資料夾,將剛剛打出來的jar包放進去

 

13、準備工作全部完成,接下來開始寫C#指令碼

 private void Awake()

    {

        //將掛載此指令碼的物體的名字改為和java指令碼中的名字一致

        this.gameObject.name = "BGPlane";

    }

 

    //開啟相簿    

    public void OpenPhoto()

    {

        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 (imagePath == null)

            return;

        StartCoroutine("LoadImage", imagePath);

    }

    

    private IEnumerator LoadImage(string imagePath)

    {

        WWW www = new WWW("file://" + imagePath);

        yield return www;

        if (www.error == null)

        {

            //成功讀取圖片,寫自己的邏輯  

            this.GetComponent<MeshRenderer>().material.mainTexture = www.texture;

        }

        else

        {

            Debug.LogError("WWW Error:" + www.error);

        }

}

14、全部完成,打包(注意:playersetting中的包名要和安卓工程以及xml檔案中的包名一致,掛在C#指令碼的物體的名字在MainActivity.java中已經定義好,要保持一致;C#指令碼中所有的方法都是通過訊息傳遞來通知的,方法名要和MainActivity.java中定義的保持一致