Reputation: 1742
My flutter app can't proceed with payment in the PayHere payment gateway in the release apk. In the debug mode and run the app in release mode working fine. but only getting an error when build and running release apk.
Upvotes: 5
Views: 881
Reputation: 740
Most likely this is an issue with Android's code minification on Release builds. The proposed solution is to try and prevent the PayHere code from getting stripped in Release builds, by adding proper ProGuard rules.
-keep class lk.payhere.** { *; }
minifyEnabled true
useProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
The final result in the "build.gradle" file should look something like this:
android {
compileSdkVersion 29
// ...
buildTypes {
release {
signingConfig signingConfigs.debug
// the code we added...
minifyEnabled true
useProguard true // android Gradle plugin 3.4.0 or higher, the plugin no longer uses ProGuard - default value is true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
Do a clean build and see if your issue is resolved.
If the issue still persists, try adding an Alert popup in the PayHere Flutter SDK's error handler to see if a readable error is returned.
Something like:
PayHere.startPayment(
paymentObject,
(paymentId) {
print("One Time Payment Success. Payment Id: $paymentId");
},
(error) {
print("One Time Payment Failed. Error: $error");
// add alert code here
},
() {
print("One Time Payment Dismissed");
}
);
Last resort would be to contact PayHere themselves for support. If that is the case, you can mail them at [email protected]
Note that ProGuard rules also work with Android's R8 code shrinking as per the documentation.
When building the release version of your app, by default, R8 automatically performs the compile-time tasks described above for you. However, you can disable certain tasks or customize R8’s behavior through ProGuard rules files. In fact, R8 works with all of your existing ProGuard rules files, so updating the Android Gradle plugin to use R8 should not require you to change your existing rules.
Upvotes: 1
Reputation: 1742
The issue is caused by Flutter’s R8 code shrinking which is turned on by default for Release builds as stated here. Since Android Gradle version 3.4.0, R8 does not use Proguard under the hood as mentioned here. However, R8 still uses the proguard rule files in the exact format, to exclude classes from being obfuscated/removed only if explicitly provided. Otherwise, unused code will be stripped out of the final product.
It is understood that the MethodChannels used internally by Flutter and Dart to link between the PayHere Android SDK and PayHere Flutter Dart components are affected by this code obfuscation process.
There are two solutions to resolving the issue. The first offers more flexibility down the line, should developers extend the existing codebase. The second solution is a quick “hotfix”, which disables code obfuscation in favor of ease of applicability.
NOTE: Please maintain a backup of your existing codebase before carrying out the solutions mentioned hereafter. This step is recommended even if you have version control enabled, since .gitignore definitions might not track changes to files carrying sensitive information.
This solution is preferred if you are comfortable creating Pro-guard rule files manually or you have already configured Pro-guard rules. The steps required are mentioned below.
Open your Flutter Project in your preferred IDE.
Create a new file named, “proguard-rules.pro” in the “/android/app” folder.
Add the following lines of code in the “proguard-rules.pro” file created in Step 2 above.
#Flutter Wrapper
-keep class io.flutter.app.** { *; }
-keep class io.flutter.plugin.** { *; }
-keep class io.flutter.util.** { *; }
-keep class io.flutter.view.** { *; }
-keep class io.flutter.** { *; }
-keep class io.flutter.plugins.** { *; }
#the required rule
-keep class lk.payhere.** { *; }
The above code excludes all default Flutter libraries and the PayHere Android SDK classes. Make sure you do not have overlapping rules. If you already had an existing “proguard-rules.pro” file, only add the last line.
Note that if you have already set up Proguard previously, you might be able to skip this step.
android {
compileSdkVersion 29
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
// Android configurations are usually here
}
// Signing Configurations are usually here
buildTypes {
release {
signingConfig signingConfigs.debug
// add these code lines
minifyEnabled true
useProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
If you do not require code obfuscation or minification in your Release APK, you can simply disable this feature altogether for the Android code. The required steps are mentioned below.
Open up your Flutter Project in your preferred IDE
Open the “build.gradle” file in the “/android/app” folder.
Find the “android” block, within it locate the “buildTypes” and “release” blocks.
Add the following mentioned code to disable code modification.
android {
compileSdkVersion 29
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
// Android configurations are usually here
}
// Signing Configurations are usually here
buildTypes {
release {
signingConfig signingConfigs.debug
// add these code lines
minifyEnabled false
shrinkResources false
}
}
}
Perform a Flutter clean task and build your Release APK. Your issue should be resolved now.
Happy coding :D
Upvotes: 2