第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

全部開發(fā)者教程

Android 入門教程

菜單類控件
菜單:Menu
并發(fā)編程
多線程

相機(jī):Camera

相機(jī)現(xiàn)在已經(jīng)不僅僅是手機(jī)必備神器了,甚至相機(jī)的拍照質(zhì)量已經(jīng)是很多人買手機(jī)的首選條件了。而對于相機(jī)而言主要有兩大功能:拍照片和拍視頻。Android 為此兩種方式:

  • 相機(jī) intent
  • 相機(jī) API
    本節(jié)我們就一起來看看相機(jī)的具體用法。

1. 打開 Camera 的兩大方式

目前市面上絕大多數(shù)的 Android 手機(jī)是有前后兩個攝像頭,當(dāng)然有部分特殊機(jī)型會存在其他的情況,本節(jié)主要針對雙攝像頭設(shè)備做解析。
在前面有提到過,通常使用相機(jī)有兩大方式:“Intent”和“API”。最大的差別就是“Intent”是跳轉(zhuǎn)到系統(tǒng)提供的相機(jī)頁面,而使用“API”是封閉在自己的 App 中使用相機(jī)。我們可以通過“Intent”直接打開系統(tǒng)提供的相機(jī) Activity,在用戶拍攝完成之后系統(tǒng) Activity 會通知我們拍攝結(jié)果,然后拿到拍攝的圖片或者視頻。而直接通過 API 就需要我們?nèi)ラ_發(fā)一整套相機(jī)的控制頁面,自行完成照片 / 視頻的拍攝進(jìn)而直接拿到用戶拍攝的結(jié)果。

2. Camera 的基本用法

我們分別看看這兩種打開方式的使用方法:

2.1 使用 Intent 打開

通過使用 MediaStore 類提供的兩個 Intnet 常量,可以直接將相機(jī)操作托管給 Android 系統(tǒng)而無需創(chuàng)建 Camera 實(shí)例:

  • ACTION_IMAGE_CAPTURE:
    拍攝照片
  • ACTION_VIDEO_CAPTURE:
    拍攝視頻

2.2 使用 API 打開

采用 API 打開會讓整個相機(jī)程序都封閉在自己的 APP 中完成,這里需要明確幾個概念:

  1. Camera 類
    使用 API 之前需要創(chuàng)建 Camera 實(shí)例,然后通過 API 來初始化 Camera 進(jìn)而拿到實(shí)時拍攝的畫面

  2. SurfaceView
    用來渲染視頻實(shí)時畫面的 View

采用 Intent 打開相機(jī)的方法非常簡單,接下來我們?nèi)淌褂?Camera API 來實(shí)現(xiàn)一下相機(jī)功能。

3. Camera 使用示例

使用 API 來拍照會相對比較麻煩一點(diǎn),首先需要獲取權(quán)限,那么對于 Android 6.0 版本以上的系統(tǒng)除了要在 Manifest 里面加入 Camera 權(quán)限之外,還需要動態(tài)獲取權(quán)限,這個可能大家在用一些比較老的教程示例時會踩坑。
獲取到權(quán)限就可以打開 Camera 了,然后拿到 Camera 實(shí)例設(shè)置一個 SurfaceView 來渲染預(yù)覽頁面,在用戶需要拍照的時候調(diào)用 Camera 的takePicture()方法獲取當(dāng)前幀,最后保存輸出到文件中或者在新的 Activity 中展示,這樣就算完成了一次拍照閉環(huán)。

3.1 Camera 拍照邏輯

首先看看整個拍照的代碼如下:


package com.emercy.myapplication;

import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class MainActivity extends Activity {

    public static final String CAMERA_PATH = "path";
    public static final String CAMERA_IMG = "img";

    private SurfaceView mSurfaceView;
    private Button mTakePhoto;
    private Camera mCamera = null;
    private SurfaceHolder.Callback mCallback = new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            startPreview();
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            stopPreview();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getPermission();

        bindViews();
    }

    /**
     * 獲取權(quán)限
     */
    private void getPermission() {
        if (Build.VERSION.SDK_INT > 22) {
            if (checkSelfPermission(android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                //先判斷有沒有權(quán)限 ,沒有就在這里進(jìn)行權(quán)限的申請
                requestPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100);
            } else {
                //說明已經(jīng)獲取到攝像頭權(quán)限了
                Log.i("Imooc Camera", "已經(jīng)獲取了權(quán)限");
            }
        } else {
            //這個說明系統(tǒng)版本在6.0之下,不需要動態(tài)獲取權(quán)限。
            Log.i("Imooc Camera", "這個說明系統(tǒng)版本在6.0之下,不需要動態(tài)獲取權(quán)限。");
        }
    }

    private void bindViews() {
        mSurfaceView = (SurfaceView) findViewById(R.id.sfv_preview);
        mTakePhoto = (Button) findViewById(R.id.btn_take);
        mSurfaceView.getHolder().addCallback(mCallback);

        mTakePhoto.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mCamera.takePicture(null, null, new Camera.PictureCallback() {
                    @Override
                    public void onPictureTaken(byte[] data, Camera camera) {
                        String path;
                        if (TextUtils.isEmpty(path = savePhoto(data))) {
                            Intent it = new Intent(MainActivity.this, PreviewActivity.class);
                            it.putExtra(CAMERA_PATH, path);
                            startActivity(it);
                        } else {
                            Toast.makeText(MainActivity.this, "拍照失敗", Toast.LENGTH_SHORT).show();
                        }
                    }
                });
            }
        });
    }

    private String savePhoto(byte[] bytes) {
        try {
            File file = File.createTempFile(CAMERA_IMG, "");
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(bytes);
            fos.flush();
            fos.close();
            return file.getAbsolutePath();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

    private void startPreview() {
        mCamera = Camera.open();
        try {
            mCamera.setPreviewDisplay(mSurfaceView.getHolder());
            mCamera.setDisplayOrientation(90);   // 讓相機(jī)旋轉(zhuǎn)90度
            mCamera.startPreview();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void stopPreview() {
        mCamera.stopPreview();
        mCamera.release();
        mCamera = null;
    }
}

里面涉及到的幾個新概念大家需要注意,然后記得在SurfaceHolder.Callback()surfaceCreated()中啟動預(yù)覽,在surfaceDestroyed()方法中要停止預(yù)覽,其他的基本上按照步驟來不會有什么問題。

3.2 相機(jī)布局

目前市面上有很多相機(jī) App,各種布局千變?nèi)f化,大家完全可以按照自己的喜好來進(jìn)行設(shè)計(jì)。這里只做一個拍照預(yù)覽和拍照按鈕。

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <SurfaceView
        android:id="@+id/sfv_preview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <Button
        android:id="@+id/btn_take"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|center"
        android:text="拍照" />

</FrameLayout>

3.3 照片回看頁面

點(diǎn)擊“拍照” Button 獲取到當(dāng)前畫面之后,我們可以就可以按照自己的邏輯對圖片進(jìn)行操作了。比如可以通過 Http 上傳、通過 Socket 發(fā)送給其他設(shè)備、保存到本地、或者傳遞給其他 App 等。本例子中將圖片傳遞給另一個 Activity 專門用于查看圖片,下面是 PhotoActivity 的代碼:

package com.emercy.myapplication;

import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.widget.ImageView;

import java.io.File;

import static com.emercy.myapplication.MainActivity.CAMERA_PATH;

public class PhotoActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ImageView img = new ImageView(this);
        String path = getIntent().getStringExtra(CAMERA_PATH);
        if (path != null) {
            img.setImageURI(Uri.fromFile(new File(path)));
        }
        setContentView(img);
    }
}

通過 Intent 接收圖片路徑,然后展示在 ImageView 上,需要注意的是PhotoActivity 中是直接將 ImageView 作為參數(shù)直接設(shè)置給了 SetContentView(),這樣相當(dāng)于布局文件中只有一個 ImageView 的寫法。

最后別忘了在 Manifest 當(dāng)中添加權(quán)限:

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

編譯運(yùn)行效果如下:

camera

點(diǎn)擊拍照進(jìn)入 PhotoActivity,展示的就是我們拍照的畫面。

4. 小結(jié)

本節(jié)學(xué)習(xí)了一個手機(jī)上必不可少的設(shè)備,通過相機(jī)我們可以拍攝照片或者視頻,Android 系統(tǒng)提供了兩大打開方式:Intent 調(diào)用系統(tǒng)相機(jī) Activitiy或者用 Camera API 自行實(shí)現(xiàn)拍照功能。第一種非常簡單,將所有的相機(jī)操作都托管給系統(tǒng),我們只關(guān)心最終用戶拍攝的結(jié)果;而第二種就需要我們自己初始化 Camera 對象從而實(shí)現(xiàn)拍攝,在實(shí)際開發(fā)中如果你的功能是和拍攝強(qiáng)相關(guān),需要一些定制化的拍攝體驗(yàn),那么一定要使用第二種方式來自己實(shí)現(xiàn) Camera,但是如果你只是一個簡單的拍照獲取圖片,那么第一種會讓你事半功倍。