개발하자

플러터 플러그인에서 수신기(브로드캐스트 수신기)를 어떻게 사용합니까?

Cuire 2022. 11. 30. 08:28
반응형

플러터 플러그인에서 수신기(브로드캐스트 수신기)를 어떻게 사용합니까?

문제

저는 Radar.io SDK의 일부 기능이 필요한 애플리케이션을 구축하고 있기 때문에 이 프로젝트가 끝난 후 플러그인을 다른 Fluter Community와 공유할 수 있도록 플러그인을 만들기로 결정했습니다. 문제는 이 플러그인에서 이벤트를 수신할 수 없다는 것입니다. 지리 위치 트리거 및 기타 백그라운드 이벤트와 같은 이벤트를 수신하려면 이 수신기가 실시간 정보를 수신해야 하므로 플러그인에 중요합니다.

나는 여기 보이는 안드로이드용 SDK(코틀린 사용)의 모든 기능을 성공적으로 구현했지만, 이벤트가 발생할 때 수신기가 호출되지 않는다. Radar.io 대시보드에서 위치가 업데이트되어 장치가 추적되는 것으로 알고 있지만, 다양한 이벤트가 발생할 때 수신기가 전혀 실행되지 않습니다.

내가 시도한 것

다음은 문서에서 매니페스트에 수신자를 등록하는 방법입니다.

  <receiver
      android:name=".MyRadarReceiver"
      android:enabled="true"
      android:exported="false">
      <intent-filter>
          <action android:name="io.radar.sdk.RECEIVED" />
      </intent-filter>
  </receiver>

이것은 표준 응용 프로그램에서 작동하지만 매니페스트에 수신기를 등록할 때 응용 프로그램이 수신기가 있는 플러그인 디렉터리를 찾지 않습니다. 대신 애플리케이션 안드로이드 디렉토리를 찾아 데이터 경로를 찾을 수 없다는 오류를 반환한다. 이로 인해 응용 프로그램이 종료됩니다.

이 문제를 해결하기 위해 나는 수신기를 프로그래밍 방식으로 설정할 수 있다는 것을 발견했고, 그래서 나는 그것을 시도하기로 결정했다.

플러그인의 메인 코틀린 파일 안에 나는 과 에서 실행될 다음 행들을 썼다. 이러한 기능은 기본적으로 onStart 기능인 것으로 알고 있습니다. 는 오래된 장치와의 호환성을 위해 유지되는 오래된 기능입니다.

val myRadarReceiver = MyRadarReceiver()
val intentFilter = IntentFilter()
intentFilter.addAction("io.radar.sdk.RECEIVED")
ContextWrapper(this.context).registerReceiver(myRadarReceiver, intentFilter)

참조된 클래스는 SDK에서 클래스의 확장으로, 이것이 내 브로드캐스트 수신기임을 의미합니다. 수업 내용은 다음과 같습니다.

public class MyRadarReceiver: RadarReceiver() {

  override fun onEventsReceived(context: Context, events: Array<RadarEvent>, user: RadarUser) {
    println("test: " + "an event was received")
  }

  override fun onLocationUpdated(context: Context, location: Location, user: RadarUser) {
    println("test: " + "location was updated")
  }

  override fun onClientLocationUpdated(context: Context, location: Location, stopped: Boolean, source: Radar.RadarLocationSource) {
    println("test: " + "client location updated")
  }

  override fun onError(context: Context, status: Radar.RadarStatus) {
    println("test: " + status)
  }

  override fun onLog(context: Context, message: String) {
    println("test: " + message)
  }

}

에뮬레이션된 장치에서 백그라운드 추적을 시작할 때 의 기능 중 하나가 실행될 것으로 예상했지만 단말기에 인쇄된 것은 없습니다. 오류는 없었지만 아무것도 수신되지 않았습니다. 이것은 내가 의도를 잘못 설정한 것인지 아니면 수신기가 잘못 작성된 것인지 궁금하게 만든다. 나는 의도를 설정하는 다른 방법을 모르기 때문에 MyRadarReceiver를 다음과 같은 더 간단한 형태로 다시 쓰기로 결정했다.

public class MyRadarReceiver: BroadcastReceiver() {
  override fun onReceive(context: Context, intent: Intent) {
    println("works! Something was received")
  }
}

안타깝게도 콘솔에 아무것도 인쇄되지 않았기 때문에 저는 이제 그것이 제 의도와 관련이 있다고 생각합니다.

요약

내가 시도할 수 있는 유일한 해결책은 플러그인 대신 애플리케이션에 수신기를 쓰는 것이다. 이것은 효과가 있을지도 모르지만, 나는 내가 끝났을 때 이 플러그인을 Fluter 커뮤니티와 공유하기를 희망하고 있었다. 레이더는 매우 강력한 플랫폼이며 이 플러그인을 Fluter 커뮤니티에 가져오는 것은 뛰어난 영향을 미칠 수 있습니다.




니트로돈의 코멘트를 본 후 나는 문제를 다르게 보고 해결책을 찾았다. 프로그래밍 방식의 수신기 초기화가 왜 작동하지 않았는지 잘 모르겠지만, 여기 내가 안드로이드 매니페스트에 넣은 것이 있다.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.youorganization.yourproject">
  <application
    android:name="io.flutter.app.FlutterApplication">
    <receiver
      android:name=".MyRadarReceiver"
      android:enabled="true"
      android:exported="false">
        <intent-filter>
            <action android:name="io.radar.sdk.RECEIVED" />
        </intent-filter>
    </receiver>
  </application>
</manifest>

응용프로그램 태그에 Android 레이블 또는 기타 항목을 추가할 수 없습니다. 그렇지 않으면 응용프로그램의 Android 매니페스트와 충돌하여 오류가 발생합니다. 이러한 이유로, 당신은 단지 이름만 포함하는 간단한 애플리케이션 태그에 수신자를 선언하기만 하면 된다.




Android 기본 사항

유용한 자료는 다음과 같습니다.

실행 시 브로드캐스트 수신기를 등록할지, 매니페스트에 정적으로 선언할지에 따라 다릅니다. 읽으십시오. 수신기를 실행하려면 정적으로 선언해야 합니다. 앱이 이미 실행 중일 때만 수신하도록 하려면 런타임에 등록하십시오.

이것은 모두 평범한 안드로이드 물건들이다.


펄럭이는방법

브로드캐스트 수신기에서 Fluter 응용 프로그램, Fluter Engine 또는 DartVM이 실행되고 있다는 보장은 없습니다. Flower를 실행하려면 Isolate를 생성해야 합니다.

flutterEngine = new FlutterEngine(context, null);
DartExecutor executor = flutterEngine.getDartExecutor();
backgroundMethodChannel = new MethodChannel(executor.getBinaryMessenger(), "your channel name");
backgroundMethodChannel.setMethodCallHandler(this);
// Get and launch the users app isolate manually:
executor.executeDartEntrypoint(DartExecutor.DartEntrypoint.createDefault());

그런 다음, 다음과 같이 전화하여 플러그인/플러터 응용프로그램에 알릴 수 있습니다.

// Even though lifecycle parameter is @NonNull, the implementation `FlutterEngineConnectionRegistry`
// does not use it, because it is a bug in the API design. See https://github.com/flutter/flutter/issues/90316
flutterEngine.getBroadcastReceiverControlSurface().attachToBroadcastReceiver(this, null); // This is the class you are in, the broadcast receiver

브로드캐스트 수신기 실행을 마치려고 할 때:

flutterEngine.getBroadcastReceiverControlSurface().detachFromBroadcastReceiver();

이렇게 하면 브로드캐스트 수신기가 연결 및 분리될 때 플러그인에 대한 정보가 표시됩니다.


반응형