preface

Problem Description:

One compatibility issue encountered when using uni-app at work is when using uni.chooseImg, some phones cannot call the camera only image. About two dozen phones were tested, with varying performance

Problem recurrence:

1. Use the official uni. ChooseImage;

2. Some Android phones, such as “SM-G9700″,”MX 2S”,”MATE30 PRO”,”MI 10 PRO”,” Pra-Al00X “(Xiaomi, Meizu and Huawei), cannot retrieve the camera; Several ios phones were tested and no problems were found;

The official offer code: uniapp. Dcloud. IO/API/media/I…

uni.chooseImage({
   count: 1.sourceType: ['album'.'camera'].sizeType: ['compressed'.'original'].success: function (res) {
        console.log(JSON.stringify(res.tempFilePaths)); }});Copy the code

Summary of extended problems:

  • Uni. ChooseImage: h5 chooseimg interface sourceType does not work;
  • 2. Use native code:
<input type="file" id="camera" multiple="multiple"capture="camera" accept="image/*" >
Copy the code

Ios phones and some Android phones, directly call the camera, no photo album selection function;

  • 3. Display compression on IOS when the image is too large

  • 4. Select the picture gallery or selfie photo and display it on the page. No matter IOS or Android phones, the picture has been rotated.

    This will be addressed in a future article, addressing the process, addressing the code;

Problem solving process:

1. Check the official website community:

I found that many people encountered this problem, but I checked the official community answers, and found that they did not solve the fundamental problem, and there were many other extended problems, such as:

  • H5 chooseimg interface sourceType does not work;
  • Type =”file”, accept specifies the file type that can be submitted by the file upload control.

Input type=”file

Problems encountered: Extend the summary of the problem, second: when uploading files or images on the mobile terminal page, IOS and Android display a lot of different ways.

The solutions to data searching are as follows:

  • The first solution:
<input type="file" accept="image/*" capture="camera">
<input type="file" accept="video/*" capture="camcorder">
<input type="file" accept="audio/*" capture="microphone">
Copy the code

Accept indicates the open system file directory

Capture represents the default device captured by the system,

Camera D. Camcorder: camera; Microphone:

There is also a multiple attribute that supports multiple selections. When multiple selections are supported, the multiple attribute takes precedence over capture, so you can only write it as:

You can.

Conclusion:

But there are still different forms of expression, ios phones directly call the camera, Android phones directly call, some can choose the camera and album !!!!

  • Second solution:

// Determine whether the current device belongs to ios mobile terminal, compatible with input and call mobile album and camera

function compatibleInput(){
    // Get the browser's userAgent and convert it to lowercase
    var ua = navigator.userAgent.toLowerCase();
    // Check if it is an iPhone, true if it is
    var isIos = (ua.indexOf('iphone') != - 1) || (ua.indexOf('ipad') != - 1);
    if (isIos) {
        $("input:file").removeAttr("capture");
    };
}
Copy the code

Conclusion:

Some Android phones just drop the camera, ios is fine;

  • Third solution

    Capture =”camera”; capture=”camera”; capture=”camera”;

    Part of the code implementation:

    <input id="input" type="file" accept="image/*" multiple>
    Copy the code
    let input = document.getElementById('input');
    const phoneModel = ["TAS-AN00"."JKM-AL00b"."SM-G9700"."MX4"."MX 2S"."MATE30 PRO"."MI 10 PRO"."PRA-AL00X"];
    const info = uni.getSystemInfoSync();
    console.log(info.model,info.platform,info,'About mobile phones')
    let mm = info.model.replace(/(^\s*)|(\s*$)/g."").toLocaleUpperCase();// Remove whitespace and convert to uppercase
    if (info.platform == 'android' && phoneModel.includes(mm)) {
    	input.capture = 'camera';
    }
    input.onchange = (event) = > {
    	console.log('Dynamically added input selection photo', event.target.files);
    	let files = event.target.files;
    	if(! files.length)return;
    	files = Array.prototype.slice.call(files);
    	this.$emit('chooseImage', files);
    }
    console.log("What kernel is used:".window.navigator.userAgent);
    Copy the code

    Conclusion:

    Began to test, really have no questions, but found that this phone WeChat open a browser, the browser default browser, QQ, QQ open a browser forms still have compatibility, and can’t have been so collect models, such a solution is not reasonable, should from the browser kernel mode to view ~ ~

  • Final solution

    See the official section below ~

Official:

My final solution:

After using the console. The log (” what is the kernel of use: “window. The navigator. UserAgent); Print, view about two dozen mobile phones, screenshots to compare the kernel, respectively through the different browser to summarize (breath, very tired ~~) :

Wechat open browser, mobile phone browser, other browsers;

I won’t put the screenshot here, but the code

This code is written as a componentCreateChooseImgCan be used with uni-app projects or VUE projects

1. CreateChooseImg component

<template> <view ref="my_mdj_input"> </view> </template> <script> /** * @description uses native DOM input type= "file" To call the camera or select pictures to resolve using the API part of the uni-app phone, * @ Lee * @ property {function} isWeixin, isMQQbrowser, isAndroid for mobile browser kernel * @ return files file information, This method may be in the parent component chooseImage binding in the concrete operation * / import {isWeixin isMQQbrowser, isAndroid} the from '@ / common/compatible' export default { name: 'CreateChooseImg', methods: ChooseImg in call album and photo in different phone display different cannot call camera etc. * in each phone can click file to call album and camera photo 1. On older versions of Android, you must add Capture or you can only call album 2. */ createUploadImgEle() {console.log(' create input and upload img elements '); let input = document.createElement('input'); input.type = 'file'; input.accept = 'image/*'; input.multiple = 'multiple'; // input.className = 'input-img_elm'; input.style.position = "absolute"; input.style.left = '0'; input.style.top = '0'; input.style.width = '100%'; input.style.height = '100%'; input.style.overflow = "hidden"; input.style.opacity = 0; Input.onchange = (event) => {console.log(' dynamically added input selects photos ', event.target.files); let files = event.target.files; if (! files.length) return; files = Array.prototype.slice.call(files); $emit('chooseImageUseH5', files); } the console. The log (" what is the kernel of use: "window. The navigator. UserAgent); try{ if (isAndroid() && isWeixin() && ! IsMQQbrowser ()) {console.log(" force to add camera call function "); input.capture = 'camera'; }}catch(e){console.log(" create native input element error: ",e); } this.$refs.my_mdj_input.$el.appendChild(input); }, }, mounted() { this.createUploadImgEle(); } } </script> <style lang="scss" scoped> </style>Copy the code

2, add mobile browser version judgment

/** * Analyze smartphone browser version information * @ author: Lixiaoyan * @ Time: 2020.5.15 */

export const browser = {
	versions: function() {
		var u = navigator.userAgent,
			app = navigator.appVersion;
		return { // Mobile terminal browser version information
			trident: u.indexOf('Trident') > - 1./ / IE kernel
			presto: u.indexOf('Presto') > - 1./ / opera kernel
			webKit: u.indexOf('AppleWebKit') > - 1.// Apple, Google kernel
			gecko: u.indexOf('Gecko') > - 1 && u.indexOf('KHTML') = =- 1.// The Firefox kernelmobile: !! u.match(/AppleWebKit.*Mobile.*/) | |!!!!! u.match(/AppleWebKit/), // Whether it is a mobile terminalios: !! u.match(/\(i[^;] +; ( U;) ? CPU.+Mac OS X/), / / ios terminal
			android: u.indexOf('Android') > - 1 || u.indexOf('Linux') > - 1.// An Android terminal or uc browser
			iPhone: u.indexOf('iPhone') > - 1 || u.indexOf('Mac') > - 1.// Whether the browser is iPhone or QQHD
			iPad: u.indexOf('iPad') > - 1./ / whether the device
			webApp: u.indexOf('Safari') = =- 1.// Whether the web should be a program, without a header and a bottom
			isWeixin: u.toLowerCase().match(/MicroMessenger/i) = ='micromessenger' ,// Whether the browser is opened by wechat
			isMQQbrowser: u.toLowerCase().match(/MQQbrowser/i) = ='mqqbrowser' // Whether the browser is opened by wechat}; } (),language: (navigator.browserLanguage || navigator.language).toLowerCase()
}

// Check whether the operating system is ios
export function isIos() {
	if (browser.versions.ios || browser.versions.iPhone || browser.versions.iPad) {
		return true;
	} else {
		return false; }}// Whether it is an Android system
export function isAndroid() {
	return  browser.versions.android
}

// Whether it is mobile
export function isMobile() {
	return browser.versions.mobile;
}

export function isWeixin() {
	return browser.versions.isWeixin;
}

export function isMQQbrowser() {
	return browser.versions.isMQQbrowser;
}
Copy the code

Follow-up questions:

Because the available mobile phone models are limited after all, it is still uncertain whether the final solution above and the follow-up problems can be solved. If there is a problem with the phone later, the code is not adapted to update the code again… Of course, if you read this article and have different suggestions or find that the code is not compatible after testing, please feel free to communicate with us