I'm trying to Read data from Firebase via Java. The addListenerForSingleValueEvent, and anything I put inside it, does not execute. After searching through other related stack questions, I've been unable to find a non-Android related answer. Please take a look and let me know why this method is not executing. Thanks in advance.
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.io.*;
public class App {
public static void main( String[] args ) {
class ServiceFile {
private FileInputStream mMyFile;
public ServiceFile(String myFile) {
try {
mMyFile = new FileInputStream(myFile);
System.out.println("The Service File exists. "); // this line prints
} catch (FileNotFoundException ex) {
System.out.println("The Service File does not exist.");
}
}
public FileInputStream getMyFile() {
return mMyFile;
}
}
ServiceFile serviceFile = new ServiceFile("/Users/xxxx/Documents/development/javaFire/serviceAccountKey.json");
FirebaseOptions options = new FirebaseOptions.Builder()
.setServiceAccount(serviceFile.getMyFile())
.setDatabaseUrl("https://xxxx.firebaseio.com")
.build();
// Initialize the app
FirebaseApp myApp = FirebaseApp.initializeApp(options);
// Get the reference to some location within the DB
final FirebaseDatabase database = FirebaseDatabase.getInstance(myApp);
DatabaseReference ref = database.getReference("/users/john");
// Attach a listener to read the data at the DB reference
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot theData) {
System.out.println("Success! "); // this line does not print
}
#Override
public void onCancelled(DatabaseError databaseError) {
System.out.println("Cancelled" + databaseError.getMessage()); // this line does not print
}
});
}
}
My database rules are as such:
{
"rules": {
".read": true,
".write": "auth != null"
}
}
My data in Firebase, at /users.json
{
"john": {
"dob": "02/20/1980"
}
}
It looks like your callback is not executing because your program ends before the callback can receive new data. Remember that addListenerForSingleValueEvent is asynchronous (it returns immediately), so your main function will return immediately, which means the JVM will exit.
At a very minimum, you could put a call to Thread.sleep() at the end of the function to make sure it doesn't terminate immediately. But for a real program, you'll likely be doing something else.
Related
I am having a problem with the API that I have implemented to my website that is connected to an activity in the Android application that I am developing. According to the Logcat of my Android Studio,
that line 118 of the ForgotPassword.java of my Android application
is throwing the java.lang.AssertionError. I have studied the problem again, then learned that the response of the API that is implemented on my website is being read by my Android application as null, thus with the aforementioned error.
I have also tried to solve the problem by doing the following:
Created a separate response class called ForgotPassRP with the same variables, because the DataRP response class is being used by other classes.
Updated the version of the retrofit that is implemented in my
build.grade(:app) from 2.7.2 to 2.9.0 and the retrofit2:converter-gson from 2.5.0 to 2.9.0.
Currently, I am still finding a solution by digging more about REST APIs on websites and Retrofit on Android, and I will implement anything new that I can learn from these. So am I missing something on my website, and Android code, or are there variables that are missing, while I am trying to do a POST method to the API that I have implemented to my website?
These are the following body of codes that I have analyzed so far that are connected to the problem (java.lang.AssertionError) that I am encountering on my Android application
The screenshot of the actual error that is being shown in the Logcat of my Android Studio:
Website:
1. APIS.php
//This is where the #POST method from my Android application API interface of the "ForgotPassword.java" is communicating with
public function forgot_password_post()
{
$response = array();
$user_info = $this->common_model->check_email($this->get_param['email'])[0];
if (!empty($user_info))
{
$this->load->helper("rendomPassword");
$info['new_password'] = get_random_password();
$updateData = array(
'user_password' => md5($info['new_password'])
);
$data_arr = array(
'email' => $user_info->user_email,
'password' => $info['new_password']
);
if ($this->common_model->update($updateData, $user_info->id, 'tbl_users')) {
$subject = $this->app_name . ' - ' . $this->lang->line('forgot_password_lbl');
$body = $this->load->view('admin/emails/forgot_password.php', $data_arr, TRUE);
if (send_email($user_info->user_email, $user_info->user_name, $subject, $body))
{
$row_info = array('success' => '1', 'msg' => $this->lang->line('password_sent_mail'));
}
else
{
$row_info = array('success' => '0', $this->lang->line('email_not_sent'));
}
}
}
else
{
$row_info = array('success' => '0', 'msg' => $this->lang->line('email_not_found'));
}
$this->set_response($row_info, REST_Controller::HTTP_OK);
}
Android Application
1. ForgotPassword.java
package com.example.mototecxecommerceapp.activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.example.mototecxecommerceapp.R;
import com.example.mototecxecommerceapp.response.DataRP;
import com.example.mototecxecommerceapp.response.ForgotPassRP;
import com.example.mototecxecommerceapp.rest.ApiClient;
import com.example.mototecxecommerceapp.rest.ApiInterface;
import com.example.mototecxecommerceapp.util.API;
import com.example.mototecxecommerceapp.util.ConstantApi;
import com.example.mototecxecommerceapp.util.Method;
import com.google.android.material.appbar.MaterialToolbar;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.textfield.TextInputEditText;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import org.jetbrains.annotations.NotNull;
import io.github.inflationx.viewpump.ViewPumpContextWrapper;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class ForgetPassword extends AppCompatActivity {
private Method method;
private TextInputEditText editText;
private ProgressDialog progressDialog;
private InputMethodManager imm;
#Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(ViewPumpContextWrapper.wrap(newBase));
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fp);
method = new Method(ForgetPassword.this);
method.forceRTLIfSupported();
progressDialog = new ProgressDialog(ForgetPassword.this);
imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
MaterialToolbar toolbar = findViewById(R.id.toolbar_fp);
toolbar.setTitle(getResources().getString(R.string.forget_password));
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
editText = findViewById(R.id.editText_fp);
MaterialButton button = findViewById(R.id.button_fp);
button.setOnClickListener(v -> {
String string_fp = editText.getText().toString();
editText.setError(null);
if (!isValidMail(string_fp) || string_fp.isEmpty()) {
editText.requestFocus();
editText.setError(getResources().getString(R.string.please_enter_email));
} else {
editText.clearFocus();
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
if (method.isNetworkAvailable()) {
forgetPassword(string_fp);
} else {
method.alertBox(getResources().getString(R.string.internet_connection));
}
}
});
}
private boolean isValidMail(String email) {
return android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches();
}
public void forgetPassword(String sendEmail) {
progressDialog.show();
progressDialog.setMessage(getResources().getString(R.string.loading));
progressDialog.setCancelable(false);
JsonObject jsObj = (JsonObject) new Gson().toJsonTree(new API(ForgetPassword.this));
jsObj.addProperty("email", sendEmail);
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
Call<DataRP> call = apiService.getForgotPass(API.toBase64(jsObj.toString()));
call.enqueue(new Callback<DataRP>() {
#Override
public void onResponse(#NotNull Call<DataRP> call, #NotNull Response<DataRP> response) {
try {
DataRP dataRP = response.body();
assert dataRP != null; //This is the part of the code where the java.lang.AssertionError is being thrown.
if (dataRP.getStatus().equals("1")) {
if (dataRP.getSuccess().equals("1")) {
editText.setText("");
}
method.alertBox(dataRP.getMsg());
} else {
method.alertBox(dataRP.getMessage());
}
} catch (Exception e) {
Log.d(ConstantApi.exceptionError, e.toString());
method.alertBox(getResources().getString(R.string.failed_response));
}
progressDialog.dismiss();
}
#Override
public void onFailure(#NotNull Call<DataRP> call, #NotNull Throwable t) {
// Log error here since request failed
Log.e(ConstantApi.failApi, t.toString());
progressDialog.dismiss();
method.alertBox(getResources().getString(R.string.failed_response));
}
});
}
#Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}
}
2. ApiInterface.java
//This is the post method that is being sent to the forgot password API of my website.
#POST("apis/forgot_password")
#FormUrlEncoded
Call<DataRP> getForgotPass(#Field("data") String data);
3. DataRP.java
package com.example.mototecxecommerceapp.response;
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
//This is the response from the #POST method.
public class DataRP implements Serializable {
#SerializedName("status")
private String status;
#SerializedName("message")
private String message;
#SerializedName("success")
private String success;
#SerializedName("msg")
private String msg;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getSuccess() {
return success;
}
public void setSuccess(String success) {
this.success = success;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
I am also including the screenshot of the API logs that are being stored in the database that I have integrated into my website. This part is what seems to be the response of the "apis/forgot_password", whenever a post method that is thrown by my Android application is executed.
The SQL database of my website showing the logs related to "apis/forgotpassword"
This is also my first time asking a question in StackOverflow. So please bear with any "rookie mistakes" with the format/structure of the question that I have posted :)
In the android application development most used Retrofit2 Retrofit2 Documention
Then Generate Response Model Class (Call API using Postman). Create a Response Model with JSON
Source type:> JSON. Annotation style:>Gson.
Use this code in the "onResponse" method section.
if (response.isSuccessful()) {
if (response.body() != null) {
DataRP dataRp=response.body();
//code statement... } }
I got a problem related to Firebase and Java EE.
I'm currently writing some Java servlets for my project and I'm using Firebase the first time because I wanted to try something new.
My actual problem is the following:
I got a servlet which is responsible for exchanging an iOS device token in an user database. This is necessary for sending Remote Push Notifications to a device.
I've done this like in the google tutorials, but I'm getting the following exception:
java.lang.IllegalStateException: FirebaseApp name [DEFAULT] already exists!
The way I'm accessing the Firebase Database is through the Java SDK.
I do this with the following code:
connect method
// gets called by the servlet to configure Firebase
public static void connect() {
try {
// for authentication purpose
Map<String, Object> auth = new HashMap<>();
auth.put("uid", "my-service-account");
// Setting up the FirebaseOptions object
// constant FIREBASE_DATABASE_URL = "url to my database"
// constant FIREBASE_KEY_PATH = "path to my json key"
options = new FirebaseOptions.Builder()
.setDatabaseUrl(FIREBASE_DATABASE_URL)
.setServiceAccount(new FileInputStream(FIREBASE_KEY_PATH))
.setDatabaseAuthVariableOverride(auth)
.build();
FirebaseApp.initializeApp(options);
// calling the method for exchanging the token
exchangeIosDeviceToken("testmail#example.com", "5bf53173c9ef0a37638f3ddaa59cf2c0687c14ca0dcd47ccf57f9f09bd6368ab");
} catch (FileNotFoundException ex) {
ex.printStackTrace();
}
}
exchangeIosDeviceToken method
public static boolean exchangeIosDeviceToken(String email, String newDeviceToken) {
FirebaseDatabase database = FirebaseDatabase.getInstance();
// getting a reference to my "employee" child
DatabaseReference employeeReference = database.getReference("/employee");
Map<String, Object> employeeUpdates = new HashMap<>();
// updating the device token with child "iosDeviceToken" of "employee"
employeeUpdates.put(email+"/iosDeviceToken", newDeviceToken);
// update the actual children
employeeReference.updateChildren(employeeUpdates);
return true;
}
The funny part is when I'm trying to execute this code in a standalone main class (replacing the connect method, with the main method), the code is working.
Before you're saying things like "there are tons of questions related to this topic"... They are nearly all related to Android and questions related to my problem seldom got answered.
Regards
Solved the problem.
The problem was:
I've called the connect method everytime a request was incoming.
Solution:
Call the connect method only once. (ServletContextListener)
this for the future users, You can check whether the default app is initialized or not like this.
FirebaseApp firebaseApp = null;
List<FirebaseApp> firebaseApps = FirebaseApp.getApps();
if(firebaseApps!=null && !firebaseApps.isEmpty()){
for(FirebaseApp app : firebaseApps){
if(app.getName().equals(FirebaseApp.DEFAULT_APP_NAME))
firebaseApp = app;
}
}
else
firebaseApp = FirebaseApp.initializeApp(options);
This exception appear because you are trying to create the [DEFAULT] FirebaseApp again, simply you can add a validation to check if it exist or not before the initialization, like this:
if(FirebaseApp.getInstance(FirebaseApp.DEFAULT_APP_NAME) != null) {
return;
}
My fix to this issue was call FirebaseApp.getInstance().delete();
My solution
package com.zs.configuration;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOpt`enter code here`ions;
import com.google.firebase.auth.FirebaseAuth;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.io.FileInputStream;
#WebListener
public class MyAppServletContextListener
implements ServletContextListener{
#Override
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("ServletContextListener destroyed");
}
//Run this before web application is started
#Override
public void contextInitialized(ServletContextEvent arg0) {
try {
FileInputStream serviceAccount = new FileInputStream(getClass().getClassLoader().getResource("zs.json").getFile());
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.setDatabaseUrl("https://zs.firebaseio.com")
.build();
FirebaseApp firebaseApp = FirebaseApp.initializeApp(options);
FirebaseAuth.getInstance(firebaseApp);
}catch (Exception exc){
System.out.println("Firebase exception "+exc);
}
System.out.println("ServletContextListener started");
}
}
In my Application class
#ServletComponentScan
#SpringBootApplication
public class ZSApplication {
public static void main(String[] args) {
SpringApplication.run(ZSApplication.class, args);
}
}
Summarising all the solutions, very good ones BTW, proposed here: Running code after Spring Boot starts please find below the spring-boot (2.6.3) implementations which works for me.
Beware: Substitute with your app and files names below.
Placing the firebase initialisation method ( FirebaseApp.initializeApp(options)) directly on the main method (as I found on this tutorial: https://www.youtube.com/watch?v=8jK9O0lwem0) it caused the error, just because, debugging I notice, for some reason the call of the method FirebaseApp.initializeApp(options); is done multiple times.
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Objects;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import lombok.extern.slf4j.Slf4j;
#Slf4j
#SpringBootApplication
public class YourAppNameApplication {
public static void main(String[] args) {
SpringApplication.run(YourAppNameApplication.class, args);
}
/**
* Initialize the firebase SDK to integrate with the firebase application. Used
* for check the clients UIDs authentications.
*
* #throws IOException in case the firebase configuration JSON file is not
* present on the path.
*/
#EventListener(ApplicationReadyEvent.class)
public void initFirebaseSDK() throws IOException {
ClassLoader classLoader = YourAppNameApplication.class.getClassLoader();
File file = new File(
Objects.requireNonNull(classLoader.getResource("your_file_firebase.json")).getFile());
FileInputStream serviceAccount = new FileInputStream(file.getAbsolutePath());
#SuppressWarnings("deprecation")
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.setDatabaseUrl("https://your_firebase_app_name.firebaseio.com").build();
FirebaseApp.initializeApp(options);
if (!(FirebaseApp.getApps().isEmpty())
&& FirebaseApp.getInstance(FirebaseApp.DEFAULT_APP_NAME).getName() != null) {
log.info("Firebase SDK has been initialised with the app name: "
+ FirebaseApp.getInstance(FirebaseApp.DEFAULT_APP_NAME).getName());
} else {
log.error(
"Firebase SDK has NOT been initialised. This is a serious error. Please contact the administrator of the app.");
}
}
}
Asterisk 11.4.0
Asterisk-java: 1.0.0.CI-SNAPSHOT
I've try to run this code:
import org.asteriskjava.live.AsteriskChannel;
import org.asteriskjava.live.AsteriskQueue;
import org.asteriskjava.live.AsteriskQueueEntry;
import org.asteriskjava.live.internal.AsteriskAgentImpl;
import org.asteriskjava.live.AsteriskServer;
import org.asteriskjava.live.AsteriskServerListener;
import org.asteriskjava.live.DefaultAsteriskServer;
import org.asteriskjava.live.ManagerCommunicationException;
import org.asteriskjava.live.MeetMeRoom;
import org.asteriskjava.live.MeetMeUser;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
public class HelloLiveEverything implements AsteriskServerListener, PropertyChangeListener
{
private AsteriskServer asteriskServer;
public HelloLiveEverything()
{
asteriskServer = new DefaultAsteriskServer("localhost", "manager", "password");
}
public void run() throws ManagerCommunicationException
{
// listen for new events
asteriskServer.addAsteriskServerListener(this);
// add property change listeners to existing objects
for (AsteriskChannel asteriskChannel : asteriskServer.getChannels())
{
System.out.println(asteriskChannel);
asteriskChannel.addPropertyChangeListener(this);
}
}
public void onNewAsteriskChannel(AsteriskChannel channel)
{
System.out.println(channel);
channel.addPropertyChangeListener(this);
}
public void onNewMeetMeUser(MeetMeUser user)
{
System.out.println(user);
user.addPropertyChangeListener(this);
}
public void onNewQueueEntry(AsteriskQueueEntry user)
{
System.out.println(user);
user.addPropertyChangeListener(this);
}
public void onNewAgent(AsteriskAgentImpl user)
{
System.out.println(user);
user.addPropertyChangeListener(this);
}
public void propertyChange(PropertyChangeEvent propertyChangeEvent)
{
System.out.println(propertyChangeEvent);
}
public static void main(String[] args) throws Exception
{
HelloLiveEverything helloLiveEverything = new HelloLiveEverything();
helloLiveEverything.run();
while (true) {
}
}
}
When executed, connectios is OK. This code show me current channels but never show me new channels when callers make a calls.
I need to catch the events when new asterisk channels are opening.
What I made wrong?
Thank you
Try This:
Your Class HelloLiveEverything should implement ManagerEventListener
then override the onManagerEvent method
#Override
public void onManagerEvent(ManagerEvent event) {
String event_name = event.getClass().getSimpleName();
if (event_name.equals("DialEvent")) {
DialEvent e = (DialEvent) event;
System.out.println(e.getCallerIdNum());//caller number
System.out.println(e.getDestination());//Called number
//do something here
}
}
edit asterisk manager.conf :
[manager]
secret = password
deny=0.0.0.0/0.0.0.0
permit=209.16.236.73/255.255.255.0; change this ip with one your java app is using permit=127.0.0.1/255.255.255.0
read = system,call,log,verbose,command,agent,user,originate; add full permission
write = system,call,log,verbose,command,agent,user,originate; add full permission
I am trying to create an Android / Java plugin for the cross-platform program Phonegap / Cordova 3.2. I am following several tutorials but can't get the simplest plugin to work.
Currently I am working on the idea that my Java code is just wrong somewhere.
Could someone please review the following code and advise if there is something obviously wrong?
The error I keep getting is
Exception: No Activity found to handle Intent { act=android.intent.action.MEDIA_SCANNER_SCAN_FILE dat=file:///{"fullPath":"media\/test.mp3"} }
Here is my .java file
package org.media.scan;
import java.io.File;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.json.JSONArray;
import org.json.JSONException;
import android.content.Intent;
import android.net.Uri;
public class Scan extends CordovaPlugin {
#Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
try {
if ( action.equals("addRemove") ) {
String filePath = args.getString(0);
filePath = filePath.replaceAll("^file://", "");
if (filePath.equals("")) {
callbackContext.error("null path passed");
return false;
}
File file = new File(filePath);
Intent scanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
scanIntent.setData(Uri.fromFile(file));
this.cordova.getActivity().startActivity( scanIntent );
callbackContext.success("good");
return true;
} else {
callbackContext.error("invalid action phrase");
}
return false;
} catch(Exception e) {
System.err.println("Exception: " + e.getMessage());
callbackContext.error(e.getMessage());
return false;
}
}
}
I am calling my Java code with this .js code
var Scan = {
createEvent:function (fullPath, successCallback, errorCallback) {
cordova.exec(
successCallback, // success callback function
errorCallback, // error callback function
'Scan', // mapped to our native Java class
'addRemove', // with this action name
[
{
"fullPath":fullPath
}
]
);
}
}
module.exports = Scan;
It's a broadcast action not activity action, you should use the send broadcast method for this kind of action!
http://developer.android.com/reference/android/content/Intent.html#ACTION_MEDIA_SCANNER_SCAN_FILE
This is the wrong line in code " this.cordova.getActivity().startActivity( scanIntent );
"
When accessing firebase via the Java client, I'm seeing the message "close called on closed connection". This is the exact printout I'm seeing when running the following code. It looks like the auth is working, but I'm curious where this message is coming from.
generateToken()...
generateToken() end
close called on closed connection
Succeeded!
using firebase-client-1.0.7.jar
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;
import com.firebase.security.token.TokenGenerator;
import com.firebase.security.token.TokenOptions;
import org.json.JSONObject;
public class TestInput {
public static void main(String[] args) throws Exception {
new Firebase(Constants.FIREBASE_URL).auth(generateToken(), new Firebase.AuthListener() {
public void onAuthError(FirebaseError error) {
System.out.println(" Failed! " + error.getMessage());
}
public void onAuthSuccess(Object authData) {
System.out.println("Succeeded!");
}
public void onAuthRevoked(FirebaseError firebaseError) {
System.out.println("Authentication status was cancelled! " + firebaseError.getMessage());
}
});
}
private static String generateToken() {
System.out.println("generateToken()...");
JSONObject arbitraryPayload = new JSONObject();
TokenGenerator tokenGenerator = new TokenGenerator(Constants.FIREBASE_SECRET);
TokenOptions to = new TokenOptions();
to.setAdmin(true);
to.setDebug(false);
String token = tokenGenerator.createToken(arbitraryPayload, to);
System.out.println("generateToken() end");
return token;
}
}
The message is from the Firebase SDK, if you upgrade to the latest JAR, it will not appear anymore.