การเข้าถึงกล้อง เสียง และไฟล์ดั้งเดิมสำหรับเว็บแอป PWA ที่โฮสต์โดยใช้ Cordova

บริบท

ฉันกำลังทำงานในแอปพลิเคชัน PWA เว็บแอปส่วนใหญ่เสร็จแล้ว มีความสามารถในการบันทึกกล้อง วิดีโอ และเสียงในเบราว์เซอร์ที่ใช้ MediaDevices เอพีไอ เมื่อทดสอบแอปพลิเคชันนี้โดยใช้ Chrome หรือ Firefox ทั้งในเดสก์ท็อปและอุปกรณ์มือถือเช่น Android ทุกอย่างทำงานได้ดี

อย่างไรก็ตาม ตาม ในแท็บความเข้ากันได้ของเบราว์เซอร์ สิ่งนี้ คุณลักษณะนี้รองรับเบราว์เซอร์เพียงไม่กี่ตัว

ด้วยข้อจำกัดนี้ ฉันได้รับมอบหมายให้พัฒนาแอปไฮบริดที่ใช้ทรัพยากรโทรศัพท์ภายในเครื่อง

ข้อจำกัด

  • สร้างแอปไฮบริด
  • ทรัพยากรบนเว็บชี้ไปที่โฮสต์ (ไฟล์ไม่สามารถอยู่ในเครื่องได้)
  • ทรัพยากรสื่อ: ถ่ายภาพ บันทึกเสียงและวิดีโอ อัพโหลดไฟล์
  • รองรับ AngularJS

person raphaelbs    schedule 28.09.2017    source แหล่งที่มา


คำตอบ (1)


คอร์โดวา

ในฐานะนักพัฒนาเว็บ การใช้ Cordova เป็นทางเลือกที่เป็นธรรมชาติ

ฉันตัดสินใจบันทึกการประมวลผลนี้เนื่องจากฉันใช้เวลาหนึ่งสัปดาห์ในการทำงานทั้งหมด


ขั้นตอน

สรุป

  1. เปิดแอปที่โฮสต์โดยไม่มีแคชในเครื่อง
  2. การเข้าถึงปลั๊กอินในแอปพลิเคชันที่โฮสต์
  3. การจัดการกับไฟล์ จากอุปกรณ์ไปยังมุมมองเว็บ

1) เปิดแอปที่โฮสต์โดยไม่มีแคชในเครื่อง

เพื่อให้แอปพลิเคชันชี้ไปที่ webapp เราสามารถเปลี่ยน config.xml ได้ง่ายๆ:

<content src="http://YOUR-DOMAIN/index.html" />

แต่ด้วยวิธีนี้ เมื่อโหลดแอปพลิเคชัน มันจะแคชหน้าทั้งหมดลงในอุปกรณ์ หากเราเปลี่ยนแปลงบางสิ่งใน webapp มันจะไม่เปลี่ยนแปลงในอุปกรณ์เฉพาะเมื่อเราล้างแคชของแอปเท่านั้น

เพื่อแก้ไขปัญหาแรกนี้ เราใช้ปลั๊กอิน com.tiltshiftfocus.cordova.plugin.clearCache

  • 1) ติดตั้งปลั๊กอิน:

ในการทุบตี:

cordova plugin add com.tiltshiftfocus.cordova.plugin.clearCache
  • 2) สร้าง script.js อย่างง่าย:

สคริปต์:

var URL = "http://YOUR-DOMAIN/index.html?platform="
var app = {
    initialize: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    onDeviceReady: function() {
        var targetUrl = URL + cordova.platformId;
        function cb(){
            window.location.replace(targetUrl);
        }
        window.cache.clear(cb, cb);
    }
};
app.initialize();

โปรดทราบว่า เรากำลังส่งตัวแปร platform ไปยัง URL หลัก เราจะใช้ตัวแปรนี้ในเว็บแอปในภายหลัง

  • 3) สร้าง index.html อย่างง่ายเพื่อโหลด script.js:

HTML:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: cdvfile: http://YOUR-DOMAIN/ https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
        <meta name="format-detection" content="telephone=no">
        <meta name="msapplication-tap-highlight" content="no">
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
        <title>TITLE</title>
    </head>
    <body>
        <script type="text/javascript" src="cordova.js"></script>
        <script type="text/javascript" src="script.js"></script>
    </body>
</html>
  • 4) อัปเดต config.xml ให้ชี้ไปที่ index.html:

กำหนดค่า.xml:

<content src="index.html" />

2) การเข้าถึงปลั๊กอินในแอปพลิเคชันที่โฮสต์

ปัญหาของการใช้โฮสต์ webapps คือเราไม่สามารถเข้าถึงปลั๊กอินที่ติดตั้งอยู่ในแอปได้อย่างง่ายดาย โชคดีที่วิธีแก้ปัญหานั้นง่าย

หลังจากติดตั้งปลั๊กอินทั้งหมดที่คุณต้องการใช้ ในโปรเจ็กต์ Cordova ของคุณ ให้นำทางไปยังโฟลเดอร์แพลตฟอร์มและคัดลอกเนื้อหาทั้งหมดไปยังโปรเจ็กต์ webapp ของคุณ

แอนดรอยด์

คัดลอกเนื้อหาจาก

Cordova_Project_Folder/platforms/android/platform_www

ไปยังไดเร็กทอรี public ของคุณภายในโปรเจ็กต์ webapp

Webapp_Project_Folder/public_www/android/

เว็บแอป

หลังจากคัดลอกโฟลเดอร์ปลั๊กอิน คุณจะต้องอ้างอิง cordova.js

เว็บแอป Index.html:

<script scr="/android/cordova.js"></script>

หมายเหตุว่าเราจำเป็นต้องอ้างอิงโฟลเดอร์ที่เหมาะสมสำหรับแพลตฟอร์มที่เหมาะสม จากนั้น ในขั้นตอนนี้ เราใช้ตัวแปร platform ที่เคยระบุให้กับเว็บแอปที่โฮสต์ไว้ ฉันจะไม่ลงรายละเอียดเกี่ยวกับกระบวนการนี้


3) การจัดการกับไฟล์ จากอุปกรณ์ไปยังมุมมองเว็บ

จนถึงตอนนี้ เรามีเว็บแอปที่โฮสต์ไว้และปลั๊กอินที่จำเป็นใช้งานได้ ตอนนี้เราต้องจัดการไฟล์ที่เก็บไว้ในอุปกรณ์

เพื่อให้กระบวนการนี้ได้ผล เราได้ใช้ขั้นตอนนี้:

  1. รับ URL แบบเต็มของไฟล์
  2. แปลง URL แบบเต็มเป็น cdvfile://
  3. ใช้ cdvfile:// ในเว็บแอป
  4. แปลง URL ใด ๆ เป็น Blob

1) รับ URL แบบเต็มของไฟล์

ปลั๊กอินใดๆ ก็ตามที่มีอยู่ซึ่งสร้างหรืออ่านไฟล์ (กล้อง เสียง ฯลฯ) จะส่งกลับ URL แบบเต็ม

<แข็งแกร่ง>2. แปลง URL แบบเต็มเป็น cdvfile://.

ปลั๊กอินกล้อง cordova-plugin-media-capture ส่งคืนออบเจ็กต์ MediaFile ที่มีเส้นทาง cdvfile:// อยู่แล้ว: fullPath คุณลักษณะ.

แต่ในบางกรณี คุณต้องแปลงเส้นทางแบบเต็ม เช่น file:///Pictures/image.jpg ถึง cdvfile://localhost/image.jpg คุณสามารถทำได้โดยใช้วิธี resolveLocalFileSystemURL จาก cordova-plugin-file

สคริปต์:

function getCDVFromFullURL(fullURL, callback){
    window.resolveLocalFileSystemURL(fullURL, gotFile, callback);
    function gotFile(fileEntry) {
        callback(null, fileEntry.toInternalURL());
    }
};
getCDVFromFullURL('file:///Picture/image.jpg', function(err, cdvUrl){
    cdvUrl === 'cdvfile://localhost/image.jpg'; // example!!!
});

<แข็งแกร่ง>3. ใช้ cdvfile:// ในเว็บแอป

ปัญหาหนึ่งคือไฟล์อ้างอิงในแท็ก webapp ตัวอย่างด้านล่างใช้งานไม่ได้

<img src="cdvfile://path/image.jpg" />

เพื่อให้สามารถทำงานได้ เราจำเป็นต้องอัปเดต config.xml ด้วย:

<access origin="cdvfile://*" />

หมายเหตุ: หากคุณใช้ AngularJS คุณจะต้องไวท์ลิสต์โปรโตคอล cdvfile://:

.config(['$compileProvider', function( $compileProvider ){ 
    $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|file|blob|cdvfile):|data:image\//);
}]);

<แข็งแกร่ง>4. แปลง URL ใด ๆ เป็น Blob.

เป้าหมายทั้งหมดของความพยายามนี้คือการส่งทรัพยากรไปยังเซิร์ฟเวอร์ เราจำเป็นต้องมีวัตถุ Blob เพื่อต่อท้ายใน FormData เรายังสามารถใช้ resolveLocalFileSystemURL สำหรับสิ่งนั้นได้

function getBlob(anyUrl, callback){
    window.resolveLocalFileSystemURL(anyUrl, gotFile, callback);
    function gotFile(fileEntry) {
        fileEntry.file(readFile);
    }
    function readFile(file){
        var reader = new FileReader();
        reader.onloadend = function(e) {
            callback(null, new Blob([ this.result ], { type: file.type } ));
        };
        reader.readAsArrayBuffer(file);
    }
}

getBlob('file:///Picture/image.jpg', function(err, blob){
    // formData.append('imagem', blob, 'iamge name');
}

สรุป

ตอนนี้เรามี:

  • เข้าถึงสื่อใด ๆ จากอุปกรณ์
  • ความสามารถในการแสดงสื่อท้องถิ่นในเว็บแอปที่โฮสต์ของเรา
  • เครื่องมือในการแปลงสื่อท้องถิ่นนี้แล้วอัปโหลดผ่าน webapp

หวังว่าโพสต์นี้จะช่วยประหยัดเวลา

person raphaelbs    schedule 28.09.2017
comment
ขอบคุณมากสำหรับความช่วยเหลือของคุณราฟาเอล ฉันมีปัญหาที่คล้ายกัน แต่ฉันไม่สามารถทำตามขั้นตอนของคุณได้ คุณมีโครงการนั่งร้านเพื่อแสดงโครงสร้างทั้งหมดหรือไม่? - person 50l3r; 14.07.2020