update app_review
This commit is contained in:
@@ -22,10 +22,11 @@ rootProject.allprojects {
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
namespace 'com.appleeducate.appreview'
|
||||
compileSdkVersion 34
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
minSdkVersion 21
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
lintOptions {
|
||||
@@ -35,5 +36,5 @@ android {
|
||||
|
||||
dependencies {
|
||||
api 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
implementation 'com.google.android.play:core:1.10.3'
|
||||
implementation 'com.google.android.play:review:2.0.1'
|
||||
}
|
||||
|
||||
+113
-63
@@ -1,6 +1,8 @@
|
||||
package com.appleeducate.appreview;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -8,128 +10,175 @@ import androidx.annotation.Nullable;
|
||||
import com.google.android.play.core.review.ReviewInfo;
|
||||
import com.google.android.play.core.review.ReviewManager;
|
||||
import com.google.android.play.core.review.ReviewManagerFactory;
|
||||
import com.google.android.play.core.tasks.OnCompleteListener;
|
||||
import com.google.android.play.core.tasks.Task;
|
||||
import com.google.android.play.core.review.testing.FakeReviewManager;
|
||||
import com.google.android.gms.tasks.OnCompleteListener;
|
||||
import com.google.android.gms.tasks.Task;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import io.flutter.embedding.engine.plugins.FlutterPlugin;
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
|
||||
import io.flutter.plugin.common.BinaryMessenger;
|
||||
import io.flutter.plugin.common.MethodCall;
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
|
||||
import io.flutter.plugin.common.MethodChannel.Result;
|
||||
import io.flutter.plugin.common.PluginRegistry.Registrar;
|
||||
|
||||
/** AppReviewPlugin */
|
||||
public class AppReviewPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware {
|
||||
private static final String CHANNEL_NAME = "app_review";
|
||||
|
||||
public class AppReviewPlugin implements FlutterPlugin, Messages.AppReviewApi, ActivityAware {
|
||||
private WeakReference<Activity> currentActivity;
|
||||
|
||||
private MethodChannel channel;
|
||||
|
||||
private ReviewManager manager;
|
||||
@Nullable
|
||||
private ReviewInfo reviewInfo;
|
||||
|
||||
public AppReviewPlugin() {
|
||||
}
|
||||
|
||||
/** Plugin registration. */
|
||||
public static void registerWith(Registrar registrar) {
|
||||
AppReviewPlugin simplePermissionsPlugin = new AppReviewPlugin();
|
||||
simplePermissionsPlugin.setupChannel(registrar.messenger());
|
||||
// registrar.addRequestPermissionsResultListener(simplePermissionsPlugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
|
||||
setupChannel(binding.getBinaryMessenger());
|
||||
Messages.AppReviewApi.setUp(binding.getBinaryMessenger(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
|
||||
teardownChannel();
|
||||
}
|
||||
|
||||
private void setupChannel(BinaryMessenger messenger) {
|
||||
channel = new MethodChannel(messenger, CHANNEL_NAME);
|
||||
channel.setMethodCallHandler(this);
|
||||
}
|
||||
|
||||
private void teardownChannel() {
|
||||
channel.setMethodCallHandler(null);
|
||||
channel = null;
|
||||
Messages.AppReviewApi.setUp(binding.getBinaryMessenger(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMethodCall(MethodCall call, @NonNull Result result) {
|
||||
String method = call.method;
|
||||
switch (method) {
|
||||
case "isRequestReviewAvailable":
|
||||
isRequestReviewAvailable(result);
|
||||
break;
|
||||
case "requestReview":
|
||||
requestReview(result);
|
||||
break;
|
||||
default:
|
||||
result.notImplemented();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void isRequestReviewAvailable(final Result result) {
|
||||
if (currentActivity == null || currentActivity.get() == null) {
|
||||
result.error("error", "Android activity not available", null);
|
||||
public void isRequestReviewAvailable(Messages.Result<Boolean> result) {
|
||||
if (manager == null) {
|
||||
result.error(new Exception("ReviewManager not initialized"));
|
||||
return;
|
||||
}
|
||||
ReviewManager manager = ReviewManagerFactory.create(currentActivity.get());
|
||||
Task<ReviewInfo> request = manager.requestReviewFlow();
|
||||
request.addOnCompleteListener(new OnCompleteListener<ReviewInfo>() {
|
||||
@Override
|
||||
public void onComplete(@NonNull Task<ReviewInfo> task) {
|
||||
if (task.isSuccessful()) {
|
||||
reviewInfo = task.getResult();
|
||||
result.success("1");
|
||||
result.success(true);
|
||||
} else {
|
||||
result.success("0");
|
||||
result.success(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void requestReview(final Result result) {
|
||||
@Override
|
||||
public void openStoreListing(@Nullable String storeId, Messages.VoidResult result) {
|
||||
if (currentActivity == null || currentActivity.get() == null) {
|
||||
result.error("error", "Android activity not available", null);
|
||||
result.error(new Exception("Android activity not available"));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + storeId));
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
currentActivity.get().startActivity(intent);
|
||||
result.success();
|
||||
} catch (android.content.ActivityNotFoundException anfe) {
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + storeId));
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
currentActivity.get().startActivity(intent);
|
||||
result.success();
|
||||
} catch (Exception e) {
|
||||
result.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openAppStoreReview(@Nullable String storeId, Messages.VoidResult result) {
|
||||
openStoreListing(storeId, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lookupAppId(@NonNull String bundleId, @Nullable String countryCode, Messages.NullableResult<String> result) {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
String country = countryCode != null ? countryCode : "";
|
||||
java.net.URL url = new java.net.URL("https://itunes.apple.com/" + country + "/lookup?bundleId=" + bundleId);
|
||||
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setConnectTimeout(5000);
|
||||
connection.setReadTimeout(5000);
|
||||
|
||||
if (connection.getResponseCode() == 200) {
|
||||
java.io.InputStream inputStream = connection.getInputStream();
|
||||
java.io.BufferedReader reader = new java.io.BufferedReader(new java.io.InputStreamReader(inputStream));
|
||||
StringBuilder response = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
response.append(line);
|
||||
}
|
||||
reader.close();
|
||||
|
||||
org.json.JSONObject json = new org.json.JSONObject(response.toString());
|
||||
org.json.JSONArray results = json.getJSONArray("results");
|
||||
if (results.length() > 0) {
|
||||
org.json.JSONObject firstResult = results.getJSONObject(0);
|
||||
if (firstResult.has("trackId")) {
|
||||
String trackId = String.valueOf(firstResult.getInt("trackId"));
|
||||
new android.os.Handler(android.os.Looper.getMainLooper()).post(() -> result.success(trackId));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
new android.os.Handler(android.os.Looper.getMainLooper()).post(() -> result.success(null));
|
||||
} catch (Exception e) {
|
||||
new android.os.Handler(android.os.Looper.getMainLooper()).post(() -> result.error(e));
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getBundleId(Messages.Result<String> result) {
|
||||
if (currentActivity == null || currentActivity.get() == null) {
|
||||
result.error(new Exception("Android activity not available"));
|
||||
return;
|
||||
}
|
||||
result.success(currentActivity.get().getPackageName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestReview(@NonNull Boolean testMode, Messages.NullableResult<String> result) {
|
||||
if (currentActivity == null || currentActivity.get() == null) {
|
||||
result.error(new Exception("Android activity not available"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (testMode) {
|
||||
manager = new FakeReviewManager(currentActivity.get());
|
||||
} else {
|
||||
if (manager == null || manager instanceof FakeReviewManager) {
|
||||
manager = ReviewManagerFactory.create(currentActivity.get());
|
||||
}
|
||||
}
|
||||
|
||||
if (reviewInfo == null) {
|
||||
getReviewInfoAndRequestReview(result);
|
||||
getReviewInfoAndRequestReview(testMode, result);
|
||||
return;
|
||||
}
|
||||
ReviewManager manager = ReviewManagerFactory.create(currentActivity.get());
|
||||
Task<Void> task = manager.launchReviewFlow(currentActivity.get(), reviewInfo);
|
||||
task.addOnCompleteListener(new OnCompleteListener<Void>() {
|
||||
@Override
|
||||
public void onComplete(@NonNull Task<Void> task) {
|
||||
reviewInfo = null;
|
||||
result.success("Success: " + task.isSuccessful());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void getReviewInfoAndRequestReview(final Result result) {
|
||||
ReviewManager manager = ReviewManagerFactory.create(currentActivity.get());
|
||||
private void getReviewInfoAndRequestReview(Boolean testMode, final Messages.NullableResult<String> result) {
|
||||
if (manager == null) {
|
||||
result.error(new Exception("ReviewManager not initialized"));
|
||||
return;
|
||||
}
|
||||
Task<ReviewInfo> request = manager.requestReviewFlow();
|
||||
request.addOnCompleteListener(new OnCompleteListener<ReviewInfo>() {
|
||||
@Override
|
||||
public void onComplete(@NonNull Task<ReviewInfo> task) {
|
||||
if (task.isSuccessful()) {
|
||||
reviewInfo = task.getResult();
|
||||
requestReview(result);
|
||||
requestReview(testMode, result);
|
||||
} else {
|
||||
result.error("Requesting review not possible", null, null);
|
||||
result.error(new Exception("Requesting review not possible"));
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -138,6 +187,7 @@ public class AppReviewPlugin implements FlutterPlugin, MethodCallHandler, Activi
|
||||
@Override
|
||||
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
|
||||
currentActivity = new WeakReference<>(binding.getActivity());
|
||||
manager = ReviewManagerFactory.create(binding.getActivity());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -153,6 +203,6 @@ public class AppReviewPlugin implements FlutterPlugin, MethodCallHandler, Activi
|
||||
@Override
|
||||
public void onDetachedFromActivity() {
|
||||
currentActivity = null;
|
||||
manager = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
// Autogenerated from Pigeon (v26.1.5), do not edit directly.
|
||||
// See also: https://pub.dev/packages/pigeon
|
||||
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
|
||||
|
||||
package com.appleeducate.appreview
|
||||
|
||||
import android.util.Log
|
||||
import io.flutter.plugin.common.BasicMessageChannel
|
||||
import io.flutter.plugin.common.BinaryMessenger
|
||||
import io.flutter.plugin.common.EventChannel
|
||||
import io.flutter.plugin.common.MessageCodec
|
||||
import io.flutter.plugin.common.StandardMethodCodec
|
||||
import io.flutter.plugin.common.StandardMessageCodec
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.nio.ByteBuffer
|
||||
private object MessagesPigeonUtils {
|
||||
|
||||
fun wrapResult(result: Any?): List<Any?> {
|
||||
return listOf(result)
|
||||
}
|
||||
|
||||
fun wrapError(exception: Throwable): List<Any?> {
|
||||
return if (exception is FlutterError) {
|
||||
listOf(
|
||||
exception.code,
|
||||
exception.message,
|
||||
exception.details
|
||||
)
|
||||
} else {
|
||||
listOf(
|
||||
exception.javaClass.simpleName,
|
||||
exception.toString(),
|
||||
"Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Error class for passing custom error details to Flutter via a thrown PlatformException.
|
||||
* @property code The error code.
|
||||
* @property message The error message.
|
||||
* @property details The error details. Must be a datatype supported by the api codec.
|
||||
*/
|
||||
class FlutterError (
|
||||
val code: String,
|
||||
override val message: String? = null,
|
||||
val details: Any? = null
|
||||
) : Throwable()
|
||||
private open class MessagesPigeonCodec : StandardMessageCodec() {
|
||||
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
|
||||
return super.readValueOfType(type, buffer)
|
||||
}
|
||||
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
|
||||
super.writeValue(stream, value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||
interface AppReviewApi {
|
||||
/**
|
||||
* Request review.
|
||||
*
|
||||
* Tells StoreKit / Play Store to ask the user to rate or review your app, if appropriate.
|
||||
* Supported only in iOS 10.3+ and Android with Play Services installed (see [isRequestReviewAvailable]).
|
||||
*
|
||||
* Returns string with details message.
|
||||
*/
|
||||
fun requestReview(testMode: Boolean, callback: (Result<String?>) -> Unit)
|
||||
/** Check if [requestReview] feature available. */
|
||||
fun isRequestReviewAvailable(callback: (Result<Boolean>) -> Unit)
|
||||
/**
|
||||
* Opens the store listing for the specified app.
|
||||
*
|
||||
* [storeId] is the package name (Android) or App ID (iOS/macOS).
|
||||
*/
|
||||
fun openStoreListing(storeId: String?, callback: (Result<Unit>) -> Unit)
|
||||
/**
|
||||
* Opens the App Store review page (iOS/macOS only).
|
||||
*
|
||||
* [storeId] is the App ID.
|
||||
*/
|
||||
fun openAppStoreReview(storeId: String?, callback: (Result<Unit>) -> Unit)
|
||||
/** Returns package name for application. */
|
||||
fun getBundleId(callback: (Result<String>) -> Unit)
|
||||
/**
|
||||
* Requests the App ID from the App Store (via iTunes Lookup API).
|
||||
*
|
||||
* [bundleId] is the bundle identifier to look up.
|
||||
* [countryCode] is the optional country code.
|
||||
*/
|
||||
fun lookupAppId(bundleId: String, countryCode: String?, callback: (Result<String?>) -> Unit)
|
||||
|
||||
companion object {
|
||||
/** The codec used by AppReviewApi. */
|
||||
val codec: MessageCodec<Any?> by lazy {
|
||||
MessagesPigeonCodec()
|
||||
}
|
||||
/** Sets up an instance of `AppReviewApi` to handle messages through the `binaryMessenger`. */
|
||||
@JvmOverloads
|
||||
fun setUp(binaryMessenger: BinaryMessenger, api: AppReviewApi?, messageChannelSuffix: String = "") {
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.app_review.AppReviewApi.requestReview$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val testModeArg = args[0] as Boolean
|
||||
api.requestReview(testModeArg) { result: Result<String?> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(MessagesPigeonUtils.wrapError(error))
|
||||
} else {
|
||||
val data = result.getOrNull()
|
||||
reply.reply(MessagesPigeonUtils.wrapResult(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.app_review.AppReviewApi.isRequestReviewAvailable$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
api.isRequestReviewAvailable{ result: Result<Boolean> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(MessagesPigeonUtils.wrapError(error))
|
||||
} else {
|
||||
val data = result.getOrNull()
|
||||
reply.reply(MessagesPigeonUtils.wrapResult(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.app_review.AppReviewApi.openStoreListing$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val storeIdArg = args[0] as String?
|
||||
api.openStoreListing(storeIdArg) { result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(MessagesPigeonUtils.wrapError(error))
|
||||
} else {
|
||||
reply.reply(MessagesPigeonUtils.wrapResult(null))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.app_review.AppReviewApi.openAppStoreReview$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val storeIdArg = args[0] as String?
|
||||
api.openAppStoreReview(storeIdArg) { result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(MessagesPigeonUtils.wrapError(error))
|
||||
} else {
|
||||
reply.reply(MessagesPigeonUtils.wrapResult(null))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.app_review.AppReviewApi.getBundleId$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
api.getBundleId{ result: Result<String> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(MessagesPigeonUtils.wrapError(error))
|
||||
} else {
|
||||
val data = result.getOrNull()
|
||||
reply.reply(MessagesPigeonUtils.wrapResult(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.app_review.AppReviewApi.lookupAppId$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val bundleIdArg = args[0] as String
|
||||
val countryCodeArg = args[1] as String?
|
||||
api.lookupAppId(bundleIdArg, countryCodeArg) { result: Result<String?> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(MessagesPigeonUtils.wrapError(error))
|
||||
} else {
|
||||
val data = result.getOrNull()
|
||||
reply.reply(MessagesPigeonUtils.wrapResult(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,325 @@
|
||||
// Autogenerated from Pigeon (v26.1.5), do not edit directly.
|
||||
// See also: https://pub.dev/packages/pigeon
|
||||
|
||||
package com.appleeducate.appreview;
|
||||
|
||||
import android.util.Log;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import io.flutter.plugin.common.BasicMessageChannel;
|
||||
import io.flutter.plugin.common.BinaryMessenger;
|
||||
import io.flutter.plugin.common.MessageCodec;
|
||||
import io.flutter.plugin.common.StandardMessageCodec;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/** Generated class from Pigeon. */
|
||||
@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression", "serial"})
|
||||
public class Messages {
|
||||
|
||||
/** Error class for passing custom error details to Flutter via a thrown PlatformException. */
|
||||
public static class FlutterError extends RuntimeException {
|
||||
|
||||
/** The error code. */
|
||||
public final String code;
|
||||
|
||||
/** The error details. Must be a datatype supported by the api codec. */
|
||||
public final Object details;
|
||||
|
||||
public FlutterError(@NonNull String code, @Nullable String message, @Nullable Object details)
|
||||
{
|
||||
super(message);
|
||||
this.code = code;
|
||||
this.details = details;
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
protected static ArrayList<Object> wrapError(@NonNull Throwable exception) {
|
||||
ArrayList<Object> errorList = new ArrayList<>(3);
|
||||
if (exception instanceof FlutterError) {
|
||||
FlutterError error = (FlutterError) exception;
|
||||
errorList.add(error.code);
|
||||
errorList.add(error.getMessage());
|
||||
errorList.add(error.details);
|
||||
} else {
|
||||
errorList.add(exception.toString());
|
||||
errorList.add(exception.getClass().getSimpleName());
|
||||
errorList.add(
|
||||
"Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception));
|
||||
}
|
||||
return errorList;
|
||||
}
|
||||
|
||||
private static class PigeonCodec extends StandardMessageCodec {
|
||||
public static final PigeonCodec INSTANCE = new PigeonCodec();
|
||||
|
||||
private PigeonCodec() {}
|
||||
|
||||
@Override
|
||||
protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) {
|
||||
switch (type) {
|
||||
default:
|
||||
return super.readValueOfType(type, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) {
|
||||
{
|
||||
super.writeValue(stream, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Asynchronous error handling return type for non-nullable API method returns. */
|
||||
public interface Result<T> {
|
||||
/** Success case callback method for handling returns. */
|
||||
void success(@NonNull T result);
|
||||
|
||||
/** Failure case callback method for handling errors. */
|
||||
void error(@NonNull Throwable error);
|
||||
}
|
||||
/** Asynchronous error handling return type for nullable API method returns. */
|
||||
public interface NullableResult<T> {
|
||||
/** Success case callback method for handling returns. */
|
||||
void success(@Nullable T result);
|
||||
|
||||
/** Failure case callback method for handling errors. */
|
||||
void error(@NonNull Throwable error);
|
||||
}
|
||||
/** Asynchronous error handling return type for void API method returns. */
|
||||
public interface VoidResult {
|
||||
/** Success case callback method for handling returns. */
|
||||
void success();
|
||||
|
||||
/** Failure case callback method for handling errors. */
|
||||
void error(@NonNull Throwable error);
|
||||
}
|
||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||
public interface AppReviewApi {
|
||||
/**
|
||||
* Request review.
|
||||
*
|
||||
* Tells StoreKit / Play Store to ask the user to rate or review your app, if appropriate.
|
||||
* Supported only in iOS 10.3+ and Android with Play Services installed (see [isRequestReviewAvailable]).
|
||||
*
|
||||
* Returns string with details message.
|
||||
*/
|
||||
void requestReview(@NonNull Boolean testMode, @NonNull NullableResult<String> result);
|
||||
/** Check if [requestReview] feature available. */
|
||||
void isRequestReviewAvailable(@NonNull Result<Boolean> result);
|
||||
/**
|
||||
* Opens the store listing for the specified app.
|
||||
*
|
||||
* [storeId] is the package name (Android) or App ID (iOS/macOS).
|
||||
*/
|
||||
void openStoreListing(@Nullable String storeId, @NonNull VoidResult result);
|
||||
/**
|
||||
* Opens the App Store review page (iOS/macOS only).
|
||||
*
|
||||
* [storeId] is the App ID.
|
||||
*/
|
||||
void openAppStoreReview(@Nullable String storeId, @NonNull VoidResult result);
|
||||
/** Returns package name for application. */
|
||||
void getBundleId(@NonNull Result<String> result);
|
||||
/**
|
||||
* Requests the App ID from the App Store (via iTunes Lookup API).
|
||||
*
|
||||
* [bundleId] is the bundle identifier to look up.
|
||||
* [countryCode] is the optional country code.
|
||||
*/
|
||||
void lookupAppId(@NonNull String bundleId, @Nullable String countryCode, @NonNull NullableResult<String> result);
|
||||
|
||||
/** The codec used by AppReviewApi. */
|
||||
static @NonNull MessageCodec<Object> getCodec() {
|
||||
return PigeonCodec.INSTANCE;
|
||||
}
|
||||
/**Sets up an instance of `AppReviewApi` to handle messages through the `binaryMessenger`. */
|
||||
static void setUp(@NonNull BinaryMessenger binaryMessenger, @Nullable AppReviewApi api) {
|
||||
setUp(binaryMessenger, "", api);
|
||||
}
|
||||
static void setUp(@NonNull BinaryMessenger binaryMessenger, @NonNull String messageChannelSuffix, @Nullable AppReviewApi api) {
|
||||
messageChannelSuffix = messageChannelSuffix.isEmpty() ? "" : "." + messageChannelSuffix;
|
||||
{
|
||||
BasicMessageChannel<Object> channel =
|
||||
new BasicMessageChannel<>(
|
||||
binaryMessenger, "dev.flutter.pigeon.app_review.AppReviewApi.requestReview" + messageChannelSuffix, getCodec());
|
||||
if (api != null) {
|
||||
channel.setMessageHandler(
|
||||
(message, reply) -> {
|
||||
ArrayList<Object> wrapped = new ArrayList<>();
|
||||
ArrayList<Object> args = (ArrayList<Object>) message;
|
||||
Boolean testModeArg = (Boolean) args.get(0);
|
||||
NullableResult<String> resultCallback =
|
||||
new NullableResult<String>() {
|
||||
public void success(String result) {
|
||||
wrapped.add(0, result);
|
||||
reply.reply(wrapped);
|
||||
}
|
||||
|
||||
public void error(Throwable error) {
|
||||
ArrayList<Object> wrappedError = wrapError(error);
|
||||
reply.reply(wrappedError);
|
||||
}
|
||||
};
|
||||
|
||||
api.requestReview(testModeArg, resultCallback);
|
||||
});
|
||||
} else {
|
||||
channel.setMessageHandler(null);
|
||||
}
|
||||
}
|
||||
{
|
||||
BasicMessageChannel<Object> channel =
|
||||
new BasicMessageChannel<>(
|
||||
binaryMessenger, "dev.flutter.pigeon.app_review.AppReviewApi.isRequestReviewAvailable" + messageChannelSuffix, getCodec());
|
||||
if (api != null) {
|
||||
channel.setMessageHandler(
|
||||
(message, reply) -> {
|
||||
ArrayList<Object> wrapped = new ArrayList<>();
|
||||
Result<Boolean> resultCallback =
|
||||
new Result<Boolean>() {
|
||||
public void success(Boolean result) {
|
||||
wrapped.add(0, result);
|
||||
reply.reply(wrapped);
|
||||
}
|
||||
|
||||
public void error(Throwable error) {
|
||||
ArrayList<Object> wrappedError = wrapError(error);
|
||||
reply.reply(wrappedError);
|
||||
}
|
||||
};
|
||||
|
||||
api.isRequestReviewAvailable(resultCallback);
|
||||
});
|
||||
} else {
|
||||
channel.setMessageHandler(null);
|
||||
}
|
||||
}
|
||||
{
|
||||
BasicMessageChannel<Object> channel =
|
||||
new BasicMessageChannel<>(
|
||||
binaryMessenger, "dev.flutter.pigeon.app_review.AppReviewApi.openStoreListing" + messageChannelSuffix, getCodec());
|
||||
if (api != null) {
|
||||
channel.setMessageHandler(
|
||||
(message, reply) -> {
|
||||
ArrayList<Object> wrapped = new ArrayList<>();
|
||||
ArrayList<Object> args = (ArrayList<Object>) message;
|
||||
String storeIdArg = (String) args.get(0);
|
||||
VoidResult resultCallback =
|
||||
new VoidResult() {
|
||||
public void success() {
|
||||
wrapped.add(0, null);
|
||||
reply.reply(wrapped);
|
||||
}
|
||||
|
||||
public void error(Throwable error) {
|
||||
ArrayList<Object> wrappedError = wrapError(error);
|
||||
reply.reply(wrappedError);
|
||||
}
|
||||
};
|
||||
|
||||
api.openStoreListing(storeIdArg, resultCallback);
|
||||
});
|
||||
} else {
|
||||
channel.setMessageHandler(null);
|
||||
}
|
||||
}
|
||||
{
|
||||
BasicMessageChannel<Object> channel =
|
||||
new BasicMessageChannel<>(
|
||||
binaryMessenger, "dev.flutter.pigeon.app_review.AppReviewApi.openAppStoreReview" + messageChannelSuffix, getCodec());
|
||||
if (api != null) {
|
||||
channel.setMessageHandler(
|
||||
(message, reply) -> {
|
||||
ArrayList<Object> wrapped = new ArrayList<>();
|
||||
ArrayList<Object> args = (ArrayList<Object>) message;
|
||||
String storeIdArg = (String) args.get(0);
|
||||
VoidResult resultCallback =
|
||||
new VoidResult() {
|
||||
public void success() {
|
||||
wrapped.add(0, null);
|
||||
reply.reply(wrapped);
|
||||
}
|
||||
|
||||
public void error(Throwable error) {
|
||||
ArrayList<Object> wrappedError = wrapError(error);
|
||||
reply.reply(wrappedError);
|
||||
}
|
||||
};
|
||||
|
||||
api.openAppStoreReview(storeIdArg, resultCallback);
|
||||
});
|
||||
} else {
|
||||
channel.setMessageHandler(null);
|
||||
}
|
||||
}
|
||||
{
|
||||
BasicMessageChannel<Object> channel =
|
||||
new BasicMessageChannel<>(
|
||||
binaryMessenger, "dev.flutter.pigeon.app_review.AppReviewApi.getBundleId" + messageChannelSuffix, getCodec());
|
||||
if (api != null) {
|
||||
channel.setMessageHandler(
|
||||
(message, reply) -> {
|
||||
ArrayList<Object> wrapped = new ArrayList<>();
|
||||
Result<String> resultCallback =
|
||||
new Result<String>() {
|
||||
public void success(String result) {
|
||||
wrapped.add(0, result);
|
||||
reply.reply(wrapped);
|
||||
}
|
||||
|
||||
public void error(Throwable error) {
|
||||
ArrayList<Object> wrappedError = wrapError(error);
|
||||
reply.reply(wrappedError);
|
||||
}
|
||||
};
|
||||
|
||||
api.getBundleId(resultCallback);
|
||||
});
|
||||
} else {
|
||||
channel.setMessageHandler(null);
|
||||
}
|
||||
}
|
||||
{
|
||||
BasicMessageChannel<Object> channel =
|
||||
new BasicMessageChannel<>(
|
||||
binaryMessenger, "dev.flutter.pigeon.app_review.AppReviewApi.lookupAppId" + messageChannelSuffix, getCodec());
|
||||
if (api != null) {
|
||||
channel.setMessageHandler(
|
||||
(message, reply) -> {
|
||||
ArrayList<Object> wrapped = new ArrayList<>();
|
||||
ArrayList<Object> args = (ArrayList<Object>) message;
|
||||
String bundleIdArg = (String) args.get(0);
|
||||
String countryCodeArg = (String) args.get(1);
|
||||
NullableResult<String> resultCallback =
|
||||
new NullableResult<String>() {
|
||||
public void success(String result) {
|
||||
wrapped.add(0, result);
|
||||
reply.reply(wrapped);
|
||||
}
|
||||
|
||||
public void error(Throwable error) {
|
||||
ArrayList<Object> wrappedError = wrapError(error);
|
||||
reply.reply(wrappedError);
|
||||
}
|
||||
};
|
||||
|
||||
api.lookupAppId(bundleIdArg, countryCodeArg, resultCallback);
|
||||
});
|
||||
} else {
|
||||
channel.setMessageHandler(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user