国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

簡單說說Android中如何使用攝像頭和相冊

2019-10-22 18:10:32
字體:
供稿:網(wǎng)友

很多 APP 應(yīng)用都有用戶頭像功能,用戶既可以調(diào)用攝像頭馬上拍一張美美的自拍,也可以打開相冊選取一張心儀的照片作為頭像。

1 調(diào)用攝像頭

布局文件:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:id="@+id/activity_main"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:orientation="vertical">  <!--拍照按鈕-->  <Button android:id="@+id/open_photo"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:text="拍照"    />  <!--照片展示-->  <ImageView    android:id="@+id/img"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:layout_gravity="center_horizontal"    /></LinearLayout>

活動類代碼:

public class MainActivity extends AppCompatActivity {  private static final String TAG = "MainActivity";  public static final int OPEN_PHOTO_REQUEST_CODE = 1;  private Uri imgUrl = null;  private ImageView imageView;  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    //為按鈕添加【打開攝像頭】事件    findViewById(R.id.open_photo).setOnClickListener(new View.OnClickListener() {      @Override      public void onClick(View v) {        File file = new File(getExternalCacheDir(), "imageView.jpg");//存儲照片        if (file.exists()) {          file.delete();        }        try {          file.createNewFile();        } catch (IOException e) {          e.printStackTrace();        }        if (Build.VERSION.SDK_INT >= 24) {//版本高于 7.0          imgUrl = FileProvider.getUriForFile(MainActivity.this, "net.deniro.camera.fileProvider", file);        } else {          imgUrl = Uri.fromFile(file);        }        //打開攝像頭        Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");        intent.putExtra(MediaStore.EXTRA_OUTPUT, imgUrl);//指定圖片輸出地址        startActivityForResult(intent, OPEN_PHOTO_REQUEST_CODE);      }    });    //顯示拍攝的照片    imageView = (ImageView) findViewById(R.id.img);  }  @Override  protected void onActivityResult(int requestCode, int resultCode, Intent data) {    Log.d(TAG, "requestCode: " + requestCode);    Log.d(TAG, "imgUrl: " + imgUrl);    switch (requestCode) {      case OPEN_PHOTO_REQUEST_CODE:        if (resultCode == RESULT_OK) {          try {//解析圖片并顯示            Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imgUrl));            imageView.setImageBitmap(bitmap);          } catch (FileNotFoundException e) {            e.printStackTrace();          }        }        break;      default:        break;    }  }}

getExternalCacheDir() 可以獲取 SD 卡中專門用于存放當(dāng)前應(yīng)用緩存數(shù)據(jù)的位置。Android6.0+ 開始,讀取存放在 SD 卡中的任何其它目錄都被列為危險權(quán)限,因此需要設(shè)定運(yùn)行時權(quán)限才可以操作,這里使用了與應(yīng)用關(guān)聯(lián)的目錄,所以就可以跳過這一步。

getUriForFile() 方法接收三個參數(shù):Context對象、任意唯一的字符串與 File對象。從 android 7.0+ 系統(tǒng)開始,直接使用本地真實的路徑被認(rèn)為是不安全的,會拋出一個 FileExposedException 異常,而 FileProvider 是一種特殊的內(nèi)容提供器,它使用與內(nèi)容提供器類似的機(jī)制對數(shù)據(jù)進(jìn)行保護(hù)。

在 AndroidManifest.xml 中注冊剛才定義的內(nèi)容提供器:

<provider  android:name="android.support.v4.content.FileProvider"  android:authorities="net.deniro.camera.fileProvider"  android:exported="false"  android:grantUriPermissions="true">  <!--指定 Uri 的共享路徑-->  <meta-data    android:name="android.support.FILE_PROVIDER_PATHS"    android:resource="@xml/file_paths" /></provider>

android:authorities 就是我們在 FileProvider.getUriForFile() 方法中傳入的第二個參數(shù)。

使用 <meta-data> 指定了 Uri 的共享路徑,在此引用了 xml 資源。

在 IDEA 中可以通過快捷鍵 ctrl + enter 直接在 xml 文件夾下創(chuàng)建文件:

Android,攝像頭,相冊

快捷創(chuàng)建

Android,攝像頭,相冊

默認(rèn)為 xml 文件夾

file_paths.xml:

<?xml version="1.0" encoding="utf-8"?><PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">  <!--指定共享的 Uri -->  <!--name:名稱(任意)-->  <!--path:共享的路徑,空值表示共享整個 SD 卡-->  <external-path name="img" path=""/></PreferenceScreen>

Android 4.4 之前,還需要設(shè)置訪問 SD 卡應(yīng)用的關(guān)聯(lián)目錄權(quán)限:

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

拍照后效果:

Android,攝像頭,相冊

2 從相冊中選取照片

直接從相冊中選取一張現(xiàn)有的照片比打開攝像頭拍一張照片更加常用,因此,一個好的 app,應(yīng)該將這兩種方式都實現(xiàn)。

修改布局文件,加入【打開相冊】按鈕:

<!--打開相冊選取照片--><Button  android:id="@+id/choose_photo"  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:text="打開相冊"  />

在活動類中加入打開相冊選取照片的處理邏輯:

/** * 打開相冊請求碼 */public static final int CHOOSE_PHOTO_REQUEST_CODE = 2;...@Overrideprotected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_main);  ...  //打開相冊  findViewById(R.id.choose_photo).setOnClickListener(new View.OnClickListener() {    @Override    public void onClick(View v) {      if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {        ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},            CHOOSE_PHOTO_REQUEST_CODE);      } else {        openAlbum();      }    }});/** * 打開相冊 */private void openAlbum() {  Intent intent = new Intent("android.intent.action.GET_CONTENT");  intent.setType("image/*");  startActivityForResult(intent, CHOOSE_PHOTO_REQUEST_CODE);}/** * 請求 WRITE_EXTERNAL_STORAGE 權(quán)限 * * 相冊中的照片一般是存放在 SD 卡上的,所以從 SD 卡中讀取照片需要申請權(quán)限 * * WRITE_EXTERNAL_STORAGE 表示讀寫 SD 卡的能力權(quán)限 * @param requestCode * @param permissions * @param grantResults */@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {  switch (requestCode) {    case CHOOSE_PHOTO_REQUEST_CODE:      if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {        openAlbum();      } else {        Toast.makeText(this, "被拒絕啦", Toast.LENGTH_SHORT).show();      }      break;    default:      break;  }  super.onRequestPermissionsResult(requestCode, permissions, grantResults);}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {  Log.d(TAG, "requestCode: " + requestCode);  Log.d(TAG, "imgUrl: " + imgUrl);  switch (requestCode) {    case OPEN_PHOTO_REQUEST_CODE:      if (resultCode == RESULT_OK) {        try {//解析圖片并顯示          Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imgUrl));          imageView.setImageBitmap(bitmap);        } catch (FileNotFoundException e) {          e.printStackTrace();        }      }      break;    case CHOOSE_PHOTO_REQUEST_CODE:      if (Build.VERSION.SDK_INT >= 19) {//4.4 及以上系統(tǒng)        handleFor4_4(data);      } else {        handleForBefore4_4(data);      }      break;    default:      break;  }}/** * 處理相片 * android 4.4- * * @param data */private void handleForBefore4_4(Intent data) {  display(getImagePath(data.getData(),null));}/** * 處理相片 * android 4.4+ * * @param data */@RequiresApi(api = Build.VERSION_CODES.KITKAT)private void handleFor4_4(Intent data) {  String imagePath = null;  Uri uri = data.getData();//需要解析  if (DocumentsContract.isDocumentUri(this, uri)) {//是 Document 類型,使用 document id 來處理    String documentId = DocumentsContract.getDocumentId(uri);    String mediaDocumentAuthority = "com.android.providers.media.documents";    String downloadDocumentAuthority = "com.android.providers.downloads.documents";    if (mediaDocumentAuthority.equals(uri.getAuthority())) {//media 格式      String id = documentId.split(":")[1];//數(shù)字格式的 ID      String selection = MediaStore.Images.Media._ID + "=" + id;      imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection);    } else if (downloadDocumentAuthority.equals(uri.getAuthority())) {      Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(documentId));      imagePath = getImagePath(contentUri, null);    }  } else if ("content".equalsIgnoreCase(uri.getScheme())) {//content 類型 uri    imagePath = getImagePath(uri, null);  } else if ("file".equalsIgnoreCase(uri.getScheme())) {//file 類型,則直接獲取路徑    imagePath = uri.getPath();  }  display(imagePath);}/** * 顯示 * @param path */private void display(String path) {  if(path==null){    Toast.makeText(this, "無法獲取圖片", Toast.LENGTH_SHORT).show();  }else{    imageView.setImageBitmap(BitmapFactory.decodeFile(path));  }}/** * 獲取圖片路徑 * * @param uri * @param selection * @return */private String getImagePath(Uri uri, String selection) {  String path = null;  Cursor cursor = getContentResolver().query(uri, null, selection, null, null);  if (cursor != null) {    if (cursor.moveToFirst()) {      path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));    }    cursor.close();  }  return path;}

這里請求了 WRITE_EXTERNAL_STORAGE 權(quán)限,以為相冊中的照片一般是存放在 SD 卡上的,所以從 SD 卡中讀取照片需要申請權(quán)限。WRITE_EXTERNAL_STORAGE 表示讀寫 SD 卡的能力權(quán)限。

為了兼容新老版本的手機(jī)(以 Android 4.4 為分水嶺),因為 Android 4.4+ 的版本返回的 Uri 需要解析才可以使用。

點擊【打開相冊】按鈕,會彈出讀取 SD 卡的權(quán)限申請:

Android,攝像頭,相冊

選取照片后的效果:

Android,攝像頭,相冊

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持VEVB武林網(wǎng)。


注:相關(guān)教程知識閱讀請移步到Android開發(fā)頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 耿马| 长沙县| 延庆县| 金乡县| 大厂| 通许县| 当涂县| 沙田区| 增城市| 大埔县| 梁河县| 瓮安县| 雷波县| 平湖市| 隆化县| 平顶山市| 三明市| 二手房| 陇川县| 陈巴尔虎旗| 凤庆县| 永泰县| 察雅县| 滨海县| 犍为县| 新邵县| 西昌市| 长阳| 三都| 鹤庆县| 伊宁市| 墨江| 广宁县| 青田县| 阜城县| 五峰| 嘉善县| 淳安县| 沙田区| 社会| 锡林浩特市|