So I have successfully gotten Geolocation permission working for Android 6.0 and later but I can't get it to work for Android 4.4.4.
I keep getting these errors in the console
dalvikvm: Could not find method android.content.res.TypedArray.getChangingConfigurations, referenced from method android.support.v7.internal.widget.TintTypedArray.getChangingConfigurations
[DEBUG] : dalvikvm: VFY: replacing opcode 0x6e at 0x0002
[INFO] : dalvikvm: Could not find method android.content.res.TypedArray.getType, referenced from method android.support.v7.internal.widget.TintTypedArray.getType
This is coming from this
var hasLocationPermissions = Ti.Geolocation.hasLocationPermissions(Ti.Geolocation.AUTHORIZATION_ALWAYS);
Now I added the following permissions in the TiApp.xml
<android xmlns:android="http://schemas.android.com/apk/res/android">
<manifest>
<application android:theme="#style/Theme.NoActionBar"/>
<!-- Camera Permissions -->
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
</manifest>
</android>
Still no luck. Here is the code I use to do this. I even tried to circumvent the by checking the version
Ti.Geolocation.accuracy = Ti.Geolocation.ACCURACY_HIGH;
Titanium.Geolocation.purpose = 'Get Current Location to search local Items';
var hasLocationPermissions = Ti.Geolocation.hasLocationPermissions(Ti.Geolocation.AUTHORIZATION_ALWAYS);
if (Titanium.Platform.model != "Simulator"){
Ti.API.info("ANDROID VERSION:"+Ti.Platform.version);
if(Alloy.Globals.versionCompare(Ti.Platform.version, "6.0") == -1){
getCurrentPosition();
} else
{
if(hasLocationPermissions == true){
getCurrentPosition();
} else {
var win = Alloy.createController('locationPermission', {callback: function(e){
Ti.Geolocation.requestLocationPermissions(Ti.Geolocation.AUTHORIZATION_ALWAYS, function(e) {
if (e.success) {
getCurrentPosition();
} else {
Alloy.Globals.createAlertDialog('There seem to be issues with determining your location.\Please enable Location Services in your Settings to use Fluid');
}
});
}}).getView();
win.open();
}
}
} else {
Ti.API.info("LOCATION FOR SIMULATOR SET TO GALVANIZE - 1644 PLATTE DENVER");
Alloy.Globals.currentLocation = {attributes:{coordinates:{"lat": 39.757885, "lng": -105.0082375}}};//Galvanize
if(successCallback) successCallback();
}
Has anyone solved this? I am on 5.2.0 GA
In my experience android versions prior to 6, or SDK versions below 23, continue to ask for all permissions at install. So this new request for permission when a feature is used is only needed for android 6 and above, or SDK 23 and above. My 5.3GA apps ask for permissions on marshmallow when say the location is requested, but phones with versions <6 ask for permissions at install as usual. My code doesn't have any conditional logic based on android version.
Related
I am trying to use the Google authentication method (One tap sign in) for my application. However, after I clicked on the sign button, I faced the following problems:
W/GoogleApiManager: com.google.android.gms.internal.auth-api.zbaz could not execute call because it requires feature (auth_api_credentials_begin_sign_in, 6).
D/btn click: Missing Feature{name=auth_api_credentials_begin_sign_in, version=6}.
May I know where have I messed up?
I am using MsSQL instead of firebase.
I have created the OAuth 2.0 client.
I am using the Web Client ID for the BuildConfig (I have both Web Client and Android)
buildConfigField : ("String", "CLIENT_ID", '"1113838514547 -neqok16gfh5b77v6hcg33c03d0khs896.apps.googleusercontent.com"')
The google Sign in button was not working with viewBinding so I swapped to "findViewById" for that particular button
Below are the codes:
import android.content.IntentSender
import android.os.Bundle
import android.util.Log
import androidx.activity.result.IntentSenderRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import com.example.myapplication.databinding.ActivitySignInBinding
import com.google.android.gms.auth.api.identity.BeginSignInRequest
import com.google.android.gms.auth.api.identity.Identity
import com.google.android.gms.auth.api.identity.SignInClient
import com.google.android.gms.common.SignInButton
import com.google.android.gms.common.api.ApiException
import com.google.android.gms.common.api.CommonStatusCodes
import com.google.android.material.snackbar.Snackbar
class MainLoginActivity : AppCompatActivity() {
private var _binding: ActivitySignInBinding? = null
private val binding get() = _binding!!
private var sign_in_button : SignInButton? = null
private var oneTapClient: SignInClient? = null
private var signUpRequest: BeginSignInRequest? = null
private var signInRequest: BeginSignInRequest? = null
private val oneTapResult = registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()){ result ->
try {
val credential = oneTapClient?.getSignInCredentialFromIntent(result.data)
val idToken = credential?.googleIdToken
when {
idToken != null -> {
// Got an ID token from Google. Use it to authenticate
// with your backend.
val msg = "idToken: $idToken"
Snackbar.make(binding.root, msg, Snackbar.LENGTH_INDEFINITE).show()
Log.d("one tap", msg)
}
else -> {
// Shouldn't happen.
Log.d("one tap", "No ID token!")
Snackbar.make(binding.root, "No ID token!", Snackbar.LENGTH_INDEFINITE).show()
}
}
} catch (e: ApiException) {
when (e.statusCode) {
CommonStatusCodes.CANCELED -> {
Log.d("one tap", "One-tap dialog was closed.")
// Don't re-prompt the user.
Snackbar.make(binding.root, "One-tap dialog was closed.", Snackbar.LENGTH_INDEFINITE).show()
}
CommonStatusCodes.NETWORK_ERROR -> {
Log.d("one tap", "One-tap encountered a network error.")
// Try again or just ignore.
Snackbar.make(binding.root, "One-tap encountered a network error.", Snackbar.LENGTH_INDEFINITE).show()
}
else -> {
Log.d("one tap", "Couldn't get credential from result." +
" (${e.localizedMessage})")
Snackbar.make(binding.root, "Couldn't get credential from result.\" +\n" +
" (${e.localizedMessage})", Snackbar.LENGTH_INDEFINITE).show()
}
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
_binding = ActivitySignInBinding.inflate(layoutInflater)
setContentView(binding.root)
sign_in_button = findViewById(R.id.sign_in_button)
oneTapClient = Identity.getSignInClient(this)
signUpRequest = BeginSignInRequest.builder()
.setGoogleIdTokenRequestOptions(
BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
.setSupported(true)
// Your server's client ID, not your Android client ID.
.setServerClientId(BuildConfig.CLIENT_ID)
// Show all accounts on the device.
.setFilterByAuthorizedAccounts(false)
.build())
.build()
signInRequest = BeginSignInRequest.builder()
.setGoogleIdTokenRequestOptions(
BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
.setSupported(true)
// Your server's client ID, not your Android client ID.
.setServerClientId(BuildConfig.CLIENT_ID)
// Show all accounts on the device.
.setFilterByAuthorizedAccounts(true)
.build())
.setAutoSelectEnabled(true)
.build()
sign_in_button!!.setOnClickListener{
displaySignIn()
}
}
private fun displaySignIn(){
oneTapClient?.beginSignIn(signInRequest!!)
?.addOnSuccessListener(this) { result ->
try {
val ib = IntentSenderRequest.Builder(result.pendingIntent.intentSender).build()
oneTapResult.launch(ib)
} catch (e: IntentSender.SendIntentException) {
Log.e("btn click", "Couldn't start One Tap UI: ${e.localizedMessage}")
}
}
?.addOnFailureListener(this) { e ->
// No Google Accounts found. Just continue presenting the signed-out UI.
displaySignUp()
Log.d("btn click", e.localizedMessage!!)
}
}
private fun displaySignUp() {
oneTapClient?.beginSignIn(signUpRequest!!)
?.addOnSuccessListener(this) { result ->
try {
val ib = IntentSenderRequest.Builder(result.pendingIntent.intentSender).build()
oneTapResult.launch(ib)
} catch (e: IntentSender.SendIntentException) {
Log.e("btn click", "Couldn't start One Tap UI: ${e.localizedMessage}")
}
}
?.addOnFailureListener(this) { e ->
// No Google Accounts found. Just continue presenting the signed-out UI.
displaySignUp()
Log.d("btn click", e.localizedMessage!!)
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.gms.common.SignInButton
android:id="#+id/sign_in_button"
android:layout_width="129dp"
android:layout_height="52dp"
android:layout_marginStart="141dp"
android:layout_marginTop="252dp"
android:layout_marginEnd="141dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
I was banging my head against the wall for a few days on this issue and finally Alex Mamo helped me solve it. A few things could have caused this issue. First, ensure the following:
User is logged in on a Google account on the emulator.
Both SHA-1 and SHA-256 debug fingerprints are added to the correct project.
The correct google-services.json file is in the correct directory.
The web_client_id is yours and passed correctly into the required fields.
Then if nothing changed, try running the app on a real Android device. By real I mean a device that has been used by real people for some real time and not just a demo physical device conveniently sitting right next you.
If your app still produces the same error, then there are some other issues with the app that I unfortunately cannot help with.
If your app functions correctly on a real device, then it means your emulator is not set up properly. Try spinning up a new emulator and going through the new device configuration process (for me it was called "Setting Up Your Device" and it was available as an actionable notification bar button). This is a separate/different process than simply signing into a Google Account on your Android device. Once complete, wait ten minutes and reboot for good measure. This solved my issue.
Hope this helps!
I got the same error while trying to SignIn using my Android Studio emulator. The problem was a version incompatibility with some plugins.
Broken project build gradle:
id 'com.android.application' version '7.1.3' apply false
id 'com.android.library' version '7.1.3' apply false
Fix:
id 'com.android.application' version '7.1.2' apply false
id 'com.android.library' version '7.1.2' apply false
Furthermore, download again the google-services.json file. It should solve the problem.
Edit: got again the problem and I found out that it is a problem of incompatibility between the API and the version of the emulator. Installing an emulator with API 31 (instead of 32) definitely solved the problem.
In addition to the requirements mentioned by Endian Tribe in his answer, I also had to ensure the following in order to get rid of the error on my emulator:
Use a Google Play system image (Google APIs image didn't work for me).
Set a lock screen pattern or PIN.
Apply any pending system updates (did this via Settings -> Security -> Security/Google Play system update on Android 12).
Not sure if all 3 steps are required but that's what did the trick for me.
In my case I have correct firebase setup (tested before and it worked on same emulator).
Also I've done all steps with authorization in google on device, setup PIN and check for system and google play updates. Nothing changed.
To solve problem I have to manually clear data in Google app on emulator. Then auth in my app worked.
For me the error disappeared in the emulator after installing the Google Play services update as indicated in the screenshots below.
First create an emulator that supports Google Play as "Pixel_4_API_R" or "Pixel_3a_API_28" (see screenshot 1).
Then start the emulator and open the Extended Controls window. There go to "Google Play" and select "Update" (see screenshot 2).
After clicking on the Update button I had to enter a google credential on the phone emulator.
After entering the credentials and confirming a few screens the update of google play services did start automatically on one emulator and on another I had to click the update button again.
Screenshot 1
Screenshot 2
I am trying to save user credentials to Firebase Realtime Database. However, when I execute the program, the DB does not update. I have configured the Firebase setup correctly as Authentication and Storage (both Firebase) are working.
build.gradle:
dependencies {
...
// Firebase SDK setup
// Import the BoM for the Firebase platform
implementation platform('com.google.firebase:firebase-bom:28.0.1')
// Declare the dependency for the Firebase library
implementation 'com.google.firebase:firebase-storage-ktx'
implementation 'com.google.firebase:firebase-auth-ktx'
implementation 'com.google.firebase:firebase-database-ktx'
}
apply plugin: 'com.google.gms.google-services'
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package=<NAME>>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
...
</application>
</manifest>
The registration class (MWE):
class RegisterActivity : AppCompatActivity() {
var selectedPhotoUri: Uri? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Register UI
register_button_register.setOnClickListener {
performRegister()
}
}
// Register user credentials
private fun performRegister() {
val email = email_editText_register.text.toString()
val password = password_editText_register.text.toString()
// Firebase Authentication - WORKING
FirebaseAuth.getInstance().createUserWithEmailAndPassword(email, password)
.addOnCompleteListener {
uploadImageToFirebaseStorage()
}
}
// Upload selected photo to Firebase Storage - WORKING
private fun uploadImageToFirebaseStorage() {
if(selectedPhotoUri == null) return
val filename = UUID.randomUUID().toString()
val ref = FirebaseStorage.getInstance().getReference("/images/$filename")
ref.putFile(selectedPhotoUri!!)
ref.downloadUrl.addOnSuccessListener {
saveUserToFirebaseDatabase(it.toString())
}
}
// Save user associated credentials to Firebase Database - NOT WORKING
private fun saveUserToFirebaseDatabase(profileImageURL: String) {
val uid = FirebaseAuth.getInstance().uid ?: ""
val ref = Firebase.database.getReference("/users/$uid")
val user = User(uid, username_editText_register.text.toString(), profileImageURL)
ref.setValue(user)
}
}
// User credentials to be saved
class User(val uid: String, val username: String, val profileImageURL: String)
The saveUserToFirebaseDatabase() method does not get executed? I have checked logcat after inserting onSuccessListener and onFailureListener statements, however no error or debug information is highlighted. The app. pushes the image to storage but the DB is not updated. It remains empty. The workflow is as:
- Authenticate user by email and password. - WORKING
- Save profile image in Storage. - WORKING
- Save profile identifier, username, and image in DB. - NOT WORKING
Firebase DB rules:
{
"rules": {
".read": "true",
".write": "true"
}
}
I tried changing the hierarchy but that did not work either:
val uid = FirebaseAuth.getInstance().uid ?: ""
val ref = Firebase.database.getReference("/users/$uid")
val user = User(uid, username_edittext_register.text.toString(), profileImageUrl)
ref.child("users").child(uid).setValue(user)
I have read the Firebase documentation and everything seems to be in place. I also disabled my firewall but that did not work either. Can someone point out the problem here? Thank you in advance.
To get a reference to a Firebase Realtime Database other than the (default) "us-central1", for instance "europe-west1", you must pass the database URL to the getInstance() method.
For "us-central1" there is no need for doing that, you can simply call the "getInstance()" method without passing any arguments.
For more info, please check the official documentation regarding Realtime Database locations:
https://firebase.google.com/docs/projects/locations#rtdb-locations
As an alternative solution, you can download an up-to-date google-services.json from the Firebase Console and add it to your app. If the correct URL of the location is in there, the SDK will read it from there when you call FirebaseDatabase.getInstance() without passing any arguments.
I am able to see the iOS device under devices tab in MF, registered to my application. but pushing a notification fails with the below error:
An error occurred while the notification was sent. Internal server error. No devices found.
Upon reviewing IOS code, I noticed the below issue while invoking MFPPush.sharedInstance.registerDevice(nil)
Cannot retrieve a valid authorization header for header. Check resource and authorization server configuration.
I am using the code from the git sample. Below is the snippet throwing the error:
#IBAction func registerDevice(_ sender: AnyObject) {
print("Attempting Device registration with Mobile First")
WLAuthorizationManager.sharedInstance().obtainAccessToken(forScope: "push.mobileclient") { (token, error) -> Void in
if (error != nil) {
print("Did not recieve an access token from server: " + error.debugDescription)
} else {
WLClient.sharedInstance()?.setDeviceDisplayName("White Ipad", withCompletionHandler: { (error) in
if error == nil{
print("device display name is set")
}else{
print("error setting device name: " + error.debugDescription)
}
})
print("Recieved the following access token value: " + (token?.value ?? "no token"))
MFPPush.sharedInstance().registerDevice(nil) { (response, error) -> Void in
if error == nil {
self.enableButtons()
self.showAlert("Registered successfully with Mobile First")
print(response?.description ?? "")
} else {
self.showAlert("Registration failed with Mobile First. Error \(error?.localizedDescription)")
print(error?.localizedDescription ?? "")
}
}
}
}
}
Mobile First Config: I have followed the documentation and configured the UserLogin security check from the sample git project and have removed scope to push.mobileclient under security.
Reading the OAuth Security in MF, i understand the that token is necessary to access resources, but I am unable to figure out how to attach the token in registerDevice().
It seems to be you haven't configured Push Notifications properly in MobileFirst Server.
Make sure that you have added push.mobileclient scope in Security tab of your application. If you are not using any security check, you can add scope like below.
Check whether your application is configured valid iOS provisioning profile enabled with Push Capability
Make sure that you have uploaded valid sandbox/production certificates in Push tab of your particular app in MFP Operations Console.
More details : here
Make sure your app is enabled Push Capability in the project setting and also check you sending device token to MF Server using MFPPush.sharedInstance().sendDeviceToken(deviceToken) API in didRegisterForRemoteNotificationsWithDeviceToken method of AppDelegate file
-
I would like to create a new mobile application. This new app will be hybrid and will need to be whitelisted. Nowadays, I have an Android native app that request the permission launching the Intent ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS that let the user the possibility of accept/deny the request.
The permission is needed because it is necessary for my app to send data to a private server even if the mobile enters doze/standby mode.
Is it possible to implement something similar using ionic or react-native (I have not decided yet which hybrid technology I will use and any recommendation is appreciated as well).
Thank you!
Yes
On android/app/src/main/AndroidManifest.xml add:
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
On android/app/src/main/java//MainApplication add:
import android.os.PowerManager;
import android.net.Uri;
import android.provider.Settings;
then on function public void onCreate() before SoLoader.init(); add:
Intent myIntent = new Intent();
String packageName = getApplicationContext().getPackageName();
PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
if (pm.isIgnoringBatteryOptimizations(packageName))
myIntent.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
else {
myIntent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
myIntent.setData(Uri.parse("package:" + packageName));
}
getApplicationContext().startActivity(myIntent);
I'm trying to monetize my app with Universal Windows. I followed the official tutorials but when I tried to load an interstitial ad, always I'm getting this errors:
Interstitial ad is not ready. With this error code: ClientConfiguration.
Failed to make http requestError. With this error code: NetworkConnectionFailure.
I don't know what I am missing.
This is my code:
public sealed partial class Myclass: Page {
InterstitialAd MyVideoAd;
public MyClass() {
this.InitializeComponent();
var MyAppId = "d25517cb-12d4-4699-8bdc-52040c712cab";
var MyAdUnitId = "11389925";
MyVideoAd = new InterstitialAd();
MyVideoAd.ErrorOccurred += MyVideoAd_ErrorOccurred;
MyVideoAd.RequestAd(AdType.Video, MyAppId, MyAdUnitId);
}
private void MyVideoAd_ErrorOccurred(object sender, AdErrorEventArgs e) {
String errrorMessage = e.ErrorMessage;
String errorCode = e.ErrorCode;
}
private void showInterstitial(object sender, TappedRoutedEventArgs e) {
MyVideoAd.Show();
}
}
When I execute the application, a few seconds after the MyVideoAd_ErrorOccurred method is launched with the values of errorMessage and errorCode as I've said. That happens on my Windows 10 mobile device and in the Desktop machine execution. The codes of adUnit and application id are the provided in the Microsoft page for tests.
I hope that you can help me.
For UWP app, please install Microsoft Universal Ad Client SDK and use AdMediatorControl.
References:
Install the Universal Ad Client SDK
Add and use the ad mediator control
Check my sample: https://github.com/Myfreedom614/UWP-Samples/tree/master/AdClientUWPApp
Be sure to have these 3 Capabilities defined inside your manifest:
<Capabilities>
...
<Capability Name="internetClient"/>
<Capability Name="internetClientServer"/>
<Capability Name="privateNetworkClientServer"/>
...
</Capabilities>
The video hasn't finished loading. you need to give it enough time for that. also you need to make sure it is loaded before calling it with.
if ((InterstitialAdState.Ready) == (MyVideoAd.State))
{
MyVideoAd.Show();
}