此篇博文解决的问题是:

1、unity3d如何访问android SD卡的文件

2、如果把android端代码以jar包形式由unity3d调用

闲话不多说,现在咱们进入正题。

一、unity3d如何访问android SD卡的文件

实现效果是unity3d调用android相册或相机,选择一张图片剪裁后,将图片肯绘制到unity3d中。

解决这个问题,首先需要明白的是unity3d的资源存放目录,因为unity3d支持跨平台特性,所以资源文件的存放必然遵循一定的规则,否则很可能在不同的平台上编译会出现问题。

Unity3D中的资源路径

Application.dataPath 此属性用于返回程序的数据文件所在文件夹的路径。例如在Editor中就是Assets了。
Application.streamingAssetsPath 此属性用于返回流数据的缓存目录,返回路径为相对路径,适合设置一些外部数据文件的路径。
Application.persistentDataPath 此属性用于返回一个持久化数据存储目录的路径,可以在此路径下存储一些持久化的数据文件。
Application.temporaryCachePath 此属性用于返回一个临时数据的缓存目录。

android平台对应的资源路径

Application.dataPath /data/app/xxx.xxx.xxx.apk
Application.streamingAssetsPath jar:file:///data/app/xxx.xxx.xxx.apk/!/assets
Application.persistentDataPath /data/data/xxx.xxx.xxx/files
Application.temporaryCachePath /data/data/xxx.xxx.xxx/cache

具体的Unity3d的资源及目录说明可参考:http://www.tuicool.com/articles/qMNnmm6 ,此处不再缀述。

因此如果我们想要访问andorid SD卡上的文件,必须使用持久化数据存储目录 Application.persistentDataPath,它在android上对应的目录为Android/data/xxx.xx.xx/files/ 文件夹。也就是说,unity3d读取android SD中的文件目录是固定的,这是一个私有目录。下面我们来实现这一功能。效果是,从相册中选择一张照片,剪裁后,讲照片保存到android app安装目录下的files文件夹中,然后由unity3d读取此图片,绘制到屏幕上。

1、我们创建一个Android工程,取名为UnitySDK,此工程的目的是把我们的android端代码打包成一个jar包,放入Unity3d中使用,这里使用的是Eclipse,记住包名需跟unity3D android配置里的包名保持一致。

2、把我们的项目设置为一个Library

3、从unity的安装目录中找出classes.jar包,不同电脑文件存放位置可能不同,Windows平台如果使用mono方式的话,此文件在\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes 中。将jar包引用到我们的项目中。

4、将MainActivity继承自UnityPlayerActivity 并移除setContentView()方法,这是因为UnityPlayerActivity 继承自Activity,它里面已经设置了unityPlayer作为界面渲染,如果不移除setContentView()方法,则会造成复写,看不到unity3d的界面。MainActivity里的代码如下:

public class MainActivity extends UnityPlayerActivity {Context mContext = null;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mContext = this;}// Unity中会调用这个方法,用于区分打开摄像机 开始本地相册public void TakePhoto(String str) {Intent intent = new Intent(mContext, WebViewActivity.class);intent.putExtra("type", str);this.startActivity(intent);}
}

在此我们定义了一个TakePhoto方法,,同时将处理结果交给WebViewActivity处理。WebViewActivity的代码如下,它的作用是用于打开相册/相机,选择照片后,进行剪裁,最后将剪裁结果保存到Android/data/com.demo.unity/files/ 目录下供unity3d调用。

public class WebViewActivity extends Activity {ImageView imageView = null;public static final int NONE = 0;public static final int PHOTOHRAPH = 1;// 拍照public static final int PHOTOZOOM = 2; // 缩放public static final int PHOTORESOULT = 3;// 结果public static final String IMAGE_UNSPECIFIED = "image/*";public final static String FILE_NAME = "image.png";public final static String DATA_URL = "/data/data/";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_webview);imageView = (ImageView) this.findViewById(R.id.imageID);String type = this.getIntent().getStringExtra("type");// 在这里判断是打开本地相册还是直接照相if (type.equals("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);} else {Intent intent = new Intent(Intent.ACTION_PICK, null);intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_UNSPECIFIED);startActivityForResult(intent, PHOTOZOOM);}}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {if (resultCode == NONE)return;// 拍照if (requestCode == PHOTOHRAPH) {// 设置文件保存路径这里放在跟目录下File picture = new File(Environment.getExternalStorageDirectory() + "/temp.jpg");startPhotoZoom(Uri.fromFile(picture));}if (data == null)return;// 读取相册缩放图片if (requestCode == PHOTOZOOM) {startPhotoZoom(data.getData());}// 处理结果if (requestCode == PHOTORESOULT) {Bundle extras = data.getExtras();if (extras != null) {Bitmap photo = extras.getParcelable("data");imageView.setImageBitmap(photo);try {SaveBitmap(photo);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}super.onActivityResult(requestCode, resultCode, data);}public void startPhotoZoom(Uri uri) {Intent intent = new Intent("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);}public void SaveBitmap(Bitmap bitmap) throws IOException {FileOutputStream fOut = null;// 注解1
//      String path = "/mnt/sdcard/Android/data/com.xys/files";String path = "/storage/emulated/0/Android/data/com.demo.unity/files";try {// 查看这个路径是否存在,// 如果并没有这个路径,// 创建这个路径File destDir = new File(path);if (!destDir.exists()) {destDir.mkdirs();}fOut = new FileOutputStream(path + "/" + FILE_NAME);} catch (FileNotFoundException e) {e.printStackTrace();}// 将Bitmap对象写入本地路径中,Unity在去相同的路径来读取这个文件bitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);try {fOut.flush();} catch (IOException e) {e.printStackTrace();}try {fOut.close();} catch (IOException e) {e.printStackTrace();}// 通知Unity开始在"/mnt/sdcard/Android/data/com.xys/files";路径中读取图片资源,并且现在在Unity中UnityPlayer.UnitySendMessage("Main Camera", "message", FILE_NAME);finish();
}}

注意 com.demo.unity是我项目的包名,实际使用过程中请注意替换。

WebViewActivity布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:orientation="vertical" ><ImageViewandroid:layout_gravity="center"android:id="@+id/imageID"android:layout_width="wrap_content"android:layout_height="wrap_content" /></LinearLayout>

Manifest中代码如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.demo.unity"android:versionCode="1"android:versionName="1.0" ><uses-sdkandroid:minSdkVersion="14"android:targetSdkVersion="14" /><!-- 连接互联网的权限 --><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" /><applicationandroid:icon="@drawable/ic_launcher"android:label="@string/app_name" ><activityandroid:name="com.demo.unity.MainActivity"android:label="@string/app_name"android:theme="@android:style/Theme.NoTitleBar.Fullscreen" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activityandroid:name="com.demo.unity.TestActivity0"android:theme="@android:style/Theme.NoTitleBar.Fullscreen" ></activity><activityandroid:name="com.demo.unity.WebViewActivity"android:theme="@android:style/Theme.NoTitleBar.Fullscreen" ></activity></application>
</manifest>

注意: 把android:theme换成android自带的主题

5、至此,android端代码基本编写完成,clean一下项目,在bin目录下找到 对应jar包,此jar包即为unity3d需要用到的jar包。

6、创建unity项目,并在Assets目录下依次创建 Plugins 和Android文件夹,将android 资源文件放到res目录下,Eclipse里的jar包,放到bin目录下,Manifest文件,放到 Android文件夹下:

注意:values中的style文件、dimen文件不要复制过去

7、编写Main Camera 的 C#文件,MainControl,代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class MainControl : MonoBehaviour {public GUISkin skin;Texture texture;string path="";// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {//当用户按下手机的返回键或home键退出游戏if (Input.GetKeyDown(KeyCode.Escape) || Input.GetKeyDown(KeyCode.Home) ){Application.Quit();}}void OnGUI(){GUILayout.Button (path, GUILayout.Height (100));GUI.skin = skin;if(GUILayout.Button("打开手机相册",GUILayout.Height(100))){//调用我们制作的Android插件打开手机相册AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");jo.Call("TakePhoto","takeSave");}if(GUILayout.Button("打开手机摄像机",GUILayout.Height(100))){//调用我们制作的Android插件打开手机摄像机AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");jo.Call("TakePhoto","takePhoto");}if(texture != null){//注意! 我们在这里绘制Texture对象,该对象是通过//我们制作的Android插件得到的,当这个对象不等于空的时候//直接绘制。GUI.DrawTexture(new Rect(300,300,600,600),texture);}}void message(string str){StartCoroutine(LoadTexture(str));}IEnumerator LoadTexture(string name){//注解1path  =  "file://" + Application.persistentDataPath +"/" + name;WWW www = new WWW(path);while (!www.isDone){}yield return www;//为贴图赋值texture = www.texture;}
}

最后来张效果图~:

源码地址:https://pan.baidu.com/s/1bo7ezDl     其中, UnityDemo为unity创建的项目, UnitySDK为android项目。

Unity3d android 通信之 unity3d读取android SD卡文件相关推荐

  1. Android 读取手机SD卡根目录下某个txt文件的文件内容

    1.先看activity_main.xml文件: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/and ...

  2. android 使用SAF框架操作外置sd卡

    android 使用SAF框架操作外置sd卡 在 Android 4.4中,Google 对 SD卡 的访问已经做了严格的限制,在 Android 5.0中,开发者可以使用 新API 要求用户对某个指 ...

  3. android 访问存储卡,Android:无法访问存储在SD卡中的文件

    我正在研究一个读取存储在SD卡(内部/数据/本地)中的.txt文件的应用程序.我遇到的问题是,它似乎可以访问文件路径,但它不能访问文件本身(尽管它具有读取和写入权限),但会引发FileNotFound ...

  4. Android—将Bitmap图片保存到SD卡目录下或者指定目录

    直接上代码就不废话啦 一:保存到SD卡下 [java] view plain copy File file = new File(Environment.getExternalStorageDirec ...

  5. android 2.3 取内外置SD卡

    在android2.3中 判断内置SD卡是否挂载: if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) ...

  6. Arduino ESP32 读取Micro sd卡容量信息示例

    Arduino ESP32 读取Micro sd卡容量信息示例 接线说明 ESP32 ----Micro SD VIN (DEVKIT这个引脚有5V电压)---- VCC GND ----GND D2 ...

  7. android sd卡 物理扇区读取,关于SD卡的逻辑扇区和物理扇区

    http://www.icdev.com.cn/bbs/viewthread.php?tid=10724 关于SD卡的逻辑扇区和物理扇区 看了几个朋友的帖子,个人认为大家对于逻辑扇区和物理扇区有点混淆 ...

  8. java 访问手机存储卡,android实现文件下载并存储进SD卡

    标题很明显,这篇博文主要内容是: 在android程序中实现文件的下载并存储进手机或虚拟机的SD卡 在demo中我主要操作为: 1,根据有效的文本文件url地址,读取文本内容:demo使用的是.lrc ...

  9. Android中ImageSwitcher结合Gallery展示SD卡中的资源图片

    本文主要是写关于ImageSwitcher结合Gallery组件如何展示SDCard中的资源图片,相信大家都看过API Demo 中也有关于这个例子的,但API Demo 中的例子是展示工程中Draw ...

最新文章

  1. 不死神兔c语言20月,不死神兔问题(斐波那契数列)
  2. 《幽灵行动·荒野》中的程序化技术:道路、河流、城镇、植被
  3. 数据预处理(part2)--多个预测变量数据变换
  4. 实例36:python
  5. 【147天】尚学堂高淇Java300集视频精华笔记(108-109)
  6. _GUN_SOURCE宏
  7. 接口调用导致阻塞_RocketMQ与Dubbo之间线程之间如何阻塞和唤醒
  8. ffmpeg java 使用教程_Java使用ffmpeg
  9. 阿里云企业邮箱使用步骤
  10. python中除法运算_python除法运算
  11. Javaweb大作业文档部分预览
  12. linux怎么查看终端号,怎么查看linux 图形终端设备号
  13. 嵌入式行业技术思维导图
  14. 基于python的药店管理系统软件_一套很不错的药店管理软件,值得一看
  15. layui单据打印_layui打印表格自定义函数
  16. 别只关注地段、户型 楼盘隐形品质不能忽视
  17. 关于x>y?x:y的含义
  18. thinkpad笔记本电脑怎么关闭触摸板
  19. vr分类及其常见类型
  20. 5G/NR 随机接入过程学习总结

热门文章

  1. php拍照,php视频拍照上传头像功能实现代码分享
  2. java将英文句子分解为单词,Java如何将文本或句子分解为单词?
  3. spyder pyecharts不显示_优派XG270QG电竞显示器评测 四大金刚的继承者
  4. datart 二开环境搭建
  5. ByteBuffer.wrap函数
  6. 戴尔电脑开机出现Recovery怎么解决
  7. 从MP4头信息中提取sps和pps数据
  8. native2ascii工具的使用
  9. 哈尔滨工业大学 计算机系统 大作业 22春
  10. 检查Rage的着色器