1. Android Camera
Đầu tiên các bạn tạo 1 project tên là: AndroidCameraDemo
Để lưu trữ ảnh chụp hoặc video vừa quay được trên thiết bị chúng ta cần cấu hình cho phép đọc và ghi dữ liệu vào thiết bị. Thêm 2 lệnh này vào AndroidManifest.xml.
<
uses-permission
android:name
=
"android.permission.WRITE_EXTERNAL_STORAGE"
/>
<
uses-permission
android:name
=
"android.permission.READ_EXTERNAL_STORAGE"
/>
AndroidManifest.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| <? xml version = "1.0" encoding = "utf-8" ?> package = "org.o7planning.androidcamerademo" > < uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" /> < uses-permission android:name = "android.permission.READ_EXTERNAL_STORAGE" /> < application android:allowBackup = "true" android:icon = "@mipmap/ic_launcher" android:label = "@string/app_name" android:supportsRtl = "true" android:theme = "@style/AppTheme" > < activity android:name = ".MainActivity" > < intent-filter > < action android:name = "android.intent.action.MAIN" /> < category android:name = "android.intent.category.LAUNCHER" /> </ intent-filter > </ activity > </ application > </ manifest > |
Hướng dẫn lập trình Android Camera - Android Studio tutorial |
activity_main.xml
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
| <? xml version = "1.0" encoding = "utf-8" ?> android:layout_width = "match_parent" android:layout_height = "match_parent" android:paddingBottom = "@dimen/activity_vertical_margin" android:paddingLeft = "@dimen/activity_horizontal_margin" android:paddingRight = "@dimen/activity_horizontal_margin" android:paddingTop = "@dimen/activity_vertical_margin" tools:context = " yourpackage .androidcamerademo.MainActivity" > < ImageView android:layout_width = "fill_parent" android:layout_height = "180dp" android:id = "@+id/imageView" android:layout_alignParentTop = "true" /> < VideoView android:layout_width = "wrap_content" android:layout_height = "180dp" android:id = "@+id/videoView" android:layout_below = "@+id/imageView" android:layout_alignParentLeft = "true" android:layout_alignParentStart = "true" /> < Button style = "?android:attr/buttonStyleSmall" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:text = "Capture Image" android:id = "@+id/button_image" android:layout_alignParentBottom = "true" android:layout_alignParentLeft = "true" android:layout_alignParentStart = "true" /> < Button style = "?android:attr/buttonStyleSmall" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:text = "Capture Video" android:id = "@+id/button_video" android:layout_alignTop = "@+id/button_image" android:layout_toRightOf = "@+id/button_image" android:layout_toEndOf = "@+id/button_image" /> </ RelativeLayout > |
Đối với Android Level >= 23, ta cần thiết lập code hỏi người dùng cho phép đọc và ghi dữ liệu vào thiết bị. Code hoàn thiện MainActivity ở dưới các bạn cứ xem giải thích trước rồi hãy code vào project.
// Khi yêu cầu hỏi người dùng được trả về (Chấp nhận hoặc không chấp nhận).
@Override
public
void
onRequestPermissionsResult(
int
requestCode,
String permissions[],
int
[] grantResults) {
super
.onRequestPermissionsResult(requestCode, permissions, grantResults);
//
switch
(requestCode) {
case
REQUEST_ID_READ_WRITE_PERMISSION: {
// Chú ý: Nếu yêu cầu bị hủy, mảng kết quả trả về là rỗng.
// Người dùng đã cấp quyền (đọc/ghi).
if
(grantResults.length >
1
&& grantResults[
0
] == PackageManager.PERMISSION_GRANTED
&& grantResults[
1
] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(
this
,
"Permission granted!"
, Toast.LENGTH_LONG).show();
this
.captureVideo();
}
// Hủy bỏ hoặc bị từ chối.
else
{
Toast.makeText(
this
,
"Permission denied!"
, Toast.LENGTH_LONG).show();
}
break
;
}
}
}
Để làm việc với Camera trong hệ điều hành Android, ứng dụng của ta sẽ gọi một intent không tường minh để yêu cầu một hành động đến Camera.
// Tạo một Intent không tường minh,
// để yêu cầu hệ thống mở Camera chuẩn bị chụp hình.
Intent intent =
new
Intent(MediaStore.ACTION_IMAGE_CAPTURE);
int
REQUEST_ID_IMAGE_CAPTURE =
100
;
// Start Activity chụp hình, và chờ đợi kết quả trả về.
this
.startActivityForResult(intent, REQUEST_ID_IMAGE_CAPTURE);
Dưới đây là code trong MainActivity, khá dài nên các bạn xem kĩ:
MainActivity.java
package org.o7planning.androidcamerademo; import android.Manifest; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.Toast; import android.widget.VideoView; import java.io.File; public class MainActivity extends AppCompatActivity { private Button buttonImage; private Button buttonVideo; private VideoView videoView; private ImageView imageView; private static final int REQUEST_ID_READ_WRITE_PERMISSION = 99 ; private static final int REQUEST_ID_IMAGE_CAPTURE = 100 ; private static final int REQUEST_ID_VIDEO_CAPTURE = 101 ; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); this .buttonImage = (Button) this .findViewById(R.id.button_image); this .buttonVideo = (Button) this .findViewById(R.id.button_video); this .videoView = (VideoView) this .findViewById(R.id.videoView); this .imageView = (ImageView) this .findViewById(R.id.imageView); this .buttonImage.setOnClickListener( new Button.OnClickListener() { @Override public void onClick(View v) { captureImage(); } }); this .buttonVideo.setOnClickListener( new Button.OnClickListener() { @Override public void onClick(View v) { askPermissionAndCaptureVideo(); } }); } private void captureImage() { // Tạo một Intent không tường minh, // để yêu cầu hệ thống mở Camera chuẩn bị chụp hình. Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // Start Activity chụp hình, và chờ đợi kết quả trả về. this .startActivityForResult(intent, REQUEST_ID_IMAGE_CAPTURE); } private void askPermissionAndCaptureVideo() { // Với Android Level >= 23 bạn phải hỏi người dùng cho phép đọc/ghi dữ liệu vào thiết bị. if (android.os.Build.VERSION.SDK_INT >= 23 ) { // Kiểm tra quyền đọc/ghi dữ liệu vào thiết bị lưu trữ ngoài. int readPermission = ActivityCompat.checkSelfPermission( this , Manifest.permission.READ_EXTERNAL_STORAGE); int writePermission = ActivityCompat.checkSelfPermission( this , Manifest.permission.WRITE_EXTERNAL_STORAGE); if (writePermission != PackageManager.PERMISSION_GRANTED || readPermission != PackageManager.PERMISSION_GRANTED) { // Nếu không có quyền, cần nhắc người dùng cho phép. this .requestPermissions( new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_ID_READ_WRITE_PERMISSION ); return ; } } this .captureVideo(); } private void captureVideo() { // Tạo một Intent không tường minh, // để yêu cầu hệ thống mở Camera chuẩn bị quay video. Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); // Thư mục lưu trữ ngoài. File dir = Environment.getExternalStorageDirectory(); if (!dir.exists()) { dir.mkdirs(); } String savePath = dir.getAbsolutePath() + "/myvideo.mp4" ; File videoFile = new File(savePath); Uri videoUri = Uri.fromFile(videoFile); // Chỉ định vị trí lưu file video khi quay. intent.putExtra(MediaStore.EXTRA_OUTPUT, videoUri); // Start Activity quay video, và chờ đợi kết quả trả về. this .startActivityForResult(intent, REQUEST_ID_VIDEO_CAPTURE); } // Khi yêu cầu hỏi người dùng được trả về (Chấp nhận hoặc không chấp nhận). @Override public void onRequestPermissionsResult( int requestCode, String permissions[], int [] grantResults) { super .onRequestPermissionsResult(requestCode, permissions, grantResults); // switch (requestCode) { case REQUEST_ID_READ_WRITE_PERMISSION: { // Chú ý: Nếu yêu cầu bị hủy, mảng kết quả trả về là rỗng. // Người dùng đã cấp quyền (đọc/ghi). if (grantResults.length > 1 && grantResults[ 0 ] == PackageManager.PERMISSION_GRANTED && grantResults[ 1 ] == PackageManager.PERMISSION_GRANTED) { Toast.makeText( this , "Permission granted!" , Toast.LENGTH_LONG).show(); this .captureVideo(); } // Hủy bỏ hoặc bị từ chối. else { Toast.makeText( this , "Permission denied!" , Toast.LENGTH_LONG).show(); } break ; } } } // Khi activy chụp hình (Hoặc quay video) hoàn thành, phương thức này sẽ được gọi. @Override protected void onActivityResult( int requestCode, int resultCode, Intent data) { super .onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_ID_IMAGE_CAPTURE) { if (resultCode == RESULT_OK) { Bitmap bp = (Bitmap) data.getExtras().get( "data" ); this .imageView.setImageBitmap(bp); } else if (resultCode == RESULT_CANCELED) { Toast.makeText( this , "Action canceled" , Toast.LENGTH_LONG).show(); } else { Toast.makeText( this , "Action Failed" , Toast.LENGTH_LONG).show(); } } else if (requestCode == REQUEST_ID_VIDEO_CAPTURE) { if (resultCode == RESULT_OK) { Uri videoUri = data.getData(); Log.i( "MyLog" , "Video saved to: " + videoUri); Toast.makeText( this , "Video saved to:\n" + videoUri, Toast.LENGTH_LONG).show(); this .videoView.setVideoURI(videoUri); this .videoView.start(); } else if (resultCode == RESULT_CANCELED) { Toast.makeText( this , "Action Cancelled." , Toast.LENGTH_LONG).show(); } else { Toast.makeText( this , "Action Failed" , Toast.LENGTH_LONG).show(); } } } } |
Ok bây giờ bạn có thể build APK và test trên thiết bị android của mình rồi.
Bonus: Nếu các muốn chọn ảnh từ thư viện thay vì chụp hình thì làm như sau.
Trước hết các bạn thêm 1 button vào giao diện, sau đó trong MainActivity ta thêm button đó vào onCreate() :
this.chonThuVien = (Button) rootView.findViewById(R.id.button_chon_thuvien);
chonThuVien.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View view) {
getImageFromAlbum();
}
});
Thêm 1 biến request ở đầu:
private static final int REQUEST_ID_IMAGE_ALBUM = 101;
Ta khai báo hàm getImageFromAlbum:
private void getImageFromAlbum() {
try {
Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
i.setType("image/*");
this.startActivityForResult(i, REQUEST_ID_IMAGE_ALBUM);
} catch (Exception exp) {
Toast.makeText(getContext(), "Error: " + exp.toString(), Toast.LENGTH_SHORT).show();
}
}
Thêm đoạn code xử lý sự kiện ta mới thêm vào, onActivityResult():
else if (requestCode == REQUEST_ID_IMAGE_ALBUM) {
if (resultCode == RESULT_OK) {
final Uri imagesUri = data.getData();
final InputStream imageStream;
try {
imageStream = getContext().getContentResolver().openInputStream(imagesUri);
final Bitmap selectedImage= BitmapFactory.decodeStream(imageStream);
this.imageView.setImageBitmap(selectedImage);
Toast.makeText(getContext(), "Upload duoc", Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
Toast.makeText(getContext(), "Something went wrong", Toast.LENGTH_SHORT).show();
}
}
Xong rồi các bạn build lại APK và test lại thử. Nếu gặp vấn đề gì thì comment bên dưới nha, mình sẽ giải đáp trong vòng 24h. Chúc các bạn học tốt.
Nhận xét
Đăng nhận xét