My app currently asks for permissions when users open activities, I would like to have those permissions on app first load.
Example
One of my components (activity) needs callNumber permission and asking for this permission won't be popup until user opens that component, I would like to have that permission popup when user install the app for first time instead of when user goes to that specific activity.
Code
MyComponent.ts (my custom component activity that calling happen in that page)
import { CallNumber } from '#ionic-native/call-number/ngx';
constructor(
private callNumber: CallNumber,
) {...}
callEmergencies(event: any) {
this.callNumber.callNumber(event, true)
.then(res => {
Toast.show({
text: 'Calling ' + res + ' ...'
});
})
.catch(err => {
Toast.show({
text: 'something went wrong.'
});
});
}
App.module.ts (main module)
import { CallNumber } from '#ionic-native/call-number/ngx';
providers: [
CallNumber,
],
app.component.ts (Main component)
Has nothing about CallNumber plugin.
Question
How can I achieve that logic (asking permissions on first launch instead of in each activity)?
This is not possible or preferable. The new permissions paradigm is to request permissions when needed ('in context'). This way, the user should be in no doubt as to why you are requesting permission.
From the Android documentation:
Ask for permissions in context, when the user starts to interact with the feature that requires it.
iOS shares this idea:
Request personal data only when your app clearly needs it.
Related
I'm trying to access my react-native app's specific permissions in Android. I can access and pull up my app's info page in Android, but I can't go directly into the permissions screen from my app.
I am using react-native-android-open-settings to to achieve this. By using this I am able to access the app's info page, but can't access the specific permissions page for the app without the user having to click on permissions in App Info. The library can be found here: https://www.npmjs.com/package/react-native-android-open-settings
import AndroidOpenSettings from 'react-native-android-open-settings'
async goToSettings() {
if(Platform.OS === 'android') {
AndroidOpenSettings.appDetailsSettings()
} else {
Linking.canOpenURL('app-settings:').then(supported => {
if (!supported) {
console.log('Can\'t handle settings url');
} else {
return Linking.openURL('app-settings:');
}
}).catch(err => console.error('An error occurred', err));
}
}
The expected result is for it to open the permissions page and not the app info page.
We've got a managed expo app, which is using the FileSystem.downloadAsync and this is all okay.
We've got a FlatList which is displaying a list of downloaded files.
We don't want to build in a file viewer, for every app under the sun, that's not the aim.
We want to be able to click a file from the list and potentially using the Android Intent system to offer the user a list of apps they already have installed which can handle the file type.
e.g. We've got something like
class FileBrowser extends Component {
state = {
files: [
{
key: '1'
name: 'file.jpg',
sys_path: 'file://blah.jpg'
}
]
}
openFile(item) {
IntentLauncherAndroid.startActivityAsync(
'android.intent.action.OPEN_DOCUMENT', {
data: item.sys_path
})
}
render() {
return (
<FlatList data={ this.state.files } renderItem={ (item) => <Button title={ item.name } onPress={ this.openFile(item) } />} />
)
}
}
We've pretty much exhausted the list of intents from https://chromium.googlesource.com/android_tools/+/febed84a3a3cb7c2cb80d580d79c31e22e9643a5/sdk/platforms/android-23/data/activity_actions.txt
The only one that almost gets there is android.intent.action.VIEW however that just opens a random list of apps, none of which can handle images - We've also passed in the mime type e.g. image/jpeg or image/* hoping that will filter the list.
What would be the correct way on Android only to offer the user to open the file in an appropriate apps?
with Expo SDK 34 (I use expo 34.0.3 because of there is font not resolve issues), you can do the open list as this way. but this is not a proper solution to open list. because the user has to do some work like this.
expo sharing api
await Sharing.shareAsync(
fileUri,
{dialogTitle: 'share or copy your pdf via'}
).catch(error =>{
console.log(error);
})
if you do this with providing a local file URI, you can see this bottom action sheet as below. then the user can choose the copy to option and paste it some location. after that user can open the file and then OS ask for what app will be used to open your file.
I'd like for users to be able to share a link (e.g. app.com/SKFLA - this is primarily because deep links on their own aren't clickable) via Facebook etc. When clicked, this redirects to a deep link app://SKFLA. If the app is installed, this opens the app - this is all working fine so far. But if the app isn't installed, I'd like to open the app store on the relevant page. Is this achievable? Thanks!
You need UNIVERSAL LINKS
Please check
IOS https://developer.apple.com/library/archive/documentation/General/Conceptual/AppSearch/UniversalLinks.html
Android
https://developer.android.com/training/app-links/
It might also require some extra server-side setup.
Not sure about native behavior.
We used third-party service like https://branch.io/deepviews/.
There is a bunch of similar services.
If someone is still stuck in this issue and needs easiest solution, you will love node-deeplink
1.) If app is installed: Calling an app through deep linking will always call componentDidMount of root component. So you can attach a listener there. Like:
Linking.getInitialURL()
.then(url => {
if (url) {
this.handleOpenURL({ url });
}
})
.catch(console.error);
Linking.addEventListener('url', this.handleOpenURL);
handleOpenURL(event) {
if (event) {
console.log('event = ', event);
const url = event.url;
const route = url.replace(/.*?:\/\//g, '');
console.log('route = ', route);
if(route.match(/\/([^\/]+)\/?$/)) {
const id = route.match(/\/([^\/]+)\/?$/)[1];
const routeName = route.split('/')[0];
if (routeName === 'privatealbum') {
Actions.privateAlbum({ albumId: id });
}
}
}
}
2.) If app is not installed: Just set up a route in your server and node-deeplink package will handle the bridging between web browser to app store when a app is not installed in your mobile.
By this, both the cases will be handled without any struggle
Per default, Dialogflow can only match one intent per one one input:
e.g
User asks: "How are you?"
Dialogflow Agent responds: "I am feeling good!"
(Matched intent: intents.howareyou)
But as soon as the user asks two questions in one input, the agent can not match multiple intents. Only one intent is matched with a smaller confidence interval)
e.g
User asks: "How are you? Do we want to go shopping?"
Dialogflow Agent responds: "Yes, lets go shopping!"
(Matched intent: intents.shopping)
There are two options now to enable the agent to answer both questions in one input:
Create an intent and let the agent response exactly for these two questions.
=> This is a very bad solution, as soon as you add more possible questions/intents. Then you would need to create every combination of every question.
Split the one input into several queries and let the agent perform the intent matching again on the splitted query.
=> This is the preferred way
Based on some blogs in the internet (e.g. https://docs.meya.ai/docs/handle-multiple-intents-in) the second option is what I did.
The Default Fallback Intent is set to use the Fulfillment webhook and this a small part of code executed:
function parseMultipleIntents (agent) {
const query = agent.query;
var pattern= /(.+?[!.?]+)/gm;
var match = pattern.exec(query);
while (match !== null) {
console.log(match[0]);
handleQuery(match[0]); //<----
match = pattern.exec(query);
}
}
The handleQuery method is the actual method, where the splitted queries are handled:
function handleQuery(query){
console.log(query);
// The path to identify the agent that owns the created intent.
const sessionPath = sessionClient.sessionPath("PROJECT_ID", "FIXED_SESSION_ID");
const request = {
session: sessionPath,
queryInput: {
text: {
text: query,
languageCode: 'de',
},
},
};
sessionClient
.detectIntent(request)
.then(responses => {
console.log('Detected intent');
const result = responses[0].queryResult;
console.log(` Query: ${result.queryText}`);
console.log(` Response: ${result.fulfillmentText}`);
if (result.intent) {
console.log(` Intent: ${result.intent.displayName}`);
} else {
console.log(` No intent matched.`);
}
})
.catch(err => {
console.error('ERROR:', err);
});
}
The problem:
If I comment everything in the handleQuery method except console.log(query); then the console outpuut in the firebase console looks fine:
originalQuery: und?warum?
11:39:58.240 PM dialogflowFirebaseFulfillment warum?
11:39:58.238 PM dialogflowFirebaseFulfillment und?
But as soon as I uncomment the rest of the handleQuery and the code looks like above, I get the following console messages which is not stopping. The messages go one if I scoll up in the console. It seems like some kind of loop:
-
-
Do I use detectIntent correctly or do you had such experiences? Or can you spot an issue?
I presumed issues with sync/async calls and also added Promises, but the same happened...
Thanks
How to open other apps (Gmail, Camera) from ReactNative. How can I pass data from current scene to other app?
I found this npm library react-native-app-link which can open other apps. This is based on deep linking, if you have any deep links then this library can help. This doesn't open apps just by giving the android package name or ios app id.
https://github.com/FiberJW/react-native-app-link
you can mange opening other apps using Linking
Code sample for opening the dialer
const urlToOpen = 'tel:1234567890';
Linking.openURL(urlToOpen);
You can refer to the official doc here, it just predefines some applications, which can be opened.
However, if the question is about to open just about any application, I hope there is no solution till now.
react-native-app-link has some redundant config (e.g. appStoreLocale parameter), so I wrote my own realization using their code:
import { Alert, Platform, ToastAndroid } from 'react-native';
const isIos = Platform.OS === 'ios';
const showNotification = (text) => isIos
? Alert.alert(text)
: ToastAndroid.show(text, ToastAndroid.SHORT);
const openApp = ({ url, appStoreId, playMarketId, name }) => {
Linking.openURL(url).catch(err => {
if (err.code === 'EUNSPECIFIED') {
Linking.openURL(
isIos
? `https://apps.apple.com/app/id${appStoreId}`
: `https://play.google.com/store/apps/details?id=${playMarketId}`,
);
} else {
showNotification(`Can't open ${name} app`);
}
});
};
It tries to open the app by the specified link, and if the user doesn't have such one, it opens its page in AppStore or Play Market.