android sd 卡

2012-04-04 16:53:58 wangjia55 阅读数 4486

实现Android SD卡文件浏览器技术分析:

主要用到的控件:ListView
我们要做的就是遍历整个SD卡下的所有文件并把他们显示到这个ListView控件中,如果遍历的是文件夹那么先获取该文件夹的下的所有文件,再把这个所有文件填充到这个ListView里就可以了,如此反复就可以了。

如何获取文件夹或者文件的修改日期?
用java里的File类只为我们提供了一个public long lastModified():表示文件最后一次被修改的时间的 long 值,用与时间点(1970 年 1 月 1 日,00:00:00 GMT)之间的毫秒数表示;如果该文件不存在,或者发生 I/O 错误,则返回 0L。

1
2
3
4
File myFile = new File("D:\\Android开发常用图标");
long modTime = myFile.lastModified();
SimpleDateFormat dateFormat =newSimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(dateFormat.format(newDate(modTime)));

实现代码:

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
162
163
package com.jiahui.sdcardfileexplorer;
 
import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;
 
public class SDCardFileExplorerActivity extendsActivity {
 
    privateTextView tvpath;
    privateListView lvFiles;
    privateButton btnParent;
 
    // 记录当前的父文件夹
    File currentParent;
 
    // 记录当前路径下的所有文件夹的文件数组
    File[] currentFiles;
 
    publicvoidonCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        lvFiles = (ListView)this.findViewById(R.id.files);
 
        tvpath = (TextView)this.findViewById(R.id.tvpath);
        btnParent = (Button)this.findViewById(R.id.btnParent);
 
        // 获取系统的SDCard的目录
        File root =newFile("/mnt/sdcard/");
        // 如果sd卡存在的话
        if(root.exists()) {
 
            currentParent = root;
            currentFiles = root.listFiles();
            // 使用当前目录下的全部文件、文件夹来填充ListView
            inflateListView(currentFiles);
 
        }
 
        lvFiles.setOnItemClickListener(newOnItemClickListener() {
            @Override
            publicvoidonItemClick(AdapterView<?> adapterView, View view,
                    intposition,long id) {
                // 如果用户单击了文件,直接返回,不做任何处理
                if(currentFiles[position].isFile()) {
                    // 也可自定义扩展打开这个文件等
                    return;
                }
                // 获取用户点击的文件夹 下的所有文件
                File[] tem = currentFiles[position].listFiles();
                if(tem ==null || tem.length ==0) {
 
                    Toast.makeText(SDCardFileExplorerActivity.this,
                            "当前路径不可访问或者该路径下没有文件", Toast.LENGTH_LONG).show();
                }else{
                    // 获取用户单击的列表项对应的文件夹,设为当前的父文件夹
                    currentParent = currentFiles[position];
                    // 保存当前的父文件夹内的全部文件和文件夹
                    currentFiles = tem;
                    // 再次更新ListView
                    inflateListView(currentFiles);
                }
 
            }
        });
 
        // 获取上一级目录
        btnParent.setOnClickListener(newView.OnClickListener() {
 
            @Override
            publicvoidonClick(View v) {
 
                try{
 
                    if(!currentParent.getCanonicalPath().equals("/mnt/sdcard")) {
 
                        // 获取上一级目录
                        currentParent = currentParent.getParentFile();
                        // 列出当前目录下的所有文件
                        currentFiles = currentParent.listFiles();
                        // 再次更新ListView
                        inflateListView(currentFiles);
                    }
                }catch(Exception e) {
                    // TODO: handle exception
                }
 
            }
        });
 
    }
 
    /**
     * 根据文件夹填充ListView
     *
     * @param files
     */
    privatevoidinflateListView(File[] files) {
 
        List<Map<String, Object>> listItems =newArrayList<Map<String, Object>>();
 
        for(inti = 0; i < files.length; i++) {
 
            Map<String, Object> listItem =newHashMap<String, Object>();
 
            if(files[i].isDirectory()) {
                // 如果是文件夹就显示的图片为文件夹的图片
                listItem.put("icon", R.drawable.folder);
            }else{
                listItem.put("icon", R.drawable.file);
            }
            // 添加一个文件名称
            listItem.put("filename", files[i].getName());
 
            File myFile =newFile(files[i].getName());
 
            // 获取文件的最后修改日期
            longmodTime = myFile.lastModified();
            SimpleDateFormat dateFormat =newSimpleDateFormat(
                    "yyyy-MM-dd HH:mm:ss");
            System.out.println(dateFormat.format(newDate(modTime)));
 
            // 添加一个最后修改日期
            listItem.put("modify",
                    "修改日期:"+ dateFormat.format(newDate(modTime)));
 
            listItems.add(listItem);
 
        }
 
        // 定义一个SimpleAdapter
        SimpleAdapter adapter =newSimpleAdapter(
                SDCardFileExplorerActivity.this, listItems, R.layout.list_item,
                newString[] {"filename","icon","modify"}, new int[] {
                        R.id.file_name, R.id.icon, R.id.file_modify });
 
        // 填充数据集
        lvFiles.setAdapter(adapter);
 
        try{
            tvpath.setText("当前路径为:"+ currentParent.getCanonicalPath());
        }catch(Exception e) {
            e.printStackTrace();
        }
 
    }
}

最终效果图:

sd卡浏览器

本文出处:http://blog.csdn.net/jiahui524


2018-09-14 08:34:42 hubianyu 阅读数 3391

Android SD卡简单的文件读写操作

 

最近有这样的需求,把每次统计到的数据,以txt形式保存到手机SD卡或是手机内存中,遇到一些问题,记录下来。

 

首先如果要在程序中使用sdcard进行存储,我们必须要在AndroidManifset.xml文件进行下面的权限设置:

 

[

  1.   <!-- SDCard中创建与删除文件权限 -->  
  2.   <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>  
  3.  <!-- 向SDCard写入数据权限 -->  
  4.  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  


  接着在使用SDcard进行读写的时候 会用到Environment类下面的几个静态方法  : 

 

    1: getDataDirectory() 获取到Android中的data数据目录(sd卡中的data文件夹)
    2:getDownloadCacheDirectory() 获取到下载的缓存目录(sd卡中的download文件夹)
    3:getExternalStorageDirectory() 获取到外部存储的目录 一般指SDcard(/storage/sdcard0)
    4:getExternalStorageState() 获取外部设置的当前状态 一般指SDcard,比较常用的应该是 MEDIA_MOUNTED(SDcard存在并且可以进行读写)还有其他的一些状态,可以在文档中进行查找。

    5:getRootDirectory()  获取到Android Root路径

 

好,以下是具体操作,直接看代码:

1,判断SD卡是否存在

 

 

  1. /** 
  2.  * 判断SDCard是否存在 [当没有外挂SD卡时,内置ROM也被识别为存在sd卡] 
  3.  *  
  4.  * @return 
  5.  */  
  6. public static boolean isSdCardExist() {  
  7.     return Environment.getExternalStorageState().equals(  
  8.             Environment.MEDIA_MOUNTED);  
  9. }  


2,获取SD卡根目录

 

 

 

  1. /** 
  2.  * 获取SD卡根目录路径 
  3.  *  
  4.  * @return 
  5.  */  
  6. public static String getSdCardPath() {  
  7.     boolean exist = isSdCardExist();  
  8.     String sdpath = "";  
  9.     if (exist) {  
  10.         sdpath = Environment.getExternalStorageDirectory()  
  11.                 .getAbsolutePath();  
  12.     } else {  
  13.         sdpath = "不适用";  
  14.     }  
  15.     return sdpath;  
  16.   
  17. }  


3,获取默认的文件存放路径

 

 

 

  1. /** 
  2.  * 获取默认的文件路径 
  3.  *  
  4.  * @return 
  5.  */  
  6. public static String getDefaultFilePath() {  
  7.     String filepath = "";  
  8.     File file = new File(Environment.getExternalStorageDirectory(),  
  9.             "abc.txt");  
  10.     if (file.exists()) {  
  11.         filepath = file.getAbsolutePath();  
  12.     } else {  
  13.         filepath = "不适用";  
  14.     }  
  15.     return filepath;  
  16. }  


4-1,使用FileInputStream读取文件

 

 

 

  1. try {  
  2. le file = new File(Environment.getExternalStorageDirectory(),  
  3. "test.txt");  
  4.     FileInputStream is = new FileInputStream(file);  
  5.     byte[] b = new byte[inputStream.available()];  
  6.     is.read(b);  
  7.     String result = new String(b);  
  8.     System.out.println("读取成功:"+result);  
  9. } catch (Exception e) {  
  10.     e.printStackTrace();  
  11. }  


4-2,使用BufferReader读取文件

 

 

 

  1. try {  
  2.     File file = new File(Environment.getExternalStorageDirectory(),  
  3.             DEFAULT_FILENAME);  
  4.     BufferedReader br = new BufferedReader(new FileReader(file));  
  5.     String readline = "";  
  6.     StringBuffer sb = new StringBuffer();  
  7.     while ((readline = br.readLine()) != null) {  
  8.         System.out.println("readline:" + readline);  
  9.         sb.append(readline);  
  10.     }  
  11.     br.close();  
  12.     System.out.println("读取成功:" + sb.toString());  
  13. } catch (Exception e) {  
  14.     e.printStackTrace();  
  15. }  

httpConnection读取流保存成String数据

 

 

  1. URL url = new URL(getForwardUrl("/queryUserByUNorIP"));  
  2. HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
  3. InputStream is = conn.getInputStream();  
  4. BufferedReader br = new BufferedReader(new InputStreamReader(is));  
  5. StringBuilder sb = new StringBuilder();  
  6. String readline = null;  
  7. while ((readline = br.readLine()) != null) {  
  8.     sb.append(readline);  
  9. }  
  10. System.out.println("result"+sb.toString());  

等效于使用ByteArrayOutputStream

 

 

 

  1. InputStream is = conn.getInputStream();  
  2. ByteArrayOutputStream bos = new ByteArrayOutputStream();  
  3. byte[] buffer = new byte[1024];  
  4. int len =-1 ;  
  5. while ((len=is.read(buffer))!=-1) {  
  6.     bos.write(buffer, 0, len);  
  7. }  
  8. is.close();  
  9. bos.close();  
  10. String result = new String(bos.toByteArray());  
  11. System.out.println("result"+result);  

 

 

5-1,使用FileOutputStream写入文件

 

 

 

  1. try {  
  2.     File file = new File(Environment.getExternalStorageDirectory(),  
  3.             DEFAULT_FILENAME);  
  4.         FileOutputStream fos = new FileOutputStream(file);  
  5.         String info = "I am a chinanese!";  
  6.            fos.write(info.getBytes());  
  7.            fos.close();  
  8.     System.out.println("写入成功:");  
  9. } catch (Exception e) {  
  10.     e.printStackTrace();  
  11. }  


5-2,使用BufferedWriter写入文件

 

 

 

  1. try {  
  2.     File file = new File(Environment.getExternalStorageDirectory(),  
  3.             DEFAULT_FILENAME);  
  4.     //第二个参数意义是说是否以append方式添加内容  
  5.     BufferedWriter bw = new BufferedWriter(new FileWriter(file, true));  
  6.     String info = " hey, yoo,bitch";  
  7.     bw.write(info);  
  8.     bw.flush();  
  9.     System.out.println("写入成功");  
  10. } catch (Exception e) {  
  11.     e.printStackTrace();  
  12. }  

 

 

读取和写入我们都实现了,貌似很简单的样子,但是我们现在想每隔30秒进行一次数据整理,然后把他们写入到我们制定的txt文件中,但是我想每次都能在上一次的结尾处开始写入,这样在电脑上通过文本打开时,就能看到每一行的数据了。

这其实要求我们每一次写入数据时,都要有换行的操作符号,比如:\n,并且IO读写能以追加的方式写入到文件里。

刚开始我很笨的想到,每次写入前,先把文件读取出来并且生成一个StringBuffer,然后再append,然后再写入.....这种方式导致每次都要2次以上的IO操作,读和写。其实系统写入时就给我们自带了append方式,还是要勤看文档啊!

BufferedWriter

使用BufferedWriter,在构造BufferedWriter时,把第二个参数设为true
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(  
                    new FileOutputStream(file, true)));  
         out.write(conent);  

FileWriter

构造函数中的第二个参数true表示以追加形式写文件  
         FileWriter writer = new FileWriter(fileName, true);  
         writer.write(content);  
         writer.close();

// 打开一个随机访问文件流,按读写方式  
RandomAccessFile randomFile = new RandomAccessFile(fileName, "rw");  
// 文件长度,字节数  
long fileLength = randomFile.length();  
// 将写文件指针移到文件尾。  
randomFile.seek(fileLength);  
randomFile.writeBytes(content);  
randomFile.close(); 

 

 

问题:我在file写入时,没一次写完后,明明都添加了换行符(bw.write("\n")),为什么在Window的文本文档中看不到换行呢?而在EditPlus或是notepad++中就能看到换行后的效果?

 

 

  1. BufferedWriter bw = new BufferedWriter(new FileWriter(file, true));  
  2. String info = " hey, yoo,bitch";  
  3. bw.write(info);  
  4. bw.write("\n");  
  5. bw.flush();  


如上代码所示,可是在windows的文本文档中:

 

但是在诸如notepad++或EditPlus中看到却是没问题的:

 

这是为什么呢?

这是windows与linux系统的编码模式不同造成的。android系统是linux内核,与windows不同。windows是采用的是DOS编码方式,所用的换行符是DOS换行符CR/LF,也就是我们俗称的\r\n,(如果不理解可以去百度一下转义字符,一般程序员会用到这些知识),而linux系统的换行符为UNIX换行符LF,也就是\n,苹果的MAC系统用的是MAC换行符CR,也就是\r,现在我想你也差不多理解了。你在android手机里建立的文档肯定用的是UNIX换行符,也就是一个\n,但是这个文档你拿到windows里用记事本打开的话,因为windows记事本是DOS换行符\r\n,所以你少了个\r,所以没法识别成换行,只能给你识别成一个小方块了,解决办法很简单,你可以用EditPlus或者UltraEdit软件打开,UltraEdit也能转换这些编码模式,转换成DOS模式就可以了。

 

所以,我们只需要添加:\r\n  

 

 

  1. BufferedWriter bw = new BufferedWriter(new FileWriter(file, true));  
  2. String info = " hey, yoo,bitch";  
  3. bw.write(info);  
  4. bw.write("\r\n");  
  5. bw.flush();  
2019-07-04 10:51:16 feelinghappy 阅读数 4354

Android获取SD卡路径
本篇将会带领大家学习如何获取android路径的几种常见用法,但在我开始bb之前需要大家清楚android中内存和外存之间的区别,下面进行简短介绍:
android中的内存:保存在内存中的程序和文件是相互关联的,什么意思呢?举个例子,假设你android手机内存中有一个程序叫bb,然后由bb程序创建了一份名叫cc的文件,当你删除bb的时候cc也会应为关联而被删除。
像是Shared Preferences或SQLite的内容就是保存到内存储中的,这些保存的内容会随程序的删除而删除用过的同学因该很快能理解。
android中的外存:我们平常在android手机使用的最多的就是外部存储,像是你用相机拍了一张照片,这些一般都是保存到外存中的,这些文件不会因为你删除了程序而不见。

随着android版本的增加一般所谓的sd卡(外存储卡)都变成内置的了

下面正式开始介绍,先是获取SD卡根目录的方法:

添加权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
 

if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
        //为真则SD卡已装入,
        sdCardExist=Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);

    }

if(sdCardExist)
{
    sdDir = Environment.getExternalStorageDirectory();//获取跟目录
    //查找SD卡根路径
    sdDir.toString();
    Log.e("main","得到的根目录路径:"+sdDir);
}

打印Log:

博主打开手机文件管理器首先来到的所在页面就是这个路径,只是手机上不会显示这个路径

 

另外一个更灵活的获取外部路径的方法:
        File directory_doc = Environment.getExternalStoragePublicDirectory(Environment. DIRECTORY_DOCUMENTS);
        //使用这个方法需要传入公共目录的类型如Environment.DIRECTORY_DOCUMENTS
        //查看公共目录文档文件的路径
        Log.e("main","得到的公共目录:"+directory_doc);

获取路径的其他方法;

 


方法
描述

 


DIRECTORY_DOCUMENTS
标准文件目录,可以是用户自定义创建的。Standard directory in which to place documents that have been created by the user.


DIRECTORY_DOWNLOADS
下载目录. Standard directory in which to place files that have been downloaded by the user.


DIRECTORY_MOVIES
影视目录.Standard directory in which to place movies that are available to the user.


DIRECTORY_MUSIC
音乐目录.Standard directory in which to place any audio files that should be in the regular list of music for the user.


DIRECTORY_PICTURES
用户可以获得的图片目录.Standard directory in which to place pictures that are available to the user.


更多内容:https://developer.android.com/reference/android/os/Environment

 

当你有多个外部存储卡:
        File[] files;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            files = getExternalFilesDirs(Environment.MEDIA_MOUNTED);
            for(File file:files){
                Log.e("main", "得到的全部外存:" +String.valueOf(file));


//便历所有外部存储
            }
        }
 

这里由于博主手机只有一个sd卡,所以只打印了一行路径
 

 

得到内存:
  File internal=getFilesDir();
      Log.e("main","内存路径:"+internal);
12

 

 


如有错误欢迎纠正
 

--------------------- 
作者:Kerwinoyyx 
来源:CSDN 
原文:https://blog.csdn.net/Kerwinoyyx/article/details/91401291 
版权声明:本文为博主原创文章,转载请附上博文链接!

2017-05-05 12:51:26 u010838555 阅读数 5478

此篇博文解决的问题是:

     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;
	@Override
	public 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/";

	@Override
	protected 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);
		}

	}

	@Override
	protected 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 block
					e.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" >

    <ImageView
        android: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-sdk
        android: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" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android: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>
        <activity
            android:name="com.demo.unity.TestActivity0"
            android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
        </activity>
        <activity
            android: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 initialization
	void Start () {
	}
	
	// Update is called once per frame
	void 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)
	{
		//注解1
		 path  =  "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项目。


2017-10-07 18:25:55 u011967006 阅读数 10459

这次演示以,安卓原生操作系统 Nexus_6手机进行操作:
这里写图片描述


AndroidManifest.xml配置相关权限:
这里写图片描述

    <!-- 增加权限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

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

关于 /mnt/sdcard/ 与 Environment.getExternalStorageDirectory()获取路径的差异:
Environment.getExternalStorageDirectory() 在Android手机上获取的路径是:/storage/sdcard/ 或者是 /storage/emulated/0/ 等等;

其实在Linux文件系统中 /mnt/sdcard/ 去关联了 /storage/sdcard/ 或者是 /storage/emulated/0/ 等等;

请看图:
这里写图片描述

请看图,这个两个路径不同,访问的地址目录确是一模一样的:
这里写图片描述


// 在SD卡目录下创建文件
File file = new File(Environment.getExternalStorageDirectory(), "mysdcard.txt");
Log.d(TAG, "file.exists():" + file.exists() + " file.getAbsolutePath():"+ file.getAbsolutePath());
if (file.exists()) {
    file.delete();
    file.createNewFile();
}
// Toast.makeText(MainActivity.this, "SD卡目录下创建文件成功...", Toast.LENGTH_LONG).show();
Log.d(TAG, "SD卡目录下创建文件成功...");
// 在SD卡目录下的文件,写入内容
FileWriter fw = new FileWriter(file);
fw.write("我的sdcard内容.....");
fw.close();
// Toast.makeText(MainActivity.this, "SD卡写入内容完成...",Toast.LENGTH_LONG).show();
Log.d(TAG, "SD卡写入内容完成...");
// 读取SD卡文件里面的内容
FileReader fr = new FileReader("/mnt/sdcard/mysdcard.txt");
BufferedReader r = new BufferedReader(fr);
String result = r.readLine();
Log.d(TAG, "SD卡文件里面的内容:" + result);

执行结果:
这里写图片描述

这里写图片描述


谢谢大家的观看,更多精彩技术博客,会不断的更新,请大家访问,
刘德利CSDN博客, http://blog.csdn.net/u011967006