Trying to add Firebase Crashlytics to an app. Added to file android/app/build.gradle: apply plugin: 'com.google.firebase.crashlytics'. Added to the android/build.gradle file: classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1'.
Initialized:
if (!kIsWeb) {
if (kDebugMode) {
await FirebaseCrashlytics.instance
.setCrashlyticsCollectionEnabled(false);
}
FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterError;
}
In my initState created a crash():
void initState() {
super.initState();
FirebaseCrashlytics.instance.crash();
}
But nothing is output in the console:
How to set it up correctly?
If this line is getting executed, then Crashlytics won't send any crashes:
FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(false);
See this document for reference. Make sure this is not getting executed when running your tests.
Also, when testing, I would recommend you having more control when the crash happens, like using a button. Similar to this:
TextButton(
onPressed: () => throw Exception(),
child: const Text("Throw Test Exception"),
),
The Crashlytics SDK, in some scenarios, will try to upload the crash reports when restarting the app. If the crashes happen too early into the startup process, it can prevent Crashlytics from actually uploading the crash report.
In addition, this will help you avoid having too many crashes.
Related
In my project, I was using flutter 3.0.3. Once I updated to 3.0.4 and updated dependencies, suddenly when I launched the app on android, the splash screen is showing continuously(never going to the main app). I tried by moving to my previous commit, downgrading flutter but to no avail.
This happened before but I luckily fixed it by upgrading kotlin jdk to 8(was 7 before).
I am using flutter_native_splash library. But it looks it doesn't have any impact on my project.
This question talks about only release mode. But, in my case it is happening both release and debug modes. I would really appreciate your help on this!
My main function:
void mainCommon() {
WidgetsFlutterBinding.ensureInitialized();
SentryFlutter.init(
(options) => options.dsn = Config.sentryDsn,
appRunner: () async {
await Firebase.initializeApp();
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
final GlobalKey<ScaffoldMessengerState> messengerKey = GlobalKey<ScaffoldMessengerState>();
await BlocOverrides.runZoned(
() async => App(
api: Api(Config.grpcChannel),
database: await Config.db,
appDirectory: await getApplicationDocumentsDirectory(),
notificationManager: await NotificationManager.init(Config.grpcChannel),
messengerKey: messengerKey,
),
blocObserver: AppBlocObserver(errorCallback: BlocErrorHandler(messengerKey).errorCallback),
);
},
);
}
This is not for all cases. But, upgrading firebase_core and firebase_messaging could solve for some cases. In my case, it solved the problem for the first. But, once I upgraded all my other packages, it occurred again.
Android studio sucks. When I used Visual Studio Code, the exception was thrown in main where I initialised firebase. But in android, it ignored exception so I wasted a lot of time finding where the problem was.
To see the error in Android studio, you need to get mainCommon in try/catch bloc:
try {
await Firebase.initializeApp();
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
runApp(App(
api: Api(Config.grpcChannel),
database: await Config.db,
appDirectory: await getApplicationDocumentsDirectory(),
notificationManager: await NotificationManager.init(Config.grpcChannel),
));
} catch (e) {
logger.e("Got exception in mainCommon: $e");
rethrow;
}
I need to add those to Android files:
android:usesCleartextTraffic="true" and <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
But I'm using managed workflow and I don't know how to add those lines to app.json file.
I did this plugin which seems to work:
const { createRunOncePlugin, withAndroidManifest } = require('#expo/config-plugins');
const withAndroidManifestHavingBetterSecuritySettings = config => {
return withAndroidManifest(config, config => {
const androidManifest = config.modResults.manifest;
const mainApplication = androidManifest.application[0];
if(process.env.CHANNEL !== 'dev') {
androidManifest.$ = {
...androidManifest.$,
'xmlns:tools': 'http://schemas.android.com/tools',
};
mainApplication.$['tools:replace'] = 'android:usesCleartextTraffic';
mainApplication.$['android:usesCleartextTraffic'] = 'false';
}
return config;
});
};
module.exports = createRunOncePlugin(
withAndroidManifestHavingBetterSecuritySettings,
'withAndroidManifestHavingBetterSecuritySettings',
'1.0.0'
);
I had many issues related to merging of AndroidManifest files when "developmentClient": true in my eas.json file (related to me dev eas profile). I believe that it's related to the fact that the debug/AndroidManifest is a higher priority manifest than main/AndroidManifest (not sure though). So my solution was not to ignore the changes when building the dev profile. Hardening security settings in development builds do not seem useful anyhow.
So I struggled with this problem for a while now and the only solution I could come up with was setting the minimum sdk version of the android app from 21 to 28. This is not ideal as my application now does not support old android devices, but doing this defaults the usesClearTextTraffic flag to false.
If your app works fine while developing in expo, but after generating the APK some functions don't work, try this. In my case the APK crashed on login, but building in development with expo was working fine. The problem was that traffic is encrypted so that's why I ended up here trying to set clear text traffic. The problem in my case was with expoPushToken, in the APK it throws an exception I wasn't catching (building with expo worked fine as I said before, no exception). So, if the exception happens just catch it and set the token to empty string.
So, I had this:
import * as Notifications from "expo-notifications";
export async function getDevicePushTokenForAPP() {
const pushToken = await Notifications.getExpoPushTokenAsync();
return pushToken.data;
}
So then, I added the try and catch:
export async function getDevicePushTokenForAPP() {
try {
const pushToken = await Notifications.getExpoPushTokenAsync();
return pushToken.data;
} catch (e) {
return "";
}
}
Now if you build the APK again (expo build:android) it should work fine, in my case login worked. But please note this is for testing purposes only, I needed the APK to quickly show it to the client. (Note that you will need the bundle, not the apk, when uploading to the Playstore). This is a quick fix for you to test the APK; but with no token, push notifications won't work. The final fix is to add firebase to your project, it's mandatory now, so add firebase and with the firebase unique ID, your push notification will work in your APK.
My conclusion is that expo uses its own ID to communicate with firebase, that's why it works while developing but the APK doesn't go through expo and tries to connect to firebase directly, but crashes because there's no ID.
You should update your app.json like that:
"android": {
"usesCleartextTraffic": true,
uses-permission android:name
},
I am using react-native to build an android app while authentication is done using firebase. I am using the following libraries :
#react-native-firebase/app
#react-native-firebase/auth
The authentication is working perfectly fine for signInWithEmailAndPassword() but not with the phone no :
The below is the function :
signInWithPhoneNumber = () => {
auth().signInWithPhoneNumber('+91 1234 567 890')
.then(confirmationResult => {
this.setState({
confirm: confirmationResult
})
})
.catch(function (error) {
console.error(error);
});
}
It's not going into the .then() and my screen for the emulator is getting stuck with blank black screen.
UPDATE (May 20, 2021)
Seems line the issue is fixed in the latest version.
This is a known issue in the firebase phone auth sdk.
Ref: https://github.com/firebase/firebase-android-sdk/issues/2164
Until Google fixes it, add the following line in your build.gradle
implementation "androidx.browser:browser:1.2.0"
I am trying to launch a url in my flutter application. What i'm trying to do is very simple and it works in all other projects except for this one! The browser should be launched on an inkwell onTap event. I tried the exact same code in other projects and worked. I also tried to create a new flutter project and the code worked.
The app does not crash and i don't get any error but on Debug i get a missing plugin exception.
I tried flutter clean and flutter run but didn't work! I tried invalidating cache and restart but also didn't work! I tried removing and re installing the plugin but also didn't work!
Here's the code:
_launchMapsUrl() async {
final url = 'https://www.google.com';
if (await canLaunch(url)) {
await launch(url);
} else {
print('Could not launch $url');
}
}
the onTap:
onTap: () {
_launchMapsUrl();
},
The Compiled and Target SDK versions are 29 and the version of the launcher in my pubspec.yaml is url_launcher: ^5.7.10
For the record the other projects that the code worked in are of the same versions
I think it has something to do with caching issue i'm not really sure, i'm very new to flutter.
Can you please recommend a solution.
I'm trying to add In App Purchases (or as Google likes to call it; "In App Billing") to my React Native App.
What I've done:
Created a product in Google Play Console (with identifier "unlock_premium"
yarn add react-native-iap (this library)
Added the code below to a component in my app
Tested both with react-native run-android on a physical device, and through publishing it to an Alpha test from Google Play Console
Notes: The app is signed and billing permissions are enabled in the manifest file, and the version of react-native-iap is 0.3.23.
The issue:
When running a debug build the console.log() just prints that the product is undefined, and the productInfo does not display on screen when running the Alpha deployed version (so the product was also undefined there). The products variable is just an empty array.
(The try-statement seems to succeed since I see no errors printed from it.)
import InAppPurchase from "react-native-iap";
const itemSKUs = Platform.select({
android: [
"com.kimer.unlock_premium" // I've also tried just "unlock_premium"
]
})
...
constructor(props) {
super(props);
this.state = {
modalVisible: false,
premiumProduct: undefined
};
}
...
async componentDidMount() {
try {
await InAppPurchase.prepare();
const products = await InAppPurchase.getProducts(itemSKUs);
console.log("finished call to get products");
console.log(products[0]);
this.setState({premiumProduct: products[0]});
} catch (err) {
console.warn(err);
}
}
...
render() {
let productInfo;
if (this.state.premiumProduct !== undefined) {
productInfo = (
<Text>{this.state.premiumProduct}
{this.state.premiumProduct.localizedPrice}
{this.state.premiumProduct.currency} {this.state.premiumProduct.productID}
{this.state.premiumProduct.title}
{this.state.premiumProduct.description}</Text>
);
}
return (
<View>
...
{productInfo}
...
</View>
);
}
SOLVED:
It is now working for me 😄! I tried a couple of things but I'm not sure what was key to getting it to work 🤔 This is anyways what I did:
Reinstalled the package
Changed my import statement from import InAppPurchase from "react-native-iap;" to "import * as InAppPurchase from 'react-native-iap';"
Changed my SKU in the code from "com.kimer.unlock_premium" to "unlock_premium"