今天看了一道題,現在總結一下里面使用到的知識點;
1.assets檔案的訪問:
原文出處:http://blog.csdn.net/fengyuzhengfan/article/details/38360017
public class ImgTestActivity extends Activity implements OnClickListener{
ImageView left_arrow;
ImageView iv_content;
ImageView right_arrow;
InputStream is = null; ArrayList<String> imgFileNameStr=new ArrayList<String>(); //儲存是圖片的檔名集合
int currentIndex=0;//表示當前選擇中的圖片
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.imgtest_activity);
initView();
try {
String[] fileName = getAssets().list("");//獲取到assets資料夾下的所有目錄;
//獲取內容[images, lz01.jpg, lz02bl.jpg, lz03lyou.jpg, lz04lyuan.jpg, sounds, webkit] //遍歷所有的檔案;
for(String fString:fileName){
File fFile=new File(fString);
if(!fFile.isDirectory()){
//呼叫該方法判斷是否是圖片
if(isPict(fString)){
//如果是圖片就將檔名儲存到集合中
imgFileNameStr.add(fString);
}
}
}
} catch (IOException e1) {
e1.printStackTrace();
} setImageContent(currentIndex);
} private void setImageContent(int currentIndex) {
//先將第一張圖片獲取出來
try {
//該方法將集合中的檔名取出;轉換為InputStream;
is = getAssets().open(imgFileNameStr.get(currentIndex));
} catch (IOException e) {
e.printStackTrace();
}
//設定給ImageView
Bitmap bitmap=BitmapFactory.decodeStream(is);
iv_content.setImageBitmap(bitmap); }
/**
* @Title: isPict * @Description: 判斷給出的檔名是不是一張圖片 * @param @param fString
*/
private boolean isPict(String fString) {
try {
is = getAssets().open(fString);
byte[] buffer = new byte[2]; //檔案型別程式碼
String filecode = ""; //檔案型別
String fileType = ""; //通過讀取出來的前兩個位元組來判斷檔案型別
if (is.read(buffer) != -1) {
for (int i = 0; i < buffer.length; i++) { //獲取每個位元組與0xFF進行與運算來獲取高位,
// 這個讀取出來的資料不是出現負數 //並轉換成字串
filecode+=Integer.toString((buffer[i]&0xFF));
} // 把字串再轉換成Integer進行型別判斷
switch (Integer.parseInt(filecode))
{ case 7790: fileType = "exe";
break;
case 7784:
fileType = "midi";
break;
case 8297:
fileType = "rar";
break;
case 8075:
fileType = "zip";
break;
case 255216:
fileType = "jpg";
break;
case 7173:
fileType = "gif";
break;
case 6677:
fileType = "bmp";
break;
case 13780:
fileType = "png";
break;
default:
fileType = "unknown type: " + filecode;
}
}
System.out.println(fileType);
if (fileType.equals("png") || fileType.equals("gif") || fileType.equals("jpg")) {
return true;
} else {
return false;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
} private void initView() {
left_arrow = (ImageView) findViewById(R.id.left_arrow);
iv_content = (ImageView) findViewById(R.id.iv_content);
right_arrow = (ImageView) findViewById(R.id.right_arrow);
left_arrow.setOnClickListener(this);
right_arrow.setOnClickListener(this);
} @Override
public void onClick(View v) {
switch (v.getId()) { //TODO 點選按鈕切換圖片
case R.id.left_arrow: currentIndex++;
if(currentIndex>imgFileNameStr.size()-1){
currentIndex=0; setImageContent(currentIndex);
}else {
setImageContent(currentIndex);
}
break;
case R.id.right_arrow:
currentIndex--;
if (currentIndex < 0) {
currentIndex = imgFileNameStr.size() - 1;
setImageContent(currentIndex);
} else {
setImageContent(currentIndex);
}
break;
default:
break;
}
}
}
public static String createFilename() {
File file = new File(ImageUtils.UPLOAD_IMAGE_PATH);
if (!file.exists()) {
file.mkdirs();// 建立資料夾
}
@SuppressWarnings("static-access")
String fileName =ImageUtils.UPLOAD_IMAGE_PATH + new DateFormat().format("yyyyMMdd_hhmmss", Calendar.getInstance(Locale.CHINA)) + ".jpg";
return fileName;
}
Uri uri=Uri.fromFile(new File(createFilename()));
bitmap = BitmapFactory.decodeStream(context.getContentResolver().openInputStream(uri), null, opts);
預前知識:
Android資原始檔分類:
Android資原始檔大致可以分為兩種:
第一種是res目錄下存放的可編譯的資原始檔:
這種資原始檔系統會在R.java裡面自動生成該資原始檔的ID,所以訪問這種資原始檔比較簡單,通過R.XXX.ID即可;
第二種是assets目錄下存放的原生資原始檔:
因為系統在編譯的時候不會編譯assets下的資原始檔,所以我們不能通過R.XXX.ID的方式訪問它們。那我麼能不能通過該資源的絕對路徑去訪問它們呢?因為apk安裝之後會放在/data/app/**.apk目錄下,以apk形式存在,asset/res和被繫結在apk裡,並不會解壓到/data/data/YourApp目錄下去,所以我們無法直接獲取到assets的絕對路徑,因為它們根本就沒有。
還好Android系統為我們提供了一個AssetManager工具類。
檢視官方API可知,AssetManager提供對應用程式的原始資原始檔進行訪問;這個類提供了一個低級別的API,它允許你以簡單的位元組流的形式開啟和讀取和應用程式繫結在一起的原始資原始檔。
問題一:中間有個方法可以直接返回對應drawable物件;然後設定給ImageView,回去再看一下API物件;
iv_contanct_photo.setImageBitmap(BitmapFactory.decodeResource(context.getResources(), R.mipmap.tianjia));
AssetManager類
概述:
提供對應用程式的原始資原始檔進行訪問;這個類提供了一個低級別的API,它允許你以簡單的位元組流的形式開啟和讀取和應用程式繫結在一起的原始資原始檔。通過getAssets()方法獲取AssetManager物件。
AssetManager類常用方法:
Public Methods |
|
final String[] |
list(String path) 返回指定路徑下的所有檔案及目錄名。 |
final InputStream |
open(String fileName) 使用 ACCESS_STREAMING模式開啟assets下的指定檔案。. |
final InputStream |
open(String fileName, int accessMode) 使用顯示的訪問模式開啟assets下的指定檔案. |
應用例項
1.載入assets目錄下的網頁:
//載入assets/win8_Demo/目錄下的index.html網頁
webView.loadUrl("file:///android_asset/win8_Demo/index.html");
說明:這種方式可以載入assets目錄下的網頁,並且與網頁有關的css,js,圖片等檔案也會的載入。
2.訪問assets目錄下的資原始檔:
AssetManager.open(String filename),返回的是一個InputSteam型別的位元組流,這裡的filename必須是檔案比如
(aa.txt;img/semll.jpg),而不能是資料夾。
3.獲取assets的檔案及目錄名:
//獲取assets目錄下的所有檔案及目錄名,content(當前的上下文如Activity,Service等ContextWrapper的子類的
都可以)
String fileNames[] =context.getAssets().list(path);
4.將assets下的檔案複製到SD卡:
- /**
- * 從assets目錄中複製整個資料夾內容
- * @param context Context 使用CopyFiles類的Activity
- * @param oldPath String 原檔案路徑 如:/aa
- * @param newPath String 複製後路徑 如:xx:/bb/cc
- */
- public void copyFilesFassets(Context context,String oldPath,String newPath) {
- try {
- String fileNames[] = context.getAssets().list(oldPath);//獲取assets目錄下的所有檔案及目錄名
- if (fileNames.length > 0) {//如果是目錄
- File file = new File(newPath);
- file.mkdirs();//如果資料夾不存在,則遞迴
- for (String fileName : fileNames) {
- copyFilesFassets(context,oldPath + "/" + fileName,newPath+"/"+fileName);
- }
- } else {//如果是檔案
- InputStream is = context.getAssets().open(oldPath);
- FileOutputStream fos = new FileOutputStream(new File(newPath));
- byte[] buffer = new byte[1024];
- int byteCount=0;
- while((byteCount=is.read(buffer))!=-1) {//迴圈從輸入流讀取 buffer位元組
- fos.write(buffer, 0, byteCount);//將讀取的輸入流寫入到輸出流
- }
- fos.flush();//重新整理緩衝區
- is.close();
- fos.close();
- }
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- //如果捕捉到錯誤則通知UI執行緒
- MainActivity.handler.sendEmptyMessage(COPY_FALSE);
- }
- }
// 測試三:遍歷asset下某個資料夾中的所有圖片資源
try {
InputStream is=null;
Bitmap bitmap=null;
String dirPath="ml_lszn_Fresh";
String photoName=null;
AssetManager assetManager = getAssets();
//使用list()方法獲取某資料夾下所有檔案的名字
String [] photos=assetManager.list(dirPath);
for (int i = 0; i < photos.length; i++) {
photoName=photos[i];
//利用dirPath+"/"+photoName組拼某檔案完整路徑
is = assetManager.open(dirPath+"/"+photoName);
bitmap = BitmapFactory.decodeStream(is);
System.out.println("測試三: i="+i+" ,width=" + bitmap.getWidth() + " ,height="+ bitmap.getHeight());
}
} catch (Exception e) {
System.out.println("異常資訊:" + e.toString());
} }
5.使用assets目錄下的圖片資源:
- InputStream is=getAssets().open("wpics/0ZR424L-0.jpg");
- Bitmap bitmap=BitmapFactory.decodeStream(is);
- imgShow.setImageBitmap(bitmap);
6.播放assets目錄下的音樂
首先,獲取通過openFd()的方法獲取asset目錄下指定檔案的AssetFileDescriptor物件。
其次,通過MediaPlayer物件的setDataSource (FileDescriptorfd, longoffset, long length)方法載入音樂檔案。
最後,呼叫prepare方法準備音樂,start方法開始播放音樂。
預備知識:
AssetFileDescriptor簡介:
在AssetManager中一項的檔案描述符。這提供你自己開啟的FileDescriptor可用於讀取的資料,以及在檔案中的
偏移量和長度的該項的資料。
可以通過AssetManager的openFd()的方法獲取asset目錄下指定檔案的AssetFileDescriptor物件。
常用方法:
Public Methods |
|
FileInputStream |
createInputStream() 為asset建立並返回一個自動關閉的輸入流。 |
FileOutputStream |
createOutputStream() 為asset建立並返回一個自動關閉的輸出流。 |
FileDescriptor |
getFileDescriptor() 返回可用於讀取檔案中的資料的FileDescriptor物件。 |
long |
getLength() 返回該asset中項的資料的總位元組數。 |
long |
getStartOffset() 返回asset中項的資料位元組開始偏移。 |
具體程式碼:
- // 開啟指定音樂檔案,獲取assets目錄下指定檔案的AssetFileDescriptor物件
- AssetFileDescriptor afd = am.openFd(music);
- mPlayer.reset();
- // 使用MediaPlayer載入指定的聲音檔案。
- mPlayer.setDataSource(afd.getFileDescriptor(),
- afd.getStartOffset(), afd.getLength());
- // 準備聲音
- mPlayer.prepare();
- // 播放
- mPlayer.start();