【问题标题】:Does HMS ML Kit supporting for Background Thread works?支持后台线程的 HMS ML Kit 是否有效?
【发布时间】:2021-07-07 03:55:45
【问题描述】:

我在 android 应用程序中使用 HMS ML Kit 来分析来自后台服务的人脸检测。我无法初始化 MLFaceAnalyzer。下面是服务类代码sn-p

@Suppress("未使用") 类 TestService : Service() {

private val TAG: String = "FaceDetectionPresenterHw"
private var faceDetectionPresenterhw: FaceDetectionPresenterHw? = null
private var isNotificationCalled = false

private fun createNotification() {

    isNotificationCalled = true

    val notificationIntent = Intent(this, MyActivity::class.java)
    notificationIntent.putExtra(Constants.INTENT_EXTRA_TYPE, "Background Service")
    notificationIntent.putExtra(Constants.INTENT_EXTRA_CHILD_ID, childId)

    val pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT)

    val notificationManager = applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    val channelId = getString(R.string.default_notification_channel_id)
    val channelName = getString(R.string.channel_name)// The user-visible name of the channel.

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val importance = NotificationManager.IMPORTANCE_DEFAULT
        val mChannel = NotificationChannel(
            channelId, channelName, importance
        )
        mChannel.setSound(null, null)
        mChannel.enableVibration(false)
        notificationManager.createNotificationChannel(mChannel)
    }

    val notification = NotificationCompat.Builder(this, channelId)
        .setSmallIcon(R.drawable.ic_stat_notification)
        .setContentTitle(“MyApp”)
        .setDefaults(0)
        .setContentText("MyApp is running")
        .setContentIntent(pendingIntent).build()

    startForeground(1337, notification)
}

override fun onCreate() {
    super.onCreate()

    if (!isNotificationCalled) {
        createNotification()
    }

   faceDetectionPresenterhw = FaceDetectionPresenterHw(this@TestService)
   

}

@SuppressLint("MissingPermission")
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {

    Log.d(TAG,"Service started")

  
    if (!isNotificationCalled) {
        createNotification()

    }

    if (Utils.permissionCheck(this@TestService)) {
      faceDetectionPresenterhw!!.startCamera()
    } else {
        stopSelf()
    }
    return START_STICKY
}

override fun onDestroy() {
    isNotificationCalled = false
    isDestroyCalled = true

    faceDetectionPresenterhw!!.stopCamera()


    super.onDestroy()
}

override fun onBind(intent: Intent): IBinder? {
    return null
}
}

FaceDetectionPresenter 类代码 sn-p 在下面

class FaceDetectionPresenterHw(private val context: Context) : FaceDetectionInterface, KoinComponent {

private var cameraConfiguration: CameraConfiguration? = null
private var lensEngine: LensEngine? = null
private var preview: LensEnginePreview? = null

init {
    faceDetectorCreate(false)
}

override fun faceDetectorCreate(orientation: Boolean) {
    Log.d(TAG, "faceDetectorCreate()")
    cameraConfiguration = CameraConfiguration()
    createCameraSource()
}


private fun createCameraSource() {
    if (lensEngine == null) {
        Log.d(TAG, "createCameraSource() ${context ==null} ${cameraConfiguration ==null} ")
        lensEngine = LensEngine(context, this.cameraConfiguration)
    }

    setDetectorOptions()

}


private fun setDetectorOptions() {

    Log.d(TAG, "Option 1")
    val options: MLFaceAnalyzerSetting = MLFaceAnalyzerSetting.Factory()
            .setPerformanceType(MLFaceAnalyzerSetting.TYPE_SPEED)
            .setFeatureType(MLFaceAnalyzerSetting.TYPE_FEATURES)
            .setShapeType(MLFaceAnalyzerSetting.TYPE_SHAPES)
            .setKeyPointType(MLFaceAnalyzerSetting.TYPE_KEYPOINTS)
            .setTracingAllowed(true, MLFaceAnalyzerSetting.MODE_TRACING_FAST)
            .allowTracing(MLFaceAnalyzerSetting.MODE_TRACING_FAST)
            .create()


    Log.d(TAG, "Option  ${lensEngine != null} -- ${context==null} ")
    lensEngine?.setMachineLearningFrameTransactor(LocalFaceTransactor(options, context))
}

override fun startCamera() {
    Log.d(TAG, "Start Camera")
    if (lensEngine != null) {
        try {
            Log.d(TAG, "Start Camera inside")
            preview = LensEnginePreview(context)
            preview!!.start(lensEngine, true)
        } catch (e: IOException) {
            Log.e("FaceDetectionPr", "Unable to start lensEngine.", e)
            lensEngine!!.release()
            lensEngine = null
        }
    }
}


private inner class LocalFaceTransactor(options: MLFaceAnalyzerSetting?, context: Context) : BaseTransactor<List<MLFace?>?>() {

    init {

        detector = MLAnalyzerFactory.getInstance().getFaceAnalyzer(options)

    }
}
}

下面的问题来了

android.content.Context com.huawei.agconnect.AGConnectInstance.getContext()' on a null object reference

Logcat

2021-07-07 13:20:28.051 16868-16868/? E/AndroidRuntime: FATAL EXCEPTION: main

进程:co.sample:sampleService,PID:16868 java.lang.RuntimeException:无法创建服务 co.sample.services.sampleService:java.lang.NullPointerException:尝试在 null 上调用虚拟方法 'android.content.Context com.huawei.agconnect.AGConnectInstance.getContext()'对象引用 在 android.app.ActivityThread.handleCreateService(ActivityThread.java:4169) 在 android.app.ActivityThread.access$2400(ActivityThread.java:273) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:2055) 在 android.os.Handler.dispatchMessage(Handler.java:112) 在 android.os.Looper.loop(Looper.java:216) 在 android.app.ActivityThread.main(ActivityThread.java:7625) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987) 原因:java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法 'android.content.Context com.huawei.agconnect.AGConnectInstance.getContext()' 在 com.huawei.hms.mlsdk.common.MLApplication.getInstance(MLApplication.java:126) 在 com.huawei.hms.mlsdk.MLAnalyzerFactory.getInstance(MLAnalyzerFactory.java:1) 在 co.sample.services.facedetection.FaceDetectionPresenterHw$LocalFaceTransactor.(FaceDetectionPresenterHw.kt:352) 在 co.sample.services.facedetection.FaceDetectionPresenterHw.setDetectorOptions(FaceDetectionPresenterHw.kt:63) 在 co.sample.services.facedetection.FaceDetectionPresenterHw.createCameraSource(FaceDetectionPresenterHw.kt:86) 在 co.sample.services.facedetection.FaceDetectionPresenterHw.faceDetectorCreate(FaceDetectionPresenterHw.kt:75) 在 co.sample.services.facedetection.FaceDetectionPresenterHw.(FaceDetectionPresenterHw.kt:43) 在 co.sample.services.sampleService.onCreate(sampleService.kt:81) 在 android.app.ActivityThread.handleCreateService(ActivityThread.java:4150) 在 android.app.ActivityThread.access$2400(ActivityThread.java:273) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:2055) 在 android.os.Handler.dispatchMessage(Handler.java:112) 在 android.os.Looper.loop(Looper.java:216) 在 android.app.ActivityThread.main(ActivityThread.java:7625) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987) 2021-07-07 13:20:28.078 1486-7158/? I/chatty: uid=1000(system) Binder:1486_1D expire 1 line 2021-07-07 13:20:28.091 1486-6494/? I/chatty: uid=1000(system) Binder:1486_1C expire 6 lines 2021-07-07 13:20:28.095 1915-4243/? I/BoosterSwitchP:notifyUidState 什么都不做 2021-07-07 13:20:28.095 1915-4243/? I/DeepNoDisturbP:notifyUidState 2021-07-07 13:20:28.095 1915-4243/? I/BrowserChrP: notifyUidState 2021-07-07 13:20:29.423 16932-16932/? D/ActivityThread:将线程附加到应用程序 2021-07-07 13:20:30.122 16932-16932/? E/AndroidRuntime: 致命异常: main 进程:co.sample:sampleService,PID:16932 java.lang.RuntimeException:无法创建服务 co.sample.services.sampleService:java.lang.NullPointerException:尝试在 null 上调用虚拟方法 'android.content.Context com.huawei.agconnect.AGConnectInstance.getContext()'对象引用 在 android.app.ActivityThread.handleCreateService(ActivityThread.java:4169) 在 android.app.ActivityThread.access$2400(ActivityThread.java:273) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:2055) 在 android.os.Handler.dispatchMessage(Handler.java:112) 在 android.os.Looper.loop(Looper.java:216)

这里有什么问题?

【问题讨论】:

    标签: android kotlin machine-learning huawei-mobile-services huawei-ml-kit


    【解决方案1】:

    该错误是由上下文为空引起的,这是主要上下文尚未准备好。

    因为它试图在上下文创建尚未完成时在 onCreate 中获取 FaceDetectionPresenterHw。

    所以不要调用在 onCreate 中使用 FaceDetectionPresenterHw。只声明变量,然后及时调用getInstance,然后使用它。所以那个时间 Context 不为空。

    =============

    补充编辑:

    在开始使用分析器的服务中使用以下代码

    【讨论】:

    • 上下文不为空。我已经检查过了。同时我正在使用运行良好的上下文初始化其他一些东西
    【解决方案2】:

    要从后台服务使用HMS ML Kit,我们需要在out Application的OnCreate()方法中初始化AGConnect实例,如下所述

    class MyApplication : Application(){
    
    override fun onCreate() {
        super.onCreate()
    
        if (AGConnectInstance.getInstance() == null) {
            AGConnectInstance.initialize(applicationContext)
        }
    }
    

    【讨论】:

      【解决方案3】:

      后台服务是否执行Service类中的以下代码?

      MLFaceAnalyzer analyzer = MLAnalyzerFactory.getInstance().getFaceAnalyzer(setting);
      

      如下:

      如果在Service类中创建了MLFaceAnalyzer对象,则测试结果是正确的。请详细描述您的问题,以便我们为您提供适当的帮助。

      【讨论】:

      • 我编辑了这个问题。请看代码sn-p。
      • 嗨巴拉,你能把你的演示发给我们吗?根据您发布的代码,很难重现该问题。 :( 您可以将您的演示上传到 github 并与我们分享链接。
      • 嗨,非常感谢您为此付出的努力。实际上,我已经创建了一个演示来发送给您,并且在中途,我从新加坡的 HMS 办公室得到了答复。这个问题现在已经解决了。我会在这里发布答案
      • 太好了!很高兴听到您的问题已解决
      【解决方案4】:

      ​ 检查

      isNotificationCalled = true

      变量已经为真了。

      if (!isNotificationCalled) {
          createNotification()
      
      }
      

      在上面的代码中,您仅在 变量为 false 时创建通知。所以条件不成立。通过 isNotificationCalled = false 

      进行检查

      然后通知将创建。

      确保你已经在 app 目录下添加了 ag-connect.json 文件

      【讨论】:

      • 嗨,是的,我已经检查过了。通知也已创建并显示。在应用程序文件中初始化 AGConnect 实例后已修复问题
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-08
      • 2011-08-03
      相关资源
      最近更新 更多