Now I'm developing IOS App and I want to check if the Viber App is existing in the Phone or not.
I already use Viber:\\ URL scheme and https://ionicframework.com/docs/native/app-availability/ to check the app but the app is not detecting
There's any possible implementation?
Thanks
Try this;
import { AppAvailability } from '#ionic-native/app-availability';
import { Platform } from 'ionic-angular';
constructor(private appAvailability: AppAvailability, private platform: Platform) { }
let app;
if (this.platform.is('ios')) {
app = 'Viber://';
} else if (this.platform.is('android')) {
app = 'com.viber.voip ';
}
this.appAvailability.check(app)
.then(
(yes: boolean) => console.log(app + ' is available'),
(no: boolean) => console.log(app + ' is NOT available')
);
the URLScheme must be declared publicly in Info.plist file first
visit this UseYourLoaf tutorial for more details
i fixed it by check if these is exist
viber = "https://itunes.apple.com/ph/app/viber-messenger-chats-calls/id382617920?mt=8"
and
use app-availability
this.appAvailability.check(viber)
Related
What is the best way of implementing the Apple App Transparency Tracker (ATT) feature on react native expo? My app keeps getting rejected by apple even after I add:
app.json file :
"infoPlist": {
"NSUserTrackingUsageDescription": "App requires permission...."
}
On iOS 14 Apple introduced the App Tracking Transparency permission to access IDFA.
You need to prompt the user whether it allows your app to use libraries that track them or not, adding it on infoPlist just allows you to use this API within your application.
Expo doesn't have this feature yet, but some libraries you can use to prompt the permission
Example: https://docs.expo.io/versions/v41.0.0/sdk/facebook/#facebookgetpermissionsasync
You can use other libraries , such as https://github.com/mrousavy/react-native-tracking-transparency
where you can request the App tracking like
import { getTrackingStatus } from 'react-native-tracking-transparency';
const trackingStatus = await getTrackingStatus();
if (trackingStatus === 'authorized' || trackingStatus === 'unavailable') {
// enable tracking features
}
import { requestTrackingPermission } from 'react-native-tracking-transparency';
const trackingStatus = await requestTrackingPermission();
if (trackingStatus === 'authorized' || trackingStatus === 'unavailable') {
// enable tracking features
}
This might need an update in a near future, as expo releases a new SDK version with a solution for that.
EDIT
From Expo 44+
Expo now have a library for TrackTransparency: (https://docs.expo.dev/versions/latest/sdk/tracking-transparency/)
expo install expo-tracking-transparency
For bare applications: https://github.com/expo/expo/tree/main/packages/expo-tracking-transparency#installation-in-bare-react-native-projects
You can add it as a plugin at your app.json
{
"expo": {
"plugins": [
[
"expo-tracking-transparency",
{
"userTrackingPermission": "This identifier will be used to deliver personalized ads to you."
}
]
]
}
}
And now you can use like this:
import React, { useEffect } from 'react';
import { Text, StyleSheet, View } from 'react-native';
import { requestTrackingPermissionsAsync } from 'expo-tracking-transparency';
export default function App() {
useEffect(() => {
(async () => {
const { status } = await requestTrackingPermissionsAsync();
if (status === 'granted') {
console.log('Yay! I have user permission to track data');
}
})();
}, []);
return (
<View style={styles.container}>
<Text>Tracking Transparency Module Example</Text>
</View>
);
}
You need to request Tracking permissions first (I used react-native-permissions):
import { request, RESULTS, PERMISSIONS } from 'react-native-permissions'
export const requestPermissionTransparency = async () => {
return await request(PERMISSIONS.IOS.APP_TRACKING_TRANSPARENCY)
}
useEffect(() => {
;(async () => {
const result = await requestPermissionTransparency()
if (result === RESULTS.GRANTED) {
//You need to enable analytics (fb,google,etc...)
await firebase.analytics().setAnalyticsCollectionEnabled(true)
console.log('Firebase Analytics: ENABLED')
}
})()
}, [])
Remember to add this file in the root project:
// <project-root>/firebase.json
{
"react-native": {
"analytics_auto_collection_enabled": false
}
}
References: https://rnfirebase.io/analytics/usage
The solution I ended up using from expo was using the Facebook.getPermissionsAsync()
https://expo.canny.io/feature-requests/p/expo-permissions-add-support-to-apptrackingtransparency-permission-on-ios
Expo 41+
TrackingTransparency:
https://docs.expo.io/versions/latest/sdk/tracking-transparency/
import { requestTrackingPermissionsAsync } from 'expo-tracking-transparency';
const { status } = await requestTrackingPermissionsAsync();
if (status === 'granted') // do something
Expo 40 and below
Admob: https://docs.expo.io/versions/latest/sdk/admob/
import { requestPermissionsAsync } from 'expo-ads-admob'
const { status } = await requestPermissionsAsync()
if (status === 'granted') // do something
Our Flutter App shows a number of locations using Google Maps, if available, or else using the local browser.
Although we had already previously uploaded a binary code for iOS which was accepted by Apple and successfully published in the App Store, now that we have added some more locations and thus attempted to publish a new version, Apple has rejected our binary, stating that it is mandatory to use "Apple Maps" instead of anything that starts with a "G", like Google...
The rejection message reads as follows:
Your app's location feature is not integrated with the built-in mapping functionality, which limits users to a third-party maps app.
Next Steps
To resolve this issue, please revise your app to give users the option to launch the native Apple Maps app.
I have found that there exists some documentation about a Javascript library named MapKit JS, which serves precisely the purpose of interacting with Apple Maps: https://developer.apple.com/maps/mapkitjs/
<script src="https://cdn.apple-mapkit.com/mk/5.x.x/mapkit.js"></script>
<script>
mapkit.init({
authorizationCallback: function(done) {
var xhr = new XMLHttpRequest();
xhr.open("GET", "/services/jwt");
xhr.addEventListener("load", function() {
done(this.responseText);
});
xhr.send();
}
});
var Cupertino = new mapkit.CoordinateRegion(
new mapkit.Coordinate(37.3316850890998, -122.030067374026),
new mapkit.CoordinateSpan(0.167647972, 0.354985255)
);
var map = new mapkit.Map("map");
map.region = Cupertino;
</script>
Nevertheless, I could really use some help no how to connect with this MapKit JS using DART, instead of JAVA, for our Flutter application.
Thank you immensely for your kind help!
Daniel
Firstly, install the url_launcher plugin
Secondly, add the below code in Info.plist:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>googlechromes</string>
<string>comgooglemaps</string>
</array>
Thirdly:
var urlAppleMaps = 'https://maps.apple.com/?q=$lat,$lng';
if (await canLaunch(urlAppleMaps)) {
await launch(urlAppleMaps);
} else {
throw 'Could not launch $url';
}
We can use it like this:
_launchMap(BuildContext context, lat, lng) async {
var url = '';
var urlAppleMaps = '';
if (Platform.isAndroid) {
url = "https://www.google.com/maps/search/?api=1&query=${lat},${lng}";
} else {
urlAppleMaps = 'https://maps.apple.com/?q=$lat,$lng';
url = "comgooglemaps://?saddr=&daddr=$lat,$lng&directionsmode=driving";
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
if (await canLaunch(url)) {
await launch(url);
} else if (await canLaunch(urlAppleMaps)) {
await launch(urlAppleMaps);
} else {
throw 'Could not launch $url';
}
}
You could try to use a Map Launcher plugin to launch apple/google maps depending on a platform
import 'dart:io';
import 'package:map_launcher/map_launcher.dart';
if (Platform.isIOS) {
await MapLauncher.launchMap(
mapType: MapType.apple,
coords: Coords(31.233568, 121.505504),
title: "Shanghai Tower",
description: "Asia's tallest building",
);
} else {
await MapLauncher.launchMap(
mapType: MapType.google,
coords: Coords(31.233568, 121.505504),
title: "Shanghai Tower",
description: "Asia's tallest building",
);
}
Just an idea but maybe you can try to use the url_launch plugin to launch a url following the schemata given in the apple maps url schemata given here: https://developer.apple.com/library/archive/featuredarticles/iPhoneURLScheme_Reference/MapLinks/MapLinks.html#//apple_ref/doc/uid/TP40007899-CH5-SW1
A simple solution I have found is to replace the google maps URL with a maps.apple.com equivalent, using the same url_launcher function.
For example, the original function for Google Maps:
void _mapaBethania() async {
const url = "https://www.google.com/maps/place/Panamanian+Institute+for+Special+Training/#9.0067418,-79.5300556,17z/data=!3m1!4b1!4m5!3m4!1s0x8faca84549395297:0x9c54b1fdb96ac590!8m2!3d9.0067365!4d-79.5278669";
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Lo sentimos, no es posible abrir: $url';
}
}
Has become:
void _mapaBethania() async {
const url = "https://maps.apple.com/?q=IPHE&ll=9.0067418,-79.5300556&z=16";
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Lo sentimos, no es posible abrir: $url';
}
}
Nevertheless, although this change does fulfill Apple's enforced obligation to use their own software instead of the competition's, the user experience with Apple Maps is very poor, because once the Map App is shown, it becomes a bit confusing and difficult to return back to the original App.
Therefore, I am planning to write code that enables both options, Apple Maps in order to comply with Apple enforcement, and also Google Maps in order to provide a better user experience, despite Apple.
Anyway, the latter is just a personal opinion; the true fact is that replacing the URL for a maps.apple.com equivalent using the same launch_url function, does seem acceptable to comply with Apple requirements.
I use Ionic 3 on one of my projects with an authentication system. I use native storage when the user wants to connect. It works on Android but on iOS, it redirects me to the login screen even using platform.ready (). I saw that several people were a similar problem but no answer, so I wanted to know if someone was facing the same problem and if he found a solution. Here is my code:
this.plt.ready().then(() => {
this.nativeStorage.setItem('userStorage', { stayConnected: (typeof this.stayConnected == "undefined" || this.stayConnected == false ? '' : 'stayConnected'), userId: (result as any).id, userLogin: (result as any).login })
.then(
() => {
this.loader.dismiss();
this.navCtrl.setRoot(HomePage);
},
error => {
this.loader.dismiss();
this.presentToast(this.languageLogin.error, 3000, "bottom");
}
)
},
error => {
this.loader.dismiss();
this.presentToast(this.languageLogin.error, 3000, "bottom");
});
thank you for your answers.
I would put 2 function storeUser() and getUser() into the same provider UserService like belows
Then add UserService to the constructor of any pages required.
It works for both IOS, Android and web
import {Storage} from '#ionic/storage';
import {Observable} from 'rxjs/Observable';
#Injectable()
export class UserService {
constructor(private storage: Storage){}
public storeUser(userData): void {
this.storage.set('userData', userData);
}
public getUser(): Observable<any>
return Observable.fromPromise(this.storage.get('userData').then((val) => {
return !!val;
}));
}
Yes, I have faced issues while using ionic native storage plugins. So I turned to javascript Window localStorage Property and it's working completely fine.
Syntax for SAVING data to localStorage:
localStorage.setItem("key", "success");
Syntax for READING data from localStorage:
var lastname = localStorage.getItem("key");
Syntax for REMOVING data from localStorage:
localStorage.removeItem("key");
and now you can write your code with this property, like this -
if (lastname == "success"){
this.navCtrl.setRoot(HomePage);
} else{
alert("Not matched")
}
You are inside a platform.ready(), which is good. The storage package also has a .ready() that you may want to leverage, which specifically checks if storage itself is ready. If this runs at startup there is a decent chance storage is initializing.
Also, this starts to get into some crazy promise chaining messiness. I'd suggest diving into async/await. Something like the (untested) code below.
try{
await this.plt.ready();
await this.nativeStorage.ready();
let stayConnectedValue = (this.stayConnected) ? 'stayConnected' : '';
await this.nativeStorage.setItem('userStorage', { stayConnected: stayConnectedValue , userId: (result as any).id, userLogin: (result as any).login });
this.navCtrl.setRoot(HomePage);
}
catch(err){
this.presentToast(this.languageLogin.error, 3000, "bottom");
}
finally{
this.loader.dismiss();
}
This question already has answers here:
Publishing issue, Callkit is included even we are not using it
(2 answers)
Closed 5 years ago.
I have an app which enables an user to make phone call to a certain number. I am doing following:-
private void CallContact(string phone)
{
phone = phone.Replace(" ", "");
var callURL = new NSUrl("tel:" + phone);
try
{
if (UIApplication.SharedApplication.CanOpenUrl(callURL))
{
UIApplication.SharedApplication.OpenUrl(callURL);
}
else
{
var av = new UIAlertView("Not supported",
"Calling is not supported on this device",
null,
"OK",
null);
av.Show();
}
}
catch (Exception ex)
{
return;
}
}
This works fine. But when I tried publishing the app, my app got rejected and the Apple team asked me the following:-
We noticed that your app has CallKit and CallKit Blocker enabled:
⁃Which features of your app require CallKit and CallKit Blocker functionality?
⁃Where, specifically, in the app would users access these features?
I am not using the CallKit functionality anywhere in my app. I searched SO and found that it is shipped with the Xamarin.iOS.dll . It is possible that the way I am making calls in my app uses the CallKit?
Sorry for bein a noob :)
try this solution
partial void BtnContactBillingCall_TouchUpInside (UIButton sender)
{
var confirm = new UIAlertView("","Call "+ mobilenumber + " ?",null,"Cancel","Call");
confirm.Show();
confirm.Clicked += (object senderConfirm, UIButtonEventArgs e) =>
{
if(e.ButtonIndex ==0)
{
}
else
{
var url = new Foundation.NSUrl("tel:"+mBillingPhoneNumber);
UIApplication.SharedApplication.OpenUrl(url);
}
};
}
Is there an example how to program the functionality with the Phonegap Framework to share a URL to email, twitter and Facebook? For Example in Android this functionality is in 90% of the apps. In Iphone it is in any Apps. In the app of techcrunch for Iphone you can see it, when You open an article. Is it possible to create this with Phonegap too?
You can do this in Android with the following code for a plugin. I haven't published this anywhere else yet, but eventually I hope to add it as a plugin in the phonegap plugin repository for Android.
JAVASCRIPT:
var Share = function() {};
Share.prototype.show = function(content) {
return PhoneGap.exec(
function(args) {
console.log("phonegap share plugin - success!")
}, function(args) {
console.log("phonegap share plugin - failed")
}, 'Share', '', content);
};
PhoneGap.addConstructor(function() {
PhoneGap.addPlugin('share', new Share());
PluginManager.addService("Share","com.COMPANYNAME(CHANGEME).android.plugins.Share");
});
JAVA IN ANDROID:
package com.COMPANYNAME(CHANGEME).android.plugins;
import org.json.JSONArray;
import org.json.JSONException;
import android.content.Intent;
import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;
public class Share extends Plugin {
private String callback;
#Override
public PluginResult execute(String action, JSONArray args, String callbackId) {
PluginResult mPlugin = null;
try {
mPlugin = activateSharing(args.getString(0), args.getString(1));
} catch (JSONException e) {
Log.e("JSON Exception", e.toString());
}
mPlugin.setKeepCallback(true);
this.callback = callbackId;
return mPlugin;
}
private PluginResult activateSharing(String title, String body) {
final Intent shareIntent = new Intent(
android.content.Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, title);
shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, body);
shareIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ctx.startActivity(Intent.createChooser(shareIntent, "Share"));
return new PluginResult(PluginResult.Status.OK);
}
}
Almost three years later: Here's a plugin that allows sharing on Android and iOS with the same API. https://github.com/EddyVerbruggen/SocialSharing-PhoneGap-Plugin
It's available on PhoneGap Build as well!
Example
window.plugins.socialsharing.share('Google is awesome, WOOT!', 'Google facts', 'https://www.google.com/images/srpr/logo11w.png', 'http://www.google.com');
Login Facebook and post feed, login twitter and post status using plugin appInBrowser:
https://github.com/raulduran/facebook-twitter-cordova.git