sponsored links

鴻蒙APP開發:後置攝像頭掃碼功能(二)-開啟後置攝像頭的預覽介面

在上一篇文章中,我們實現“獲取相機的許可權ohos.permission.CAMERA”之後,緊接著要讓手機的螢幕開啟拍攝外部環境的畫面,其拍攝預覽的畫面也必須是後置攝像頭所拍攝的畫面。

鴻蒙APP開發:後置攝像頭掃碼功能(二)-開啟後置攝像頭的預覽介面

如果你感覺開啟拍攝畫面的功能實現比較複雜,我建議你最好是參考一下HarmonyOS Developer的相關文件內容,可根據“開發->媒體->相機”目錄下的“相機開發指導”中的介面內容進行其功能的梳理。

鴻蒙APP開發:後置攝像頭掃碼功能(二)-開啟後置攝像頭的預覽介面

依據上圖中的相機開發流程,華為手機的後置攝像頭想要開啟拍攝的預覽畫面,我們必須要建立相機裝置這個物件,為了更直觀更簡潔的方便你們去實現此功能,我還是按照自己的專案結構呈現相關程式碼內容。

一.在專案中新建一個CameraView類繼承DirectionalLayout,單獨代表相機這個檢視物件,並實現相機裝置的建立。

專案結構圖,如下:

鴻蒙APP開發:後置攝像頭掃碼功能(二)-開啟後置攝像頭的預覽介面

程式碼內容,如下:

import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.surfaceprovider.SurfaceProvider;
import ohos.agp.graphics.Surface;
import ohos.agp.graphics.SurfaceOps;
import ohos.agp.window.service.WindowManager;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.media.camera.CameraKit;
import ohos.media.camera.device.Camera;
import ohos.media.camera.device.CameraConfig;
import ohos.media.camera.device.CameraStateCallback;
import ohos.media.camera.device.FrameConfig;

import static ohos.media.camera.device.Camera.FrameConfigType.FRAME_CONFIG_PREVIEW;

public class CameraView extends DirectionalLayout{

    static final HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00311, "MY_TAG");

    //相機裝置
    private Camera cameraSurface;

    //相機預覽模版的配置物件
    private SurfaceProvider surfaceProvider;

    //相機預覽模版
    private Surface previewSurface;

    //上下文
    private Context context;

    //攝像頭型別:前置攝像頭,後置攝像頭
    private String cameraId ;

    //執行回撥
    private EventHandler eventHandler = new EventHandler(EventRunner.current()) {
    };

    private ComponentContainer componentContainer;

    // 載入相機檢視
    public CameraView(Context context) {
        super(context);
        this.context = context;
        initSurface(context);
    }

    //第一步:初始化照相機預覽畫面的SurfaceProvider
    private void initSurface(Context context){
        WindowManager.getInstance().getTopWindow().get().setTransparent(true);
        DirectionalLayout.LayoutConfig params = new DirectionalLayout.LayoutConfig(
                ComponentContainer.LayoutConfig.MATCH_PARENT,
                ComponentContainer.LayoutConfig.MATCH_PARENT
        );
        surfaceProvider = new SurfaceProvider(context);
        surfaceProvider.setLayoutConfig(params);
        surfaceProvider.pinToZTop(false);
        surfaceProvider.getSurfaceOps().get().addCallback(new SurfaceCallBack());
        addComponent(surfaceProvider);
    }

    //第二步:建立Surface的監聽器SurfaceCallBack,正常感知SurfaceProvider的建立、改變或銷燬
    private class SurfaceCallBack implements SurfaceOps.Callback{

        @Override
        public void surfaceCreated(SurfaceOps surfaceOps) {
            //初始化相機
            initCamera();
        }

        @Override
        public void surfaceChanged(SurfaceOps surfaceOps, int i, int i1, int i2) {

        }

        @Override
        public void surfaceDestroyed(SurfaceOps surfaceOps) {

        }
    }

    //第三步:裝置建立-根據攝像頭型別建立相機裝置物件
    private void initCamera(){
        CameraKit cameraKit = CameraKit.getInstance(context);
        String[] cameraList = cameraKit.getCameraIds();
        if(cameraList.length > 1) {
            //攝像頭型別:後置攝像頭
             cameraId = cameraList[0];
        }
        CameraStateCallbackImpl cameraStateCallback = new CameraStateCallbackImpl();
        cameraKit.createCamera(cameraId, cameraStateCallback, eventHandler);
    }

    //第四步:相機回撥-透過回撥觸發並帶回Camera物件,執行相機裝置的操作
    private class CameraStateCallbackImpl extends CameraStateCallback{

        //建立相機裝置
        @Override
        public void onCreated(Camera camera) {
            previewSurface = surfaceProvider.getSurfaceOps().get().getSurface();
            if(previewSurface == null){
                return;
            }
            CameraConfig.Builder builder = camera.getCameraConfigBuilder();
            builder.addSurface(previewSurface);
            camera.configure(builder.build());
            cameraSurface = camera;
        }

        //配置相機裝置
        @Override
        public void onConfigured(Camera camera) {
            FrameConfig.Builder builder = camera.getFrameConfigBuilder(FRAME_CONFIG_PREVIEW);
            builder.addSurface(previewSurface);
            camera.triggerLoopingCapture(builder.build());
        }

        @Override
        public void onReleased(Camera camera) {
            super.onReleased(camera);
        }
    }

    //第五步:釋放相機-關閉相機相關資源
    private void releaseCamera(){
        if (cameraSurface != null){
            cameraSurface.release();
        }
    }
}

二.在MainAbilitySlice中建立相機CameraView的佈局,載入其拍攝的預覽介面。

import com.saomiao.camera.view.CameraView;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.window.dialog.ToastDialog;
import ohos.bundle.IBundleManager;

public class MainAbilitySlice extends AbilitySlice {

    public static final int MY_PERMISSIONS_REQUEST_CAMERA = 1039;

    private CameraView cameraView;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
//        super.setUIContent(ResourceTable.Layout_ability_main);
        requestCameraPermission();
    }

    //1.獲取相機許可權
    public void requestCameraPermission(){
        if (verifySelfPermission("ohos.permission.CAMERA") != IBundleManager.PERMISSION_GRANTED) {
            // 應用未被授予許可權
            if (canRequestPermission("ohos.permission.CAMERA")) {
                // 是否可以申請彈框授權(首次申請或者使用者未選擇禁止且不再提示)
                requestPermissionsFromUser(
                        new String[] { "ohos.permission.CAMERA" } , MY_PERMISSIONS_REQUEST_CAMERA);
            } else {
                // 顯示應用需要許可權的理由,提示使用者進入設定授權
                new ToastDialog(getContext()).setText("請進入手機系統【設定】中,重新開啟應用的相機許可權").show();
            }
        } else {
            // 許可權已被授予
            new ToastDialog(getContext()).setText("已授權,可使用相機的拍攝功能").show();
            //成功進入相機拍攝的預覽介面
            initCameraView();
        }
    }

    private void initCameraView(){
        cameraView = new CameraView(this);
        DirectionalLayout.LayoutConfig params = new DirectionalLayout.LayoutConfig(
                ComponentContainer.LayoutConfig.MATCH_PARENT,
                ComponentContainer.LayoutConfig.MATCH_PARENT
        );
        cameraView.setLayoutConfig(params);
        super.setUIContent(cameraView);
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }
}

三.手機USB資料線連線電腦端,進行真機測試,開啟專案的APP檢視相機的後置攝像頭是否讓螢幕出現拍攝畫面。

鴻蒙APP開發:後置攝像頭掃碼功能(二)-開啟後置攝像頭的預覽介面

如上圖所示,若專案APP的介面開啟之後,其預覽介面能正常顯示出所拍攝的事物,則表示手機後置攝像頭已經可以進行正常拍攝。

結語:

我們手機的掃碼功能-“掃一掃”,其掃碼區域的範圍仍處於手機後置攝像頭所拍攝的區域,必須要開啟手機的拍攝畫面才行。只有開啟手機的拍攝畫面,我們才能在後面透過掃描功能來捕獲拍攝畫面中的條形碼、二維碼等圖片資訊。

本篇內容,由於存在回撥函式Callback的多次使用,初學者需要參考HarmonyOS官方相應的文件才能更加熟悉。以上所有的程式碼塊我自己已經測試成功,請你們在成功獲取相機許可權之後再進行本篇程式碼內容的新增和功能測試、最佳化。

分類: 國際
時間: 2022-01-29

相關文章

看完《長津湖》再看美國紀錄片《長津湖戰役》。會有不一樣的感受

看完《長津湖》再看美國紀錄片《長津湖戰役》。會有不一樣的感受
看完<長津湖>再看美國紀錄片<長津湖戰役>.更能理解電影裡一些臺詞的含義. 要不是吃了大虧,美國老兵最後會這麼評價?或許就是喝著咖啡嘲笑"洗衣工"了. 一直 ...

原來河南燜面是這樣做的?怪不得總是炒糊粘鍋?看完真的長知識了

原來河南燜面是這樣做的?怪不得總是炒糊粘鍋?看完真的長知識了
原來河南燜面是這樣做的?怪不得總是炒糊粘鍋?看完真的長知識了.親愛的好朋友們,大家好,我是大廚江一舟,今天又到了,給大家分享美食的時刻了,你們準備好了嗎? 很多河南人的主食,裡面都會有一道河南燜面,麵 ...

核動力並非唯一選擇?常規航母+電磁彈射,真的就要落後於美國嗎

核動力並非唯一選擇?常規航母+電磁彈射,真的就要落後於美國嗎
進入21世紀以來,不知不覺間,一些有航母國家似乎正在逐步推進著各自的下一代航空母艦專案.現代航母使用經驗最豐富的美國,推出了集萬千新技術於一身的福特級核航母:第一個推出真正意義的航空母艦的國家英國,服 ...

新冠病毒源於美國?莫迪罕見與普京達成一致,這次必須還中國清白

新冠病毒源於美國?莫迪罕見與普京達成一致,這次必須還中國清白
如今,新冠病毒已經在世界各地肆虐了近兩年,世界各國對該病毒的追蹤從未停止過.大家都認識到,只有調查出病毒的源頭,才能更好地防控疫情.因此,在世衛組織的帶領下,開始對各國進行溯源調查. 自導自演的鬧劇? ...

海灣戰爭,面對美國聯軍陳兵50萬,薩達姆為何仍不聽中國勸阻?

海灣戰爭,面對美國聯軍陳兵50萬,薩達姆為何仍不聽中國勸阻?
第二次世界大戰的場景如今想想還有點令人毛骨悚然,全世界幾乎所以國家都被戰火所荼毒.槍炮無眼,慘烈的戰爭造成了近2億人的傷亡,更何況當時的全球總人口數也才不過25億. 在這場戰爭中,有人落敗,有人勝出, ...

美國人修公路時,為什麼要預埋一層輪胎?中國為何不效仿?

美國人修公路時,為什麼要預埋一層輪胎?中國為何不效仿?
基礎建設是一個國家的命脈,如果沒有良好的基礎建設,那麼經濟的發展將會變得異常艱難,自然也就無法增強自身的國力了.我國在發展的過程中十分注重基礎設施的建設,並且取得了令人矚目的成就,也能因此稱為是&qu ...

美國銀行:全球缺芯情況下 最喜歡這些汽車半導體公司
美國銀行的分析師說,汽車行業使用的半導體是他們2022年的首選行業之一,並點出了6家他們看好未來增長的"首選"公司. 從家用電器.智慧手機到汽車都使用的半導體晶片的供應幾個月來一直 ...

美國遊客拍下“長沙南站”建築,引發網友熱議:中國建設很強大

美國遊客拍下“長沙南站”建築,引發網友熱議:中國建設很強大
中國近年來建築行業快速發展,各種特色建築.基建設施等,像雨後春筍般拔地而起! 像廣州的"廣東省博物館",其位於廣州新城市中軸線珠江新城中心區南部,於2010年建成,總佔地面積6.7 ...

哈哈哈哈哈看完真的提神醒腦

哈哈哈哈哈看完真的提神醒腦
今年的Met Gala來了! 先來說下Met Gala到底是個啥? Met Gala,也叫Met Ball,中文名"紐約大都會藝術博物館慈善舞會". 這個活動由時尚雜誌<Vo ...

安樂死真的沒痛苦嗎?能讓絕症患者有尊嚴地離開,為何中國不實行

安樂死真的沒痛苦嗎?能讓絕症患者有尊嚴地離開,為何中國不實行
小島美奈子選擇進行安樂死,再次引起了很多人的熱議. 小島美奈子出生在日本一個普通家庭裡,有一個非常幸福的家庭,還有個感情特別好的姐姐.從小和姐姐親密無間,即便是長大後兩個人擁有了各自的家庭以後,小島美 ...

為什麼客餐廚一體化越來越流行?看完她家就知道了,真的很治癒

為什麼客餐廚一體化越來越流行?看完她家就知道了,真的很治癒
嚮往的家是什麼樣子的?我想應該是那種很溫柔很溫暖,並且有力量的,家是一個人的能量場,當我們在外勞累奔波了一天,精疲力盡地回家,在家休整一下,第二天又能能量滿滿的出門接著奮鬥. 所以家一定要很乾淨很治癒 ...

戒酒對高血壓真的有好處嗎?或許很多人不瞭解,看完漲知識了

戒酒對高血壓真的有好處嗎?或許很多人不瞭解,看完漲知識了
導語:隨著大家生活水平的不斷提高 ,如今大家的生活品質也得到顯著的改善,而絕大多數年輕人在平常生活之中的壓力也顯著的提升. 有些人為了更好地緩解壓力,也是在無形中之中產生了一些不好的飲食結構,像吸菸喝 ...

防水插排真的可以防水嗎?看完你就知道答案了
現在家裡到處都是電子產品.傢俱,需要用到插頭的地方很多,但如果考慮到現實情況的話裝的插座數量是不可能滿足所有用電需要的,這個時插排就很重要了.都說水導電,為了我們的安全,插排也在不斷迭代,防水插排出現 ...

總工一直偷偷在用的:新版工程量計算書,看完是真的好

總工一直偷偷在用的:新版工程量計算書,看完是真的好
連總工都悄悄在用的:21版工程量計算書,造價算量都不是事 連總工都悄悄在用的:21版工程量計算書,造價算量都不是事 包含了:安裝,工程,裝修,給排水,消防等等,前一列輸入計算式,後一列自動化生成結果, ...

燈光如何佈局?怎麼才能讓燈光更有層次感?價效比最高的無主燈

燈光如何佈局?怎麼才能讓燈光更有層次感?價效比最高的無主燈
現在好多人家裝修都考慮用無主燈,無主燈美觀,讓室內整體的光照均勻無死角,靈活度高,比較便捷還能營造不同的氛圍,讓在家的夜晚不再單調,無論是看書,看報,看電影,玩手機都能找到適合自己的氛圍,我這次新裝的 ...

100部高分經典動畫電影(三)

100部高分經典動畫電影(三)
31.<魁拔Ⅲ戰神崛起>-8.5分 估計很多人以為這是一部日漫,其實這是一部國漫.不知道國漫為啥名字和人物設定都有點片日漫風格,但真的是一部優秀的國漫作品.這是一部系列電影可以從1看到3, ...

歷史上真實的明樓,5重間諜,和杜月笙拜把子,死後葬在八寶山

歷史上真實的明樓,5重間諜,和杜月笙拜把子,死後葬在八寶山
"他不顧個人的譭譽完成了黨交給的特殊使命."--<中共黨史人物傳> 翻開歷史的書卷,那一個個在抗日戰場上衝鋒陷陣.誓死為國的戰士,他們用鮮血換來了新中國的誕生,人民由此 ...

地心引力:
地心引力 深邃浩瀚的外太空中,瑞恩和Matt正在檢查維修機器.麥特是位幽默風趣的宇航員,他一邊檢修一邊說話讓工作氛圍輕鬆.突然他們接收修斯敦傳遞來的資訊.一顆被導彈擊碎的俄羅斯廢棄衛星產生的碎片引起了 ...

數千名美國科學家投奔中國,是真的看好中國嗎?背後有什麼隱情?

數千名美國科學家投奔中國,是真的看好中國嗎?背後有什麼隱情?
大家好,我是老七,本期我們來說說這個話題 人才流失,一直是中國人心中的痛,每當說起清華北大有多少留學生留在美國,不願意回國的事情,我們總是如鯁在喉,總有一種被被背叛的感覺,畢竟自己辛辛苦苦養大的雞,卻 ...

在美國當碼農,真的很香嗎?

在美國當碼農,真的很香嗎?
最近看到一個這樣的統計結果,說近六成的大學畢業生預估自己十年內會年入百萬.有美好的願望是好事,但這個誇張結果也體現出年輕人的天真和浮躁. 可如果不分國家,那麼美國的CS(計算機)畢業生剛入職的稅前收入 ...