激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Android - 簡單說說Android中如何使用攝像頭和相冊

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

2022-02-25 15:19deniro Android

本篇文章主要介紹了簡單說說Android中如何使用攝像頭和相冊,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

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

1 調用攝像頭

布局文件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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>

活動類代碼:

?
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
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 卡中專門用于存放當前應用緩存數據的位置。Android6.0+ 開始,讀取存放在 SD 卡中的任何其它目錄都被列為危險權限,因此需要設定運行時權限才可以操作,這里使用了與應用關聯的目錄,所以就可以跳過這一步。

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

在 AndroidManifest.xml 中注冊剛才定義的內容提供器:

?
1
2
3
4
5
6
7
8
9
10
<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() 方法中傳入的第二個參數。

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

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

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

快捷創建

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

默認為 xml 文件夾

file_paths.xml:

?
1
2
3
4
5
6
7
<?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 之前,還需要設置訪問 SD 卡應用的關聯目錄權限:

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

拍照后效果:

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

2 從相冊中選取照片

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

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

?
1
2
3
4
5
6
7
<!--打開相冊選取照片-->
<Button
  android:id="@+id/choose_photo"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:text="打開相冊"
  />

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

?
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
/**
 * 打開相冊請求碼
 */
public static final int CHOOSE_PHOTO_REQUEST_CODE = 2;
...
@Override
protected 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 權限
 *
 * 相冊中的照片一般是存放在 SD 卡上的,所以從 SD 卡中讀取照片需要申請權限
 *
 * WRITE_EXTERNAL_STORAGE 表示讀寫 SD 卡的能力權限
 * @param requestCode
 * @param permissions
 * @param grantResults
 */
@Override
public 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);
}
 
@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;
    case CHOOSE_PHOTO_REQUEST_CODE:
      if (Build.VERSION.SDK_INT >= 19) {//4.4 及以上系統
        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];//數字格式的 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 權限,以為相冊中的照片一般是存放在 SD 卡上的,所以從 SD 卡中讀取照片需要申請權限。WRITE_EXTERNAL_STORAGE 表示讀寫 SD 卡的能力權限。

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

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

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

選取照片后的效果:

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

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://www.jianshu.com/p/1bd723fc4826

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: vidz 98hd| 草草视频在线 | 91 视频网站 | 久久精品23 | 久久国产精品小视频 | 美国一级免费视频 | 亚洲男人一区 | 国产成人高清成人av片在线看 | 国产黄色网页 | 精品一二三区视频 | 国产精品视频自拍 | 国产精品亚洲一区二区三区在线观看 | 神秘电影91 | 鲁一鲁一鲁一鲁一曰综合网 | 99视频网址| 久久99精品久久久久久小说 | 国产羞羞视频在线观看 | 中文字幕欧美在线 | 成人在线免费视频播放 | 黄色二区三区 | 国产成人精品一区在线播放 | 国产成人免费高清激情视频 | 久久久久久久久久久久久久久伊免 | 激情视频在线播放 | 亚洲成人欧美在线 | 97久色| 一级做a爱片久久 | 欧美三级一级 | 黄色av网站在线观看 | 91网站免费观看 | 国产成人高清在线 | 国内免费视频成人精品 | 久久国产精品久久久久久电车 | 久久精品小短片 | 精品国产一区二区三 | 国产精品久久久免费看 | 国产无遮挡一区二区三区毛片日本 | 国产免费乱淫av | 羞羞草视频 | 少妇淫片免费一级毛片 | 欧美14一15sex性hd |