Google Mobile Vision API二维码检测在华为Honor 6X失效求助
Hey there, let's figure out why your QR code reader is failing on the Honor 6X while working fine on the Galaxy S7. The key issues here are the barcodeDetector.isOperational() returning false and empty detection results—let's break down the fixes step by step:
1. Fix the Meta-data Placement (Critical!)
You've added the Vision API dependency meta-data inside your <activity> tag, but this needs to be placed directly under the <application> tag in your AndroidManifest.xml. The meta-data tells Google Play Services to pre-download the barcode detection library, and putting it in the activity means it won't be picked up properly on some devices (like the Honor 6X):
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <!-- Move meta-data HERE, outside of any activity --> <meta-data android:name="com.google.android.gms.vision.DEPENDENCIES" android:value="barcode" /> <activity android:name=".view" android:label="Check out your route" /> </application> <!-- Keep permissions outside the application tag --> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.INTERNET" />
2. Complete the Play Services Vision Dependency
Your build.gradle snippet cuts off mid-line—you need to add the full Google Play Services Vision dependency, which is required for the barcode detector to function:
dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:26.1.0' implementation 'com.android.support.constraint:constraint-layout:1.1.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' // Add this line to include the Vision API library implementation 'com.google.android.gms:play-services-vision:19.0.0' }
3. Handle Library Download State
The barcodeDetector.isOperational() returns false when the required detection library hasn't finished downloading to the device. On devices with restricted network access or older Play Services versions, this can take time. Add a broadcast receiver to listen for when the download completes, then reinitialize the detector:
Update your view.java with this structured approach:
package com.example.android.gpsv01; import android.Manifest; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.Vibrator; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.util.SparseArray; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.widget.TextView; import com.google.android.gms.vision.CameraSource; import com.google.android.gms.vision.Detector; import com.google.android.gms.vision.barcode.Barcode; import com.google.android.gms.vision.barcode.BarcodeDetector; import java.io.IOException; public class view extends AppCompatActivity { SurfaceView surfaceView; CameraSource cameraSource; TextView txtResult; BarcodeDetector barcodeDetector; final int RequestCameraPermissionID = 1001; @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode) { case RequestCameraPermissionID: { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { return; } try { cameraSource.start(surfaceView.getHolder()); } catch (IOException e) { e.printStackTrace(); } } } break; } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.view); surfaceView = findViewById(R.id.camerapreview); txtResult = findViewById(R.id.textView); initializeBarcodeDetector(); } private void initializeBarcodeDetector() { barcodeDetector = new BarcodeDetector.Builder(this) .setBarcodeFormats(Barcode.QR_CODE) .build(); if (!barcodeDetector.isOperational()) { txtResult.setText("Could not set up the detector! Waiting for library download..."); // Listen for when the barcode library finishes downloading IntentFilter filter = new IntentFilter(BarcodeDetector.RECEIVER_DOWNLOAD_COMPLETE); registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // Clean up old detector and reinitialize barcodeDetector.release(); initializeBarcodeDetector(); // Restart camera source if ready if (barcodeDetector.isOperational() && ActivityCompat.checkSelfPermission(context, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { try { cameraSource.start(surfaceView.getHolder()); txtResult.setText("Detector ready! Point at a QR code."); } catch (IOException e) { e.printStackTrace(); } } } }, filter); return; } txtResult.setText("Detector ready! Point at a QR code."); cameraSource = new CameraSource.Builder(this, barcodeDetector) .setRequestedPreviewSize(640, 480) .setAutoFocusEnabled(true) .build(); surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder surfaceHolder) { if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(view.this, new String[]{Manifest.permission.CAMERA}, RequestCameraPermissionID); return; } try { cameraSource.start(surfaceHolder); } catch (IOException e) { e.printStackTrace(); } } @Override public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {} @Override public void surfaceDestroyed(SurfaceHolder surfaceHolder) { cameraSource.stop(); } }); barcodeDetector.setProcessor(new Detector.Processor<Barcode>() { @Override public void release() {} @Override public void receiveDetections(Detector.Detections<Barcode> detections) { final SparseArray<Barcode> qrcodes = detections.getDetectedItems(); Log.e("********", "" + qrcodes.size()); if (qrcodes != null && qrcodes.size() > 0) { runOnUiThread(() -> { String barcode = qrcodes.valueAt(0).displayValue; if (!barcode.isEmpty()) { txtResult.setText(barcode); // Optional: Vibrate on detection Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); if (vibrator != null) { vibrator.vibrate(500); } } }); } } }); } }
4. Check Google Play Services on Honor 6X
Make sure the Honor 6X has the latest version of Google Play Services installed. Older versions might have issues downloading the Vision API libraries or running the detector correctly. You can prompt the user to update Play Services if needed, but first try the above fixes.
These changes should resolve the detector issue on the Honor 6X. The main culprit was likely the misplaced meta-data, which prevented the device from downloading the required barcode detection library.
内容的提问来源于stack exchange,提问作者riccardo

