unity 启动相机_Unity3D研究院之打开照相机与本地相册进行裁剪显示(三十三)...
最近做項目需要用到這個功能,就是在Unity中調用Android本地相冊或直接打開攝像機拍照并且裁剪一部分用于用戶頭像,今天研究了一下,那么研究出成果了MOMO一定要分享給大家。Unity與Android的交互還有誰不會?? 如果有不會的朋友請看MOMO之前的文章喔,Unity3D研究院之打開Activity與調用JAVA代碼傳遞參數(十八)這里有關交互的方式就不詳細說明,主要將如何在Unity中打開攝像機、在Unity中打開本地相冊,選一個照片后如何進行裁剪,最后將圖片轉換成Texture顯示在U3D的世界當中。
首先看看Eclipse中的Android插件部分,我的包名是com.xys請大家與MOMO保持一致,Unity工程中也需要是這個包名噢。
UnityTestActivity.java 這個類是Unity的插件主類,在這里調用是打開攝像機 還是本地相冊的方法。
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
packagecom.xys;
importandroid.content.Context;
importandroid.content.Intent;
importandroid.os.Bundle;
importcom.unity3d.player.UnityPlayerActivity;
publicclassUnityTestActivityextendsUnityPlayerActivity{
//public class UnityTestActivity extends Activity {
ContextmContext=null;
@Override
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
mContext=this;
}
//Unity中會調用這個方法,用于區分打開攝像機 開始本地相冊
publicvoidTakePhoto(Stringstr)
{
Intentintent=newIntent(mContext,WebViewActivity.class);
intent.putExtra("type",str);
this.startActivity(intent);
}
}
然后是WebViewActivity.java 這里主要處理用戶打開攝像機或本地相冊后如何進行裁剪圖片,并且把裁剪的圖片儲存在本地文件中。
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
packagecom.xys;
importjava.io.File;
importjava.io.FileNotFoundException;
importjava.io.FileOutputStream;
importjava.io.IOException;
importcom.unity3d.player.UnityPlayer;
importandroid.app.Activity;
importandroid.content.Intent;
importandroid.graphics.Bitmap;
importandroid.net.Uri;
importandroid.os.Bundle;
importandroid.os.Environment;
importandroid.provider.MediaStore;
importandroid.view.KeyEvent;
importandroid.widget.ImageView;
publicclassWebViewActivityextendsActivity
{
ImageViewimageView=null;
publicstaticfinalintNONE=0;
publicstaticfinalintPHOTOHRAPH=1;// 拍照
publicstaticfinalintPHOTOZOOM=2;// 縮放
publicstaticfinalintPHOTORESOULT=3;// 結果
publicstaticfinalStringIMAGE_UNSPECIFIED="image/*";
publicfinalstaticStringFILE_NAME="image.png";
publicfinalstaticStringDATA_URL="/data/data/";
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
imageView=(ImageView)this.findViewById(R.id.imageID);
Stringtype=this.getIntent().getStringExtra("type");
//在這里判斷是打開本地相冊還是直接照相
if(type.equals("takePhoto"))
{
Intentintent=newIntent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(newFile(Environment.getExternalStorageDirectory(),"temp.jpg")));
startActivityForResult(intent,PHOTOHRAPH);
}else
{
Intentintent=newIntent(Intent.ACTION_PICK,null);
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,IMAGE_UNSPECIFIED);
startActivityForResult(intent,PHOTOZOOM);
}
}
@Override
protectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){
if(resultCode==NONE)
return;
// 拍照
if(requestCode==PHOTOHRAPH){
//設置文件保存路徑這里放在跟目錄下
Filepicture=newFile(Environment.getExternalStorageDirectory()+"/temp.jpg");
startPhotoZoom(Uri.fromFile(picture));
}
if(data==null)
return;
// 讀取相冊縮放圖片
if(requestCode==PHOTOZOOM){
startPhotoZoom(data.getData());
}
// 處理結果
if(requestCode==PHOTORESOULT){
Bundleextras=data.getExtras();
if(extras!=null){
Bitmapphoto=extras.getParcelable("data");
imageView.setImageBitmap(photo);
try{
SaveBitmap(photo);
}catch(IOExceptione){
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
super.onActivityResult(requestCode,resultCode,data);
}
publicvoidstartPhotoZoom(Uriuri){
Intentintent=newIntent("com.android.camera.action.CROP");
intent.setDataAndType(uri,IMAGE_UNSPECIFIED);
intent.putExtra("crop","true");
// aspectX aspectY 是寬高的比例
intent.putExtra("aspectX",1);
intent.putExtra("aspectY",1);
// outputX outputY 是裁剪圖片寬高
intent.putExtra("outputX",300);
intent.putExtra("outputY",300);
intent.putExtra("return-data",true);
startActivityForResult(intent,PHOTORESOULT);
}
publicvoidSaveBitmap(Bitmapbitmap)throwsIOException{
FileOutputStreamfOut=null;
//注解1
Stringpath="/mnt/sdcard/Android/data/com.xys/files";
try{
//查看這個路徑是否存在,
//如果并沒有這個路徑,
//創建這個路徑
FiledestDir=newFile(path);
if(!destDir.exists())
{
destDir.mkdirs();
}
fOut=newFileOutputStream(path+"/"+FILE_NAME);
}catch(FileNotFoundExceptione){
e.printStackTrace();
}
//將Bitmap對象寫入本地路徑中,Unity在去相同的路徑來讀取這個文件
bitmap.compress(Bitmap.CompressFormat.PNG,100,fOut);
try{
fOut.flush();
}catch(IOExceptione){
e.printStackTrace();
}
try{
fOut.close();
}catch(IOExceptione){
e.printStackTrace();
}
}
@Override
publicbooleanonKeyDown(intkeyCode,KeyEventevent)
{
if(keyCode==KeyEvent.KEYCODE_BACK&&event.getRepeatCount()==0)
{
//當用戶點擊返回鍵是 通知Unity開始在"/mnt/sdcard/Android/data/com.xys/files";路徑中讀取圖片資源,并且現在在Unity中
UnityPlayer.UnitySendMessage("Main Camera","message",FILE_NAME);
}
returnsuper.onKeyDown(keyCode,event);
}
}
注解1:主要是路徑”/mnt/sdcard/Android/data/com.xys/files”,如下圖所示,我們在這里把文件保存在這個路徑下。為什么要把圖片2進制文件寫在這里呢? 還記得以前MOMO給大家說過在Unity中訪問Android或IOS本地2進制文件時用到的這個路徑,
Application.persistentDataPath ? 該路徑等價于?/mnt/sdcard/Android/data/com.xys/files ,當然后者的包名是對應的工程包名,這樣在Unity中可以找到對應裁剪后的圖片文件,并且顯示在Unity中。
AndroidManifest.xml ?這個文件也沒什么好說的,大家看看吧。
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package="com.xys"
android:versionCode="1"
android:versionName="1.0">
android:icon="@drawable/ic_launcher"
android:label="@string/app_name">
android:name=".UnityTestActivity"
android:label="@string/app_name">
android:name=".WebViewActivity">
然后把上面的Android工程打包做成插件放在Unity中。如下圖所示,這個我的Unity工程中對應的路徑。如果看不懂的朋友請看我之前的文章哈。
然后看Test.cs腳本,它直接掛在攝像機身上。
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
usingUnityEngine;
usingSystem.Collections;
usingSystem.IO;
publicclassTest:MonoBehaviour
{
publicGUISkinskin;
Texturetexture;
voidUpdate()
{
if(Input.GetKeyDown(KeyCode.Escape)||Input.GetKeyDown(KeyCode.Home))
{
Application.Quit();
}
}
voidOnGUI()
{
GUI.skin=skin;
if(GUILayout.Button("打開手機相冊"))
{
//調用我們制作的Android插件打開手機相冊
AndroidJavaClassjc=newAndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObjectjo=jc.GetStatic("currentActivity");
jo.Call("TakePhoto","takeSave");
}
if(GUILayout.Button("打開手機攝像機"))
{
//調用我們制作的Android插件打開手機攝像機
AndroidJavaClassjc=newAndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObjectjo=jc.GetStatic("currentActivity");
jo.Call("TakePhoto","takePhoto");
}
if(texture!=null)
{
//注意! 我們在這里繪制Texture對象,該對象是通過
//我們制作的Android插件得到的,當這個對象不等于空的時候
//直接繪制。
GUI.DrawTexture(newRect(100,300,300,300),texture);
}
}
voidmessgae(stringstr)
{
//在Android插件中通知Unity開始去指定路徑中找圖片資源
StartCoroutine(LoadTexture(str));
}
IEnumeratorLoadTexture(stringname)
{
//注解1
stringpath="file://"+Application.persistentDataPath+"/"+name;
WWWwww=newWWW(path);
while(!www.isDone)
{
}
yieldreturnwww;
//為貼圖賦值
texture=www.texture;
}
}
注解1:請大家一定要注意這個路徑的寫法, 前面一定要加 “File://” 不然無法讀取。OK說了這么多我們看看這個項目運行的效果,激動人心的時刻來臨啦 嚯嚯嚯嚯!!!
1.首次進入的畫面, 這里的圖片是我剛剛從相冊選擇的
2.打開相冊我們選擇一張圖片
3. 選擇一張圖片,我們進行裁剪
最后我們返回到Unity中界面。新的圖片Unity已經完成讀取,界面上已經修改成剛剛我裁剪的啦,哇咔咔。 怎么樣,還不錯啦? 哈哈后。這個做用戶頭像肯定給力 蛤蛤。
如果點擊打開攝像機按鈕,拍照完畢后會提示裁剪,裁減完畢返回到Unity界面中同樣能看到效果。
最后MOMO將本篇博文的源碼放出來, ?源碼包括Android的工程 與Unity的工程,雨松MOMO祝大家學習愉快,大家互相學習互相進步,加油哇咔咔,啦啦啦。
最后編輯:2015-07-03作者:雨松MOMO
專注移動互聯網,Unity3D游戲開發
捐 贈寫博客不易,如果您想請我喝一杯星巴克的話?就進來看吧!
總結
以上是生活随笔為你收集整理的unity 启动相机_Unity3D研究院之打开照相机与本地相册进行裁剪显示(三十三)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于月的网名143个
- 下一篇: 硝酸钡是沉淀吗