Chuyển đến nội dung chính

Hướng dẫn lập trình Android Camera - Android Tutorial

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>
Thiết kế giao diện ví dụ:
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"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    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);

ACTION_IMAGE_CAPTURE_SECURE sẽ gọi ứng dụng Camera để chụp hình và trả về một Image được chụp từ Camera.
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

Bài đăng phổ biến từ blog này

Tổng hợp danh sách các trang web lấy backlink cực tốt (P.1)

Đi backlink  trong SEO là điều mà ai cũng phải biết và đầu tư cho nó nhiều nhất. Dưới đây, mình chia sẻ các trang web có thể đi backlink khá tốt cho mọi người. Mỗi ngày các bạn tạo 1 bài post sau đó post lên 10 trang trong tổng số 40 trang này, hôm sau cũng viết 1 bài khác rồi post lên 10 trang kế, khi hết thì quay vòng lại 10 trang đầu, mình sẽ update thêm các website nên các bạn cứ yên tâm không lo hết. (Các bạn nhớ bookmark lại kẻo quên trang mình nha :) ) Nếu các bạn không rõ về DA PA IN-EXTERNAL Links thì xem ở đây:  Các chỉ số quan trọng cần biết khi làm SEO ID URL DA PA Internal Links External Links Alexa Global Rank Alexa Local Rank 1 http://diendan.zing.vn/ 63,17 54,5 168 19 701 9 2 http://vatgia.com/ 62,61 57,34 984 23 8086 71 3 http://forum.ueh.edu.vn/ 49,82 38,88 555 43 92060 774 4 http://www.5giay.vn/ 47,12 55,72 445 12 43

Viết game flappy bird bằng HTML và JavaScript (P.1)

Hôm nay chúng ta sẽ viết một game tương tự flappy bird bằng HTML và JavaScript một cách đơn giản, bài viết không chỉ giúp bạn nâng cao khả năng lập tình HTML JS mà còn tạo ra 1 sản phẩm thú vị cho nên các bạn chịu khó theo dõi nha. Các bạn xem demo sản phẩm khi chúng ta hoàn thành trên fiddle:  Demo  đây chỉ là demo cơ bản thôi, khi xem xong bài viết này các bạn có thể làm hay hơn thế nữa :)). Nào ta bắt đầu thôi. HTML Canvas Đầu tiên để tạo game chúng ta cần tạo background cho nó, chúng ta sẽ dùng HTML Canvas , Canvas là một element tuyệt vời cho việc thiết kế game trong HTML. Chúng ta sẽ dùng Js để vẽ trên Canvas. Nếu các bạn chưa biết về Canvas mình có để link phía dưới để các bạn tìm hiểu nên hiện giờ cứ yên tâm mà xem tiếp nha. Bây giờ các bạn tạo 1 file html và nhập đoạn code sau: <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <style> canvas {

Xdebug, PhpStorm and Docker - Why it not working?

  Lately, i start new job with Magento, and while setup IDE for project i face problem with Xdebug, PhpStorm and Docker. It took me a lot of hours to find out and make it work. So i write this post to save some step for you guys also me some way to solve the stuck when we got. 1. How Xdebug work: Link  i founded this article with quite easy understand explanation how xdebug work, so spend some minutes to read it, we need to understans the thing we do to easy to solve it. 2: Define Xdebug is installed on server: With php -v you should see Xdebug showed. And with phpinfo() If you dont see it showed, it mean you have not installed it or it not enable Checking if you have enable extension from your php ini. Or if you have not installed it, consider its document: Link . 3. Now if you make sure xdebug installed but your break point at PhpStorm not break, continue these steps: In phpinfo(), make sure  xdebug.remote_enable is On cause you are using docker container, also checking  xdebug.remot