flutter_in_app_update icon indicating copy to clipboard operation
flutter_in_app_update copied to clipboard

Migrating to jnigen bindings

Open orestesgaolin opened this issue 10 months ago • 1 comments

Hey, I'm working on bindings to call Google Play SDK In-App Update APIs directly from Dart using jni and jnigen.

This makes it possible to call the SDK APIs directly without passing messages via method channels etc.

Example usage:


  void getAppUpdateInfo() {
    localPrint('Checking for update');
    final context = JObject.fromReference(Jni.getCachedApplicationContext());
    manager = AppUpdateManagerFactory.create(context);

    localPrint('Got manager instance: ${manager}');
    appInfoTask = manager?.getAppUpdateInfo();

    localPrint('Got app info task: ${appInfoTask}');

    appInfoTask?.addOnSuccessListener(
      OnSuccessListener.implement(
        $OnSuccessListener<AppUpdateInfo>(
          onSuccess$async: true,
          TResult: AppUpdateInfo.type,
          onSuccess: (result) {
            setState(() {
              appUpdateInfo = result;
            });
          },
        ),
      ),
    );

    appInfoTask?.addOnFailureListener(
      OnFailureListener.implement(
        $OnFailureListener(
          onFailure$async: true,
          onFailure: (e) {
            localPrint(e.toString());
          },
        ),
      ),
    );

    appInfoTask?.addOnCanceledListener(
      OnCanceledListener.implement(
        $OnCanceledListener(
          onCanceled: () {
            localPrint('Canceled');
            setState(() {
              isCanceled = true;
            });
          },
        ),
      ),
    );
  }

And updating the app:


  void onImmediateUpdate() {
    final activity = JObject.fromReference(Jni.getCurrentActivity());

    final allowed = appUpdateInfo!.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE);

    if (!allowed) {
      localPrint('Update type not allowed');
      return;
    }

    _updateTask = manager?.startUpdateFlow(
      appUpdateInfo!,
      activity,
      AppUpdateOptions.newBuilder(AppUpdateType.IMMEDIATE)
          .setAllowAssetPackDeletion(true)
          .build(),
    );

    _updateTask?.addOnSuccessListener(
      OnSuccessListener.implement(
        $OnSuccessListener(
          onSuccess$async: true,
          TResult: InstallStatus.type,
          onSuccess: (result) {
            localPrint('Update success ${result}');
          },
        ),
      ),
    );

    _updateTask?.addOnFailureListener(
      OnFailureListener.implement(
        $OnFailureListener(
          onFailure$async: true,
          onFailure: (e) {
            localPrint('Update failed');
            localPrint(e.toString());
          },
        ),
      ),
    );

    _updateTask?.addOnCanceledListener(
      OnCanceledListener.implement(
        $OnCanceledListener(
          onCanceled: () {
            localPrint('Update canceled');
          },
        ),
      ),
    );
  }

I was wondering if you'd be open to contributing this change to this plugin? It would obviously be a breaking change, but at the same time the native API could be exposed directly as it is documented here https://developer.android.com/guide/playcore/in-app-updates/kotlin-java.

For convenience I think it would be good to have a wrapper around the calls that you can see in the example above, so that manager.getAppUpdateInfo() could be called like this:

final appUpdateInfo = await manager.getAppUpdateInfo();

orestesgaolin avatar Feb 09 '25 21:02 orestesgaolin

Very interesting indeed but I'm currently not too eager in spending too much time using jnigen as its status is experimental

jonasbark avatar Feb 10 '25 00:02 jonasbark