How to check if a Firebase App is already initialized on Android - java

With the following, the first time it's called it works, but then fails on subsequent calls with "FirebaseApp name [DEFAULT] already exists!"
public FirebaseDatabase conn(Context c) {
FirebaseOptions options = new FirebaseOptions.Builder()
.setApiKey("key")
.setDatabaseUrl("url")
.setApplicationId("ID")
.build();
/////I tried Try and Catch with no success//////
FirebaseApp app = FirebaseApp.initializeApp(c, options);
/// for this : FirebaseApp app = FirebaseApp.initializeApp(c, options, "some_app");
//// will fail with "FirebaseApp name some_app already exists!"
return FirebaseDatabase.getInstance(app);
}
All of the above is an attempt to connect to a second Firebase App.

On firebase web, you check if already initialized with:
if (firebase.apps.length === 0) {
firebase.initializeApp({});
}

In v9, Firebase has been modularized for better tree shaking. So we can no longer import entire app and check the apps property AFAIK. The below approach can be used instead.
import { initializeApp, getApps, getApp } from "firebase/app";
getApps().length === 0 ? initializeApp(firebaseConfig) : getApp();
https://firebase.google.com/docs/reference/js/v9/app.md#getapps for documentation

Firebase Version 9
import { initializeApp, getApp } from "firebase/app";
const createFirebaseApp = (config = {}) => {
try {
return getApp();
} catch () {
return initializeApp(config);
}
};
const firebaseApp = createFirebaseApp({/* your config */})

For those wondering how to do the same as the accepted answer, in Android:
if (FirebaseApp.getApps(context).isEmpty()) {
FirebaseApp.initializeApp(context);
}
and in an instrumented test environment, use this context:
InstrumentationRegistry.getContext()

You can try to get the Firebase app instance, in it's code firebase checks if it's initialized, if not it throws an IllegalStateException.
try{
FirebaseApp.getInstance();
}
catch (IllegalStateException e)
{
//Firebase not initialized automatically, do it manually
FirebaseApp.initializeApp(this);
}

I think what you want to do is check the list of running apps before initializing your app. Each of the SDKs have a method for getting this array, in android it's getApps:
https://firebase.google.com/docs/reference/android/com/google/firebase/FirebaseApp.html
Then you can check to see if your app is already initialized.
In my case I just ended up checking the length of the array (I'm using the javascript / web sdk so I'm sure it's a little different for Android) and initializing a new app if it is 0.

In firebase admin SDK for java, initialize the app if and only if there is no app.
if (FirebaseApp.getApps().isEmpty()) {
FirebaseApp.initializeApp();
}

I faced the similar issue.
I solved the following problem by deleting the already initialized app.
// Access your firebase app
let app = firebase.app();
// Delete your app.
app.delete(app);
Solution works for web.

Not sure in android, but how about using a singleton method. In JS you can do this. Hope this helps someone
// Config file
import * as firebase from "firebase";
const config = {...};
export default !firebase.apps.length ? firebase.initializeApp(config) : firebase.app();
// Other file
import firebase from '../firebase';

import * as firebase from "firebase/app";
firebase.apps.map(e => e.name); // Give you an array of initialized apps

For those who are using dotNet FirebaseAdmin SDK
if (FirebaseApp.GetInstance("[DEFAULT]") == null)
{
var createdApp = FirebaseApp.Create(new AppOptions()
{
Credential = GoogleCredential.FromFile("private-key.json")
});
}

I faced the similar issue, I resolved it as following:
Create a var for the application and initialize it with null
Take reference of the application while initialization
Check before initializing it again
//global variable
var firebaseResumeDownloadAdd = null;
//inside function check before initializing
if(firebaseResumeDownloadAdd==null){
firebaseResumeDownloadAdd =
firebase.initializeApp(functions.config().firebase);
}

in Android, depending on Daniel Laurindo's answer:
if (FirebaseApp.getApps(context).size != 0) {
}

A cleaner solution for ES6+ is
if (!firebase.apps.length) {
...
}

Simple use Java 8 Stream and Optional featured.
Code below as
FirebaseApp.getApps()
.stream()
.filter(firebaseApp ->
firebaseApp.getName().equals("APP_NAME"))
.findFirst()
.orElseGet(() -> FirebaseApp.initializeApp(firebaseOptions, "APP_NAME"));

Th
Use Platform check to initialize according to environment
On firebase web, you check if already initialized with
use the below snippet while launching MYAPP()
import 'dart:io';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
if (Platform.isAndroid || Platform.isIOS) {
await Firebase.initializeApp();
} else {
if (Firebase.apps.isEmpty) {
await Firebase.initializeApp(
// connect for web to firebase
options:firebaseOptions
}
}
runApp(const MyApp());
}

const app = !getApps().length ? initializeApp(firebaseConfig) : getApp();

For web, you could use:
import { getApp, initializeApp } from "firebase/app"
const firebaseConfig = {/* YOUR CONFIG */}
function createFirebaseApp(config) {
try {
return getApp()
} catch {
return initializeApp(config)
}
}
const firebaseApp = createFirebaseApp(firebaseConfig)

As of now, I Do not have access to comments or likes. But I think this point is important to make.
Many good answers here, but it is also essential to talk about the best answers and performance.
Ideally, you want to minimize code that goes into your production and also want to make sure that there are no unnecessary pieces out there. Thus, a tree-shaking solution is best.
I do following
import { initializeApp, getApps, cert } from "firebase-admin/app";
const secret = JSON.parse(process.env.FIREBASE_SECRET || "{}");
if (!getApps().length) initializeApp({ credential: cert(secret) });

If you are using Nativescript to build an hybrid mobile app for Android | iOS you can use this script:
import * as firebase from 'nativescript-plugin-firebase';
_initFirebase(): Promise<any> {
if (!(firebase as any).initialized) {
return firebase.init({}).then(
() => {
console.info('firebase started...');
},
(error) => console.error(error)
);
}
}

Related

How to get Google Ads impressions based on location

I am working with Google Ads API. Based on my use case, I need to get the impressions, clicks, and other statistics about the products based on location(Without creating the campaign).
I contacted the Google Ads API team to address the issue but the doc reference they provided me didn't work in my case. (I'm not using keywords also)
generate forecast metrics
And also the query I used to access the data is...
public void queryTest(long customerId,String campaignId) {
try (GoogleAdsServiceClient googleAdsServiceClient =
googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) {
SearchGoogleAdsStreamRequest request =
SearchGoogleAdsStreamRequest.newBuilder()
.setCustomerId(Long.toString(customerId))
.setQuery("SELECT metrics.clicks, metrics.impressions,geographic_view.country_criterion_id FROM geographic_view WHERE geographic_view.country_criterion_id = 1009919")
.build();
ServerStream<SearchGoogleAdsStreamResponse> stream =
googleAdsServiceClient.searchStreamCallable().call(request);
for (SearchGoogleAdsStreamResponse response : stream) {
for (GoogleAdsRow googleAdsRow : response.getResultsList()) {
System.out.println("outPut"+googleAdsRow.getGeographicView());
}
}
}
}
Can someone please help me to resolve this issue??
Thank you!!

user.permissionsBoundary returns NULL while retrieving information from AWS using Java SDK

I am using AWS Java SDK v2 to list users using the code defined here on the AWS GitHub repo.
public static void listAllUsers(IamClient iam) {
try {
boolean done = false;
String newMarker = null;
while (!done) {
ListUsersResponse response;
ListUsersRequest request;
if (newMarker == null) {
request = ListUsersRequest.builder().build();
} else {
request = ListUsersRequest.builder()
.marker(newMarker).build();
}
response = iam.listUsers(request);
for (User user : response.users()) {
System.out.format("\n Retrieved user %s", user.userName());
System.out.println("\nPermission Boundary: " + user.permissionsBoundary());
}
if (!response.isTruncated()) {
done = true;
} else {
newMarker = response.marker();
}
}
} catch (IamException e) {
System.err.println(e);
System.exit(1);
}
}
It returns NULL for user.permissionsBoundary(). Here is the output for print statements in the above code.
Retrieved user jamshaid
Permission Boundary: null
Retrieved user luminadmin
Permission Boundary: null
Retrieved user test
Permission Boundary: null
When I run the following command in AWS CloudShell on AWS console, it returns the PermissionBoundary for the users it is defined.
aws iam get-user --user-name test
Here is the sample output from AWS CloudShell.
I am using the same account to make both requests.
I have confirmed this behavior by setting a permission boundary on an IAM user in the AWS Management Console. I changed the ListUsers example to include this code:
for(User user : response.users()) {
System.out.format("\n Retrieved user %s", user.userName());
AttachedPermissionsBoundary permissionsBoundary = user.permissionsBoundary();
if (permissionsBoundary != null)
System.out.format("\n Permissions boundary details %s", permissionsBoundary.permissionsBoundaryTypeAsString());
}
...
The permissionsBoundary() method does return null - even though the permission is set. This is a bug.
My advice here is to log a Github issue here:
https://github.com/aws/aws-sdk-java-v2
I also tested this with Kotlin SDK. Same result.
suspend fun listAllUsers() {
IamClient { region = "AWS_GLOBAL" }.use { iamClient ->
val response = iamClient.listUsers(ListUsersRequest { })
response.users?.forEach { user ->
println("Retrieved user ${user.userName}")
val permissionsBoundary = user.permissionsBoundary
if (permissionsBoundary != null)
println("Permissions boundary details ${permissionsBoundary.permissionsBoundaryType.toString()}")
}
}
}
I do not think it is an issue, but the programmed behavior. From the API docs:
IAM resource-listing operations return a subset of the available attributes
for the resource. For example, this operation does not return tags, even
though they are an attribute of the returned object. To view all of the
information for a user, see GetUser.
This is stated as well in the API javadocs.
In the console you are using get-user, not list-users, and this is why the command is returning all the information about the user, PermissionsBoundary within it.
Please, try instead using:
aws iam list-users
and check the output, it should match the result you obtained with the Java SDK, it will not contain PermissionsBoundary either.
If you want to obtain the same results that you are currently getting with the command aws iam get-user --user-name test from Java code, you can use the getUser method in IamClient. Try Something like:
GetUserRequest request = GetUserRequest.builder()
.userName("test")
.build()
;
GetUserResponse response = iam.getUser(request);
User user = response.user();
System.out.println("\nPermission Boundary: " + user.permissionsBoundary());
The User class is reused in both operations, get and list, but only in the former all the fields are populated.

Firebase : updatePhoneNumber for Current User who logged in with google

Firebase developers, I used login with google in one of my application and successfully done.
Problem: I am getting Display Name and Email Id from Google but not getti get Phone Number. So I am taking that phone number from user in next activity.
Now If I want to update that phone number to current user of Firebase then what are the ways to do that.
I have found one method that is FirebaseAuth.getInstance().getCurrentUser().updatePhoneNumber() but didn't get any proper idea to use this.
If you have implemented this thing, help me.
Appreciated advance.
Thank you.
FirebaseUser's updatePhoneNumber() method:
Updates the phone number of the user.
And as you can see, it takes as an argument a PhoneAuthCredential object. So in order to update the phone number of the corresponding user, call updatePhoneNumber() method and pass the new phone credential object as an argument.
Important: this is a security sensitive operation that requires the user to have recently signed in. If this requirement isn't met, ask the user to authenticate again and later call reauthenticate(AuthCredential).
it took me a lot to find out how it could be done but here's how I did it
user firebase SDK recapcha
window.recaptchaVerifier = new fireabase.auth.RecaptchaVerifier('sign-in-button', {
size: 'invisible'
})
send SMS code
const phoneNumber = this.input.phone
const appVerifier = window.recaptchaVerifier
firebase.auth().currentUser.linkWithPhoneNumber(phoneNumber, appVerifier)
.then((confirmationResult) => {
window.confirmationResult = confirmationResult
// prompt user to entre code
...
})
.catch((error) => {
// reset rechatcha and try again
appVerifier.reset('sign-in-button')
alert(error.message)
})
Confirm the Code and link
const code = this.input.code
window.confirmationResult.confirm(code).then((result) => {
const credential = firebase.auth.PhoneAuthProvider.credential(window.confirmationResult.verificationId, code)
firebase.auth().currentUser.linkWithCredential(credential)
})
.then(() => {
// done
})
.catch((error) => {
alert(error.message)
// try again
})
Some github repo containing an implementation:
https://github.com/wardah9/QuestionsQate/blob/9224a6d2e00a9304566be063c2d611b76cc76fb8/app/src/main/java/com/questionqate/StudentProfile/UpdatedMobileAthuntication.java
You need to import and build an 'com.google.firebase.auth.PhoneAuthCredential'
To do that you need to ask your user to authenticate using their phone number using the 'com.google.firebase.auth.PhoneAuthProvider'.
Since you are using GoogleAuthProvider, you can update the user Phone Number 'by hand' using the method you posted and building the PhoneAuthCredential yourself or you need to intanciate a new PhoneAuthProvider and make the already authenticated user re-auth with his phone number (you need Phone Auth enabled in your providers at Firebase Console)
You can do this in React Native.
handlePhone=()=>{
const auth = firebase.auth();
const {phoneNumber} = this.state;
const self = this;
if(phoneNumber != ''){
try{
const snapshot = await auth.verifyPhoneNumber(`+92${phoneNumber}`).on('state_changed',
async (phoneAuthSnapshot) => {
switch(phoneAuthSnapshot.state){
case firebase.auth.PhoneAuthState.CODE_SENT:
self.setState({verificationSnapshot:phoneAuthSnapshot,showOTP:true})
}
})
}catch(error){
console.log(error);
this.showAlert('Try again later');
}
}else{
this.showAlert('Please enter phone number.');
}
}
handleVerifyOTP=()=>{
const {verificationCode, verificationSnapshot} = this.state;
console.log(verificationCode, verificationSnapshot)
const self = this;
try{
const credential = await firebase.auth.PhoneAuthProvider.credential(verificationSnapshot.verificationId, verificationCode);
console.log(credential)
const u = await firebase.auth().currentUser.updatePhoneNumber(credential);
console.log(u)
self.setState({showOTP:false,phoneNumberState:true});
Alert.alert('Number has been registered successfully')
}catch(error){
Alert.alert('Something went wrong');
console.log(error,"ERRR")
}
}
Add two input fields with buttons
One is for phone number
Other is for OTP

Can the accessibility "Magnification Gesture" be detected on Android?

I've got a game app and it requires repeated tapping. Some players are complaining that it doesn't work when they have the "triple tap to zoom" accessibility gesture enabled on their device.
Web search showed me that it can't be disabled within my game, but can it be detected? At least then I can explain to users how to turn it off while playing.
I'm not sure which android API I could use to check this setting. I'm not a native android developer, I work in Unity and Google isn't turning up anything.
Thanks to zcui93, I was able to test for this setting using the following Java:
Settings.Secure.getInt( context.getContentResolver(), "accessibility_display_magnification_enabled" );
...just check the return value: 1 = enabled, 0 = disabled
Here's the code to do it in a Unity C# Script:
public static bool CheckForSystemZoomEnabled()
{
#if UNITY_ANDROID
try {
using(AndroidJavaClass clsUnity = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
AndroidJavaObject objActivity = clsUnity.GetStatic<AndroidJavaObject>("currentActivity");
AndroidJavaObject objResolver = objActivity.Call<AndroidJavaObject>("getContentResolver");
using(AndroidJavaClass clsSecure = new AndroidJavaClass("android.provider.Settings$Secure"))
{
int val = clsSecure.CallStatic<int>("getInt", objResolver, "accessibility_display_magnification_enabled");
return val != 0;
}
}
} catch(System.Exception) { }
#endif
return false;
}

how to identify whether the OS is Linux desktop or Android? [duplicate]

This question already has answers here:
How do I programmatically determine operating system in Java?
(22 answers)
Closed 3 years ago.
I have an app that runs on several mobile devices running either Fedora or Android. To consolidate my codebase and distribution I would like to determine which OS I am on. I tried System.getProperty("os.name"), but that just returns "Linux". Is there something unique to Android in the System properties?
Thanks
There are several properties you could check. Candidates are:
java.vendor.url --> http://www.android.com
java.vm.name --> Dalvik (I don't know, which one Fedora is using...)
java.vm.vendor --> The Android Project
java.vendor --> The Android Project
Maybe you want to check by yourself?
Properties p = System.getProperties();
Enumeration keys = p.keys();
while(keys.hasMoreElements()) {
String key = (String) keys.nextElement();
String value = (String) p.get(key);
System.out.println(key + " >>>> " + value);
}
I do not know Android but if you do not find some unique system property you can sometimes identify the system if some specific class exists there. So you can do the following:
boolean isAndroid() {
try {
Class.forName("the class name");
return true;
} catch(ClassNotFoundException e) {
return false;
}
}
Here is some code that I wrote using the information from this page, in case you want to copy-paste:
private static YLogger ylogger;
public static YLogger getLogger() {
if (ylogger == null){
// need to find a new logger. Let's check if we have Android running
if (System.getProperty("java.vm.name").equalsIgnoreCase("Dalvik")){
ylogger = new AndroidLogger();
ylogger.d("YLoggerFactory", "Instantiating Android-based logger");
} else {
// fallback option, system logger.
ylogger = new SystemLogger();
ylogger.d("YLoggerFactory", "Instantiating System-based logger");
}
}
return ylogger;
}
The list of defined system properties is here: https://developer.android.com/reference/java/lang/System#getProperties()
I'm using
boolean android = "The Android Project".equals(System.getProperty("java.specification.vendor"));
I use this in my processing sketch to determine in which mode I'm running i.e. where I'm running it.
enum Mode {
java, android
}
Mode getMode() {
return System.getProperty("java.runtime.name").equals("Android Runtime") ? Mode.android : Mode.java;
}
if (getMode() == Mode.java){
// do something
// eg: do something that android can't handle
} else {
// do android stuff
// eg: scale the sketch by 2 to improve visibility
}

Categories

Resources