I am using notifee to create notifications in a react native app. I noticed, by default notifications get blocked by android (See under Settings->Apps->My App). Do I have to set the permission somewhere in my app?
When I enable notifications in the Apps-Settings, they work fine, but I'd like them to be enabled when installing the apk.
Yes, You have to explicitly request notifications permission if you targets Android 13.
Paste the following line in AndroidManifest.xml:
<uses-permission android:name="android.permission.POST_NOTIFICATION"/>
And then in your app:
import { PermissionsAndroid } from 'react-native'
const requestNotificationPermission = async () => {
try {
await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.POST_NOTIFICATION
)
} catch (err) {
if (_DEV_) console.warn('requestNotificationPermission error: ', err)
}
}
Permission could be named "POST_NOTIFICATION" or "POST_NOTIFICATIONS", depending on your RN version.
Related
I need to install downloaded .apk file from within the Expo app (it's for update functionality). This is my code:
import React from "react";
import { Button, View } from "react-native";
import * as FileSystem from "expo-file-system";
import { startActivityAsync } from "expo-intent-launcher";
export function Updater() {
async function updateApk() {
const uri = "https://expo.dev/artifacts/eas/my_apk_name.apk";
const localUri = FileSystem.documentDirectory + "test.apk";
try {
await FileSystem.downloadAsync(uri, localUri);
await startActivityAsync("android.intent.action.INSTALL_PACKAGE", {
data: localUri,
flags: 1,
});
} catch (error) {
alert(`Error during installing APK: ${error}`);
}
}
return (
<View>
<Button title="Reset APK" onPress={updateApk} />
</View>
);
}
It downloads the file, stores it, but then there is an error during startActivityAsync:
Encountered an exception while calling native method:
Exception occurred while executing exported method startActivity on module ExpoIntentLauncher:
file://data/user/0/com.my.app.id/files/test.apk exposed beyond app through Intent.getData()
I tried passing uri first to FileSystem.getContentUriAsync() but then there is no error, the intent result is 0 but nothing happens.
My permissions in app.json:
"permissions": [
"READ_EXTERNAL_STORAGE",
"WRITE_EXTERNAL_STORAGE",
"CAMERA"
]
Do I need any additional permissions to get it to work? Or is it completely impossible with Expo? Maybe I should save the file to different location to be able to use this intent?
I also tried android.intent.action.VIEW with no luck.
I test it on Android 13, on physical device. App is built with EAS.
Maybe you can use this command to build release build.
expo:build android
For that you have to signup in Expo's website.
After that you can get apk in Expo's server.
I finally got it to work. The funny part is that I got the answer from the AI that is now banned here. But I just tested this solution on a real android device and it works. Anyway there are two changes needed:
REQUEST_INSTALL_PACKAGES must be added to app.json file.
Uri for intent must be a content uri so: localUri = await FileSystem.getContentUriAsync(localUri)
I am out of ideas right now why my app does not pass app check verifications. I am building a React-Native app with Firebase using react-native-firebase. It throws this error:
[firestore/permission-denied]
I have installed the app-check package for react native. I have added these lines to app/build.gradle:
implementation 'com.google.firebase:firebase-appcheck-safetynet'
implementation 'com.google.firebase:firebase-appcheck-debug'
I have enabled App Check in Firebase console and added the SHA-256 certificate fingerprint to it.
I have added this flag to firebase.json:
"automaticResourceManagement": true,
and finally, the initialization of the app check in index.js:
import { firebase } from '#react-native-firebase/app-check';
try {
firebase.appCheck().setTokenAutoRefreshEnabled(true);
firebase.appCheck().activate('ignored', true);
const appchecktoken = firebase.appCheck().getToken(true);
console.log("app check success, appchecktoken: " + JSON.stringify(appchecktoken));
} catch (e) {
console.log("Failed to initialize appCheck:", e);
}
When I print the appchecktoken it seems empty:
{"_U":0,"_V":0,"_W":null,"_X":null}
What am I missing here? Please remember that I am using the react-native-firebase package and not the native packages.
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 making a simple application in expo react native to scan and connect to devices via bluetooth, the problem is the errors that it throws at me.
I am using the following library: https://github.com/dotintent/react-native-ble-plx
In android I get this error:
In IOS:
Part of my code:
import { BleManager } from 'react-native-ble-plx';
const manager = new BleManager();
useEffect(()=>{
manager.startDeviceScan(UUIDs, null, (error, device) => {
console.log("Scanning...");
if (error) {
console.log(error);
return;
}
console.log(device.name)
});
}, [manager])
Sorry for the late reply but it seems that expo does not support Bluetooth
EDIT:
https://expo.canny.io/feature-requests/p/bluetooth-1
You can use Expo with react-native-ble-plx
I installed the Contacts plugin for Ionic 2 as explained in this documentation:
https://ionicframework.com/docs/v2/native/contacts/
The reference don't give us any explanation on how to use the plugin and no example of how to find and handle errors.
In an emulator my app works just fine. It lists all the contacts. But in real device it gives me an empty error and no contact is written to the list.
Contacts.find(['phoneNumbers']).then((phone_contacts) => {
self.contacts = {};
// Some code
}).catch((error) => {
alert('Contacts error: '+JSON.stringify(error));
});
The error object is empty and alert prints {}.
I installed the app by two different ways:
1- sudo ionic run android
2- copying the android-debug.apk to downloads folder and install it via package manager. I granted the requested permissions.
These two lines are in my Manifest.xml
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="24" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
Anyone got a clue on how I can debug it? Or what could be this error?
#edit
It's a Android 4.4.2, KitKat
#edit 2
I put the code in my home.ts, in constructor, in the ready event.
platform.ready().then(() => {
});
I have a similar error, in the console.log show this message:
EXCEPTION: Uncaught (in promise): TypeError: navigator.contacts is undefined
Contacts
This is my code:
import { Component } from '#angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar, Splashscreen } from 'ionic-native';
import { Contacts } from 'ionic-native';
import { HomePage } from '../pages/home/home';
#Component({
templateUrl: 'app.html'
})
export class MyApp {
rootPage = HomePage;
constructor(platform: Platform) {
platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
StatusBar.styleDefault();
Splashscreen.hide();
Contacts.find(['displayName','name','nickname'], {filter:''})
.then(
cont=>{
console.log(cont[0]);
alert(JSON.stringify(cont[0]));
})
});
}
}