This question already has an answer here:
Firebase Have to upload image twice to get it to display
(1 answer)
Closed 1 year ago.
I'm creating an app for my school project, my coding is not that advanced so I apologise in advance for my bad coding. So I'm trying to get the download Uri, so once the user completes the form with the picture, I can upload the details to realtime database to be used in my other parts of my app.
//I use this code below, I got it from the Firebase documents//
ref.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
// picUri is a globally declared string and I use it to set my database values,
picUri=(uri.toString());
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
// Handle any errors
}
});
I believe it has to do with the fact that Firebase method is asynchronous? So the uri.toString() doesnt get parsed into the global string variable? Because I've been playing around and I realised that when I do the .setValue(object) to write my object to realtime database, the uri does get captured, but that would be too messy and then I wouldnt be able to capture the other values. Ive read around that I need to write a callback, theres alot of guides out there that I've really confused myself here.
Could someone people direct me to a guide or a youtube tutorial on how to understand callbacks and implement a callback to get this value , or issit something else that I'm doing wrong, please advice , thank you.
The photos and the other parameters are being recorded succesfully, its only the picture's uri that I'm unable to capture. (I've temporarily replaced the categoryinput with picUri to run tests easier)
I'm a new user so i cant upload pics but the pic for database and layout is:
https://i.ibb.co/YbdSzwB/databasestack.png
https://i.ibb.co/SVG2zxL/stackoverflow.png
I'll input my entire code just for info
package com.example.giventake;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.*;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.OnProgressListener;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.UploadTask;
import java.io.IOException;
public class ListPage extends AppCompatActivity {
/*Declare all variables I'll be using*/
private EditText title, category, description;
private ImageView image, image2, image3;
private FirebaseAuth mAuth;
private FirebaseStorage storage;
private StorageReference storageReference;
private FirebaseDatabase rootNode;
private DatabaseReference referenceItems;
private Uri filePath;
private Uri filePath2;
private Uri filePath3;
private final int PICK_IMAGE_REQUEST = 1;
private final int PICK_IMAGE2_REQUEST = 2;
private final int PICK_IMAGE3_REQUEST = 3;
String picUri;
/*Declare all variables I'll be using*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
/*Initialise all instances of variables*/
title = (EditText) findViewById(R.id.editTextItemTitle);
category = (EditText) findViewById(R.id.editTextItemCategory);
description = (EditText) findViewById(R.id.editTextItemDescription);
image = (ImageView) findViewById(R.id.imgViewPic);
image2 = (ImageView) findViewById(R.id.imgViewPic2);
image3 = (ImageView) findViewById(R.id.imgViewPic3);
image.setImageResource(R.drawable.ic_baseline_list_24);
image2.setImageResource(R.drawable.ic_baseline_list_24);
image3.setImageResource(R.drawable.ic_baseline_list_24);
storage = FirebaseStorage.getInstance();
storageReference = storage.getReference();
mAuth = FirebaseAuth.getInstance();
rootNode = FirebaseDatabase.getInstance();
referenceItems = rootNode.getReference("Items");
/*Initialise all instances of variables*/
}
/*This is to upload images from your phones direction*/
public void onFirstPicClick(View view) {
Intent i = new Intent();
i.setType("image/*");
i.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(i, "Select Picture"), PICK_IMAGE_REQUEST);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK
&& data != null && data.getData() != null) {
filePath = data.getData();
try {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), filePath);
image.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/*This is to upload images from your phones direction*/
public void onSubmitClicked(View view) {
//Fetching data
String titleInput = title.getText().toString().trim();
//String categoryInput = category.getText().toString().trim();
String descriptionInput = description.getText().toString().trim();
String itemId = referenceItems.child(mAuth.getCurrentUser().getUid()).push().getKey();
referenceItems = referenceItems.child(mAuth.getCurrentUser().getUid()).child(itemId);
if (filePath != null) {
StorageReference ref = storageReference.child("Images").child(mAuth.getCurrentUser().getUid()).child(itemId).child("Pic1");
ref.putFile(filePath)
.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
// Toast.makeText(ListPage.this, "Uploaded", Toast.LENGTH_SHORT).show();
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(ListPage.this, "Picture upload failed" + e.getMessage(), Toast.LENGTH_SHORT).show();
}
})
.addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
#Override
public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
double progress = (100.0 * taskSnapshot.getBytesTransferred() / taskSnapshot
.getTotalByteCount());
}
});
ref.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
// Got the download URL for 'users/me/profile.png'
picUri=(uri.toString());
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
// Handle any errors
}
});
}
//ItemsHelperClass item = new ItemsHelperClass(titleInput, categoryInput, descriptionInput, itemId);
ItemsHelperClass item = new ItemsHelperClass(titleInput,picUri,descriptionInput,itemId);
referenceItems.setValue(item).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Intent i = new Intent(ListPage.this, MainActivity.class);
startActivity(i);
finish();
// getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new HomeFragment()).commit();
} else {
//If it fails to add
Toast.makeText(ListPage.this, "Something went wrong, please try again", Toast.LENGTH_LONG).show();
}
}
}
);
}
}
The Java Firebase Android SDK makes heavy use of Task objects (which are similar to JavaScript Promise objects) where you can chain a number of actions together that need to interact with asynchronous APIs.
A Task object, has many methods to attach listeners, the main ones you'll encounter are:
addOnSuccessListener - When the task completes successfully, run the given code.
addOnFailureListener - When the task fails, run the given code.
addOnCompleteListener - When the task completes (either successfully or has failed), run the given code.
onSuccessTask - When the task completes successfully, start another task.
continueWith - When the task completes (either successfully or has failed), start another task.
Sometimes if you are dealing with multiple tasks at a time, you'll need to make use of methods on the Tasks utility class.
For what you are trying to do, here is a list of the steps you need to take once the user clicks the submit button:
Get the values of any inputs (title, description, category, image file path, etc)
Validate the inputs (make sure each has a value, no invalid characters, etc) and if invalid, show an error.
Create the private references you need: a DatabaseReference and a StorageReference
Upload the image file
If the upload was successful, get a download URL
If getting a download URL was successful, save information to the database.
If any of the tasks in step 4, 5, or 6 fail, show an error.
As this is a school project, I'm not going to dive in any further. Study the links above, and you should be able to combine that knowledge with these steps to find the solution.
However, I will point out this bug that will get you into hot water:
String itemId = referenceItems.child(mAuth.getCurrentUser().getUid()).push().getKey();
referenceItems = referenceItems.child(mAuth.getCurrentUser().getUid()).child(itemId);
You assign to referenceItems here which messes up your code the next time you hit submit and will quickly make your database look like:
{
"Items": {
"-MYu4i_5q-GUETw4WV1i": {
"title": "my first image",
"uri": "https://firebasestorage.googleapis.com/...",
"description": "some description",
"category": "some category",
"-MYu5jNs2MMJJGB2L7jJ": {
"title": "my second image",
"uri": "https://firebasestorage.googleapis.com/...",
"description": "some description",
"category": "some category",
"-MYu72gLxsi4M6J9aBAr": {
"title": "my third image",
"uri": "https://firebasestorage.googleapis.com/...",
"description": "some description",
"category": "some category",
"-MYu78gFeoWhV6OSiF9I": ...
}
}
}
}
}
or, if you had a syntax error rather than a successful upload, you might end up with:
{
"Items": {
"-MYu4i_5q-GUETw4WV1i": {
"-MYu5jNs2MMJJGB2L7jJ": {
"-MYu72gLxsi4M6J9aBAr": {
"title": "my first image",
"uri": "https://firebasestorage.googleapis.com/...",
"description": "some description",
"category": "some category"
}
}
}
}
}
Instead, save and use the reference returned by push():
DatabaseReference itemDataRef = referenceItems.child(mAuth.getCurrentUser().getUid()).push();
String itemId = itemDataRef.getKey();
/* ... */
StorageReference itemStorageRef = storageReference.child("Images").child(mAuth.getCurrentUser().getUid()).child(itemId).child("Pic1");
Related
I'm trying to create Android Application using Android Studio and firebase. I connected my app to firebase and was trying to use Realtime database. Everything have seemed fine until I realized, that firebase was not creating any tables in the Realtime database. Authentication works without any problems and I can see the registered users on the Authentication Page on Firebase website. What's more, I can even use their data to log into application and everything works as it should. I guess, that if something However, nothing new appears in Realtime database. No Users table is created.
Realtime database rules:
{
"rules": {
".read": "true",
".write": "true"
}
}
RegisterUser Activity, which sends data to Firebase Realtime Database:
package com.kalarus.kaluzinski.kaczor;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Patterns;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.FirebaseDatabase;
public class RegisterUser extends AppCompatActivity implements View.OnClickListener{
private TextView banner;
private Button registerUserButton;
private EditText editTextFullNameRegisterPage, editTextAgeRegisterPage ,editTextEmailRegisterPage, editTextPasswordRegisterPage;
private ProgressBar progressBarRegisterPage;
private FirebaseAuth kinoAuth;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register_user);
kinoAuth = FirebaseAuth.getInstance();
banner = (TextView) findViewById(R.id.banner);
banner.setOnClickListener(this);
registerUserButton = (Button) findViewById(R.id.registerUserButton);
registerUserButton.setOnClickListener(this);
editTextFullNameRegisterPage = (EditText) findViewById(R.id.editTextFullNameRegisterPage);
editTextAgeRegisterPage = (EditText) findViewById(R.id.editTextAgeRegisterPage);
editTextEmailRegisterPage = (EditText) findViewById(R.id.editTextEmailRegisterPage);
editTextPasswordRegisterPage = (EditText) findViewById(R.id.editTextPasswordRegisterPage);
progressBarRegisterPage = (ProgressBar) findViewById(R.id.progressBarRegisterPage);
progressBarRegisterPage.setVisibility(View.INVISIBLE);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.banner:
startActivity(new Intent(this, LoginPage.class));
break;
case R.id.registerUserButton:
registerUser();
break;
}
}
private void registerUser()
{
String email = editTextEmailRegisterPage.getText().toString().trim();
String password = editTextPasswordRegisterPage.getText().toString().trim();
String fullName = editTextFullNameRegisterPage.getText().toString().trim();
String age = editTextAgeRegisterPage.getText().toString().trim();
if(fullName.isEmpty())
{
editTextFullNameRegisterPage.setError("Full name is required!");
editTextFullNameRegisterPage.requestFocus();
return;
}
if(age.isEmpty())
{
editTextAgeRegisterPage.setError("Age is required!");
editTextAgeRegisterPage.requestFocus();
return;
}
if(email.isEmpty())
{
editTextEmailRegisterPage.setError("Email is required!");
editTextEmailRegisterPage.requestFocus();
return;
}
if(!Patterns.EMAIL_ADDRESS.matcher(email).matches())
{
editTextEmailRegisterPage.setError("Please provide valid email!");
editTextEmailRegisterPage.requestFocus();
return;
}
if(password.isEmpty())
{
editTextPasswordRegisterPage.setError("Password is required!");
editTextPasswordRegisterPage.requestFocus();
return;
}
if(password.length() < 6)
{
editTextPasswordRegisterPage.setError("Min password length should be 6 characters!");
editTextPasswordRegisterPage.requestFocus();
return;
}
progressBarRegisterPage.setVisibility(View.VISIBLE);
kinoAuth.createUserWithEmailAndPassword(email, password).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if(task.isSuccessful())
{
User user = new User(fullName, age, email);
FirebaseDatabase.getInstance().getReferenceFromUrl("https://console.firebase.google.com/project/kino-fcff3/database/kino-fcff3-default-rtdb/data/~2F")
.child(FirebaseAuth.getInstance().getCurrentUser().getUid())
.setValue(user).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful())
{
Toast.makeText(RegisterUser.this, "User has been registered successfully!", Toast.LENGTH_LONG).show();
progressBarRegisterPage.setVisibility(View.INVISIBLE);
}
else
{
Toast.makeText(RegisterUser.this, "Failed to register! Try again!", Toast.LENGTH_LONG).show();
progressBarRegisterPage.setVisibility(View.INVISIBLE);
}
}
});
}
else
{
Toast.makeText(RegisterUser.this, "Failed to register! Try again!", Toast.LENGTH_LONG).show();
progressBarRegisterPage.setVisibility(View.INVISIBLE);
}
}
});
}
}
User data is stored in User class:
package com.kalarus.kaluzinski.kaczor;
public class User {
public String fullName, age, email;
public User() {
}
public User(String fullName, String age, String email) {
this.fullName = fullName;
this.age = age;
this.email = email;
}
}
I tried many solutions, that I've found on the Internet but none of them solved the issue. Things I've done:
created new realtime database in firebase
enabled email/password authentication in firebase
changed the rules of realtime database to "true"
connected Android Studio project to Firebase and added appropriate SDKs (Authentication SDKs and realtime database SDKs)
checked if gradle is using appropriate dependencies
redownloaded google-services.json file and replaced the one in a project
created new clean project and connected it to firebase realtime database
The URL in getReferenceFromUrl() seems to be the problem. You are passing the console's URL instead of database URL. Try using getReference() instead:
FirebaseDatabase.getInstance().getReference()
.child("data")
.child(FirebaseAuth.getInstance().getCurrentUser().getUid())
.setValue(...)
If you want to use getReferenceFromUrl() then the URL must be:
https://<project_id><db-name?>.europe-west1.firebasedatabase.app/data
The domain might differ based on the database location but you can check the URL in console here followed by the path:
I am using data messages where we can send messages even when the app is killed or in background or in foreground. I am using FCM .
But in my case sometimes my app does not get those messages . I am sending messages from app to app. Sometimes the app get messages even when it is killed or removed from background but again , sometimes it wont.
When i open the app , then suddenly the message appears. I am opening activities when a particular message is received . I know that data messages are used for sending messages even when the app is killed or in background or in foreground , but i am having problem like this . please help !..
I want it to be absolute .
I just want my app to be connected to FirebaseMessagingServices always , even when it is killed. I don't know about services and some says that i need to create a foreground services . How to create it and implement to FirebaseMessagingServices .?
MYFirebaseMessaging.java
package com.example.praful.ubercoustomer.Service;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.RequiresApi;
import android.support.v4.app.NotificationCompat;
import android.widget.Toast;
import com.example.praful.ubercoustomer.AcceptedWindow;
import com.example.praful.ubercoustomer.Common.Common;
import com.example.praful.ubercoustomer.CompanycancelledtheBooking;
import com.example.praful.ubercoustomer.DeclinedWindow;
import com.example.praful.ubercoustomer.Helper.NotificationHelper;
import com.example.praful.ubercoustomer.Onthewayandimreached;
import com.example.praful.ubercoustomer.R;
import com.example.praful.ubercoustomer.RateActivity;
import com.example.praful.ubercoustomer.VerifyingCompletedBooking;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import java.util.Map;
public class MyFirebaseMessaging extends FirebaseMessagingService {
#Override
public void onMessageReceived(final RemoteMessage remoteMessage) {
if (remoteMessage.getData() != null) {
Map<String, String> data = remoteMessage.getData();
String title = data.get("title");
final String companyName = data.get("CompanyName");
final String BookingIdC = data.get("BookingIdC");
final String BookingIdT = data.get("BookingIdT");
final String companyPhone = data.get("CompanyPhone");
final String companyRates = data.get("CompanyRates");
final String companyId = data.get("CompanyId");
final String Date = data.get("Date");
final String companyIdC = data.get("companyIdC");
final String Time = data.get("Time");
final String Id = data.get("Id");
final String Address = data.get("Address");
final String Bookingid = data.get("Bookingid");
final String TimeCB = data.get("TimeCB");
final String DateCB = data.get("DateCB");
final String EventType = data.get("EventType");
final String messageCB = data.get("messageCB");
final String AddressCB = data.get("AddressCB");
final String companythatcancelledthebooking = data.get("CompanyNamethatcancelledthebooking");
final String message = data.get("message");
// remoteMessage.getNotification().getTitle() = title and remoteMessage.getNotification().getBody() = message
if (title != null && title.equals("Cancel")) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(MyFirebaseMessaging.this, DeclinedWindow.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Common.isCompanyFound = false;
Common.companyId = "";
Toast.makeText(MyFirebaseMessaging.this, "" + message, Toast.LENGTH_SHORT).show();
}
});
} else if (title != null && title.equals("cancelAdvanceBooking")) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(getBaseContext(), CompanycancelledtheBooking.class);
intent.putExtra("DateCB", DateCB);
intent.putExtra("TimeCB", TimeCB);
intent.putExtra("messageCB", messageCB);
intent.putExtra("AddressCB", AddressCB);
intent.putExtra("EventType", EventType);
intent.putExtra("Id", Id);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Common.isCompanyFound = false;
Common.companyId = "";
Toast.makeText(MyFirebaseMessaging.this, "" + messageCB, Toast.LENGTH_SHORT).show();
}
});
} else if (title != null && title.equals("Accept")) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(MyFirebaseMessaging.this, AcceptedWindow.class);
intent.putExtra("Date", Date);
intent.putExtra("Time", Time);
intent.putExtra("Address", Address);
intent.putExtra("companyName", companyName);
intent.putExtra("companyPhone", companyPhone);
intent.putExtra("companyRates", companyRates);
intent.putExtra("companyId", companyId);
intent.putExtra("Bookingid", Bookingid);
intent.putExtra("EventType", EventType);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Common.isCompanyFound = false;
Common.companyId = "";
Toast.makeText(MyFirebaseMessaging.this, "" + message, Toast.LENGTH_SHORT).show();
}
});
} else if (title != null && title.equals("Arrived")) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
showArrivedNotifAPI26(message);
else
showArrivedNotif(message);
}
});
} else if (title != null && title.equals("Completed")) {
openRateactivity(message);
} else if (title != null && title.equals("completedAdvancebooking")) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(MyFirebaseMessaging.this, VerifyingCompletedBooking.class);
intent.putExtra("BookingIdC", BookingIdC);
intent.putExtra("message", message);
intent.putExtra("companyid", companyIdC);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
});
} else if (title != null && title.equals("Ontheway")) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(MyFirebaseMessaging.this, Onthewayandimreached.class);
intent.putExtra("message", message);
intent.putExtra("BookingIdT", BookingIdT);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
});
} else if (title != null && title.equals("Reached")) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(MyFirebaseMessaging.this, Onthewayandimreached.class);
intent.putExtra("message", message);
intent.putExtra("BookingIdT", BookingIdT);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
});
}
}
}
#RequiresApi(api = Build.VERSION_CODES.O)
private void showArrivedNotifAPI26(String body) {
PendingIntent contentIntent = PendingIntent.getActivity(getBaseContext(), 0,
new Intent(), PendingIntent.FLAG_ONE_SHOT);
Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationHelper notificationHelper = new NotificationHelper(getBaseContext());
Notification.Builder builder = notificationHelper.getUberNotification("Arrived", body, contentIntent, defaultSound);
notificationHelper.getManager().notify(1, builder.build());
}
private void openRateactivity(String body) {
Intent intent = new Intent(this, RateActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
private void showArrivedNotif(String body) {
PendingIntent contentIntent = PendingIntent.getActivity(getBaseContext(), 0,
new Intent(), PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(getBaseContext());
builder.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND)
.setWhen(System.currentTimeMillis()).
setSmallIcon(R.drawable.ic_menu_camera)
.setContentTitle("Arrived")
.setContentText(body)
.setContentIntent(contentIntent);
NotificationManager manager = (NotificationManager) getBaseContext().getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(1, builder.build());
}
}
MyFirebaseIdService
package com.example.praful.ubercoustomer.Service;
import com.example.praful.ubercoustomer.Common.Common;
import com.example.praful.ubercoustomer.Model.Token;
import com.example.praful.ubercoustomer.Common.Common;
import com.example.praful.ubercoustomer.Model.Token;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
public class MyFirebaseIdService extends FirebaseInstanceIdService {
#Override
public void onTokenRefresh() {
super.onTokenRefresh();
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
updateTokenToServer(refreshedToken);
}
private void updateTokenToServer(String refreshedToken) {
FirebaseDatabase db =FirebaseDatabase.getInstance();
DatabaseReference tokens = db.getReference(Common.token_table);
Token token = new Token(refreshedToken);
if(FirebaseAuth.getInstance().getCurrentUser() != null)
tokens.child(FirebaseAuth.getInstance().getCurrentUser().getUid()).setValue(token);
}
}
First check this remote message contains payload, May be payload get corrupt for any reason.
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "REMOTE_MSG";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
if (remoteMessage == null)
return;
// check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.e(TAG, "Notification body: " + remoteMessage.getNotification().getBody());
createNotification(remoteMessage.getNotification());
}
// check if message contains a data payload
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
}
}
DON'T forgent to update your FCM device token on your DB.
public class MyFirebaseInstanceIdService extends FirebaseInstanceIdService {
private static final String TAG = "FCM_ID";
#Override
public void onTokenRefresh() {
// get hold of the registration token
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
// lg the token
Log.d(TAG, "Refreshed token: " + refreshedToken);
sendRegistrationToServer(refreshedToken);
}
private void sendRegistrationToServer(String token) {
// implement this method if you want to store the token on your server
}
}
Update 1
As mentioned Firebase repo issue expected that issue to be related to device, Please try another device aspect.
Update 2 Quote from firebase repo contributor kroikie
FCM does not process messages if an app is "killed" or force stopped.
When a user kills an app it is an indication that the user does not
want the app running so that app should not run till the user
explicitly starts it again.
Note that swiping an app from recents list should NOT "kill" or force
stop it. If messages are not being received after swiping from recents
list then please identify these devices and we will work with the
manufactures to correct this behaviour.
Only being able to handle messages when the app is in the foreground
or background is working as intended.
Update 3
Try hacks mentioned on this issue.
Inserting this lines in Manifest.xml
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
It is because of DOZE mode and battery optimization,you just have to turn off battery optimization for all apps or particular app. Go to Settings>> apps >> select your app>> battery>>
battery optimization> select your app>> select don't optimise.
Problem solved.
Now (for APP IS CLOSED case) I write Notification text to file and read this text if extras == null and notificationText.txt is exists... its stupid solution but it works. How can I catch this extras when app is closed in other way.
Update 4
Try to Setting the priority of a message,
Disable Battery Optimization
Users can manually configure the whitelist in Settings > Battery >
Battery Optimization. Alternatively, the system provides ways for apps
to ask users to whitelist them.
An app can fire the ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS intent
to take the user directly to the Battery Optimization, where they can
add the app. An app holding the REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
permission can trigger a system dialog to let the user add the app to
the whitelist directly, without going to settings. The app fires a
ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS Intent to trigger the
dialog. The user can manually remove apps from the whitelist as
needed.
Programmatically open Battery Optimization, check this answer.
TAKE CARE ABOUT THIS
Before asking the user to add your app to the whitelist, make sure the
app matches the acceptable use cases for whitelisting.
Note:
Google Play policies prohibit apps from requesting direct exemption from
Power Management features in Android 6.0+ (Doze and App Standby)
unless the core function of the app is adversely affected.
Update 5
Check PowerManager.isIgnoringBatteryOptimizations() from this answer.
When disable battery optimization, Consider to check first if it's already disabled then no need to show dialog, else you can show dialog.
/**
* return false if in settings "Not optimized" and true if "Optimizing battery use"
*/
private boolean checkBatteryOptimized() {
final PowerManager pwrm = (PowerManager) getSystemService(Context.POWER_SERVICE);
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return !pwrm.isIgnoringBatteryOptimizations(getBaseContext().getPackageName());
}
}catch (Exception ignored){}
return false;
}
private void startBatteryOptimizeDialog(){
try {
Intent intent = new Intent(android.provider.Settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:PUT_YOUR_PACKAGE_NAME_HERE"));
startActivity(intent);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
}
}
I was going through a tutorial to create a voice recorder which will then upload the recording to Firebase. I watched the tutorial many times and made sure the app is connected to Firebase; however, the app will not open right now most likely due to this issue. I'm pretty new to Java programming. Can someone please provide me with some guidance? Thank you
package bfb.ess.myapplicationbfb;
import android.app.ProgressDialog;
import android.media.MediaRecorder;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.UploadTask;
import java.io.File;
import java.io.IOException;
public class speakp extends AppCompatActivity {
private Button mRecordBtn;
private TextView mRecordlabel;
private MediaRecorder mRecorder;
private String mFileName = null;
private static final String LOG_TAG = "Record_log";
private StorageReference mStorage;
private ProgressDialog mProgress;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recordpage);
mStorage = FirebaseStorage.getInstance().getReference();
mRecordlabel = (TextView) findViewById(R.id.recordlabel);
mRecordBtn =(Button) findViewById(R.id.recordBtn);
mProgress = new ProgressDialog(this);
mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
mFileName +="/recorded_audio.3gp";
mRecordBtn.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if(motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
startRecording();
mRecordlabel.setText("Recording Started ...");
} else if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
stopRecording();
mRecordlabel.setText("Recording Stopped ...");
}
return false;
}
});
}
private void startRecording() {
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setOutputFile(mFileName);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
mRecorder.prepare();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
mRecorder.start();
}
private void stopRecording() {
mRecorder.stop();
mRecorder.release();
mRecorder = null;
uploadAudio();
}
private void uploadAudio() {
mProgress.setMessage("Uploading Audio ...");
mProgress.show();
StorageReference filepath = mStorage.child("Audio").child("new_audio.3gp");
Uri uri = Uri.fromFile(new File(mFileName));
filepath.putFile(uri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
mProgress.dismiss();
mRecordlabel.setText("Uploading Finished");
}
});
}
}
Go to Firebase console and update read and write rules for storage
You can look into the Google Firebase Sample: Storage Sample
Please check the URI of audio file if its proper. Because I guess lastPathSegment of uri is getting faulty.
By Default:
service firebase.storage {
match /b/<name_of_app>/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
Update it to:
service firebase.storage {
match /b/<name_of_app>/o {
match /{allPaths=**} {
allow read;
allow write;
}
}
}
NOTE:
This update will allow you to store the data even if you are not authorised.
It is only for development purpose because it can cause security issue of accessing the data without getting authorised.
So take care when uploading the app to play store, update this parameter and change according to your requirement.
You need to update the read and write rules for storage in your firebase console,
Go to Firebase console, select storage
Click on the Rules tab
By Default:
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
Change to:
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write;
}
}
}
as Mohom.R said
NOTE: This update will allow you to store the data even if you are not authorised. It is only for development purpose because it can cause security issue of accessing the data without getting authorised. So take care when uploading the app to play store, update this parameter and change according to your requirement.
I have image steganography app for android. The main function of this app have worked well, such as encoding, decoding, and save images in phone storage.
But, I want a picture that has been inserted a secret message can be shared with other app like Whatsapp, Facebook, Twitter. After I try to make the share button and click the button, I was not given a choice application where I will share those images.
However, I was directed to the MMS message. although the MMS message can work well, but I want to be able to choose the app where I will share images.
This is a part of encoding code where assosiated with share button :
Button buttonShare = (Button) findViewById(R.id.share);
buttonShare.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
closeContextMenu();
closeOptionsMenu();
progressBar=new MobiProgressBar(EncodeActivity.this);
progressBar.setMax(100);
progressBar.setMessage(context.getString(R.string.encoding));
progressBar.show();
Thread tt = new Thread(new Runnable() {
public void run() {
Uri uri= encode();
ShareIntent share=new ShareIntent(uri,EncodeActivity.this);
progressBar.dismiss();
share.send();
}
});
tt.start();
}
});
And this code for share method :
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
public class ShareIntent {
private Uri uri;
private final Context context;
public Uri getUri() {
return uri;
}
public void setUri(Uri uri) {
this.uri = uri;
}
public ShareIntent(Uri uri,Context context) {
this.uri = uri;
this.context=context;
}
public void send()
{
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM,uri);
shareIntent.setType("image/jpeg");
context.startActivity(Intent.createChooser(shareIntent, "Share Image"));
}
}
Thank you!!
I am trying to develop an app where the user takes a photo and uploads it to Google Drive automatically (The image is not saved on the phone). I figured out the code for that thanks to a Google Drive tutorial, but I have no idea how I would do that when it comes to upload videoes?
Here is the code for photo uploading:
package com.google.android.gms.drive.sample.quickstart;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import android.app.Activity;
import android.content.Intent;
import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.drive.Drive;
import com.google.android.gms.drive.DriveApi.DriveContentsResult;
import com.google.android.gms.drive.MetadataChangeSet;
/**
* Android Drive Quickstart activity. This activity takes a photo and saves it
* in Google Drive. The user is prompted with a pre-made dialog which allows
* them to choose the file location.
*/
public class VideoCapture extends Activity implements ConnectionCallbacks,
OnConnectionFailedListener {
private static final String TAG = "drive-quickstart";
private static final int REQUEST_CODE_CAPTURE_VIDEO = 1;
private static final int REQUEST_CODE_CREATOR = 2;
private static final int REQUEST_CODE_RESOLUTION = 3;
private GoogleApiClient mGoogleApiClient;
private Byte mVideoToSave;
/**
* Create a new file and save it to Drive.
*/
private void saveFileToDrive() {
// Start by creating a new contents, and setting a callback.
Log.i(TAG, "Creating new contents.");
final Byte video = mVideoToSave;
Drive.DriveApi.newDriveContents(mGoogleApiClient)
.setResultCallback(new ResultCallback<DriveContentsResult>() {
#Override
public void onResult(DriveContentsResult result) {
// If the operation was not successful, we cannot do anything
// and must
// fail.
if (!result.getStatus().isSuccess()) {
Log.i(TAG, "Failed to create new contents.");
return;
}
// Otherwise, we can write our data to the new contents.
Log.i(TAG, "New contents created.");
// Get an output stream for the contents.
OutputStream outputStream = result.getDriveContents().getOutputStream();
// Write the bitmap data from it.
ByteArrayOutputStream mBAOS = new ByteArrayOutputStream();
byte[] mByte = new byte[1024];
try {
outputStream.write(mBAOS.toByteArray());
} catch (IOException e1) {
Log.i(TAG, "Unable to write file contents.");
}
// Create the initial metadata - MIME type and title.
// Note that the user will be able to change the title later.
MetadataChangeSet metadataChangeSet = new MetadataChangeSet.Builder()
.setMimeType("video/mp4").setTitle("Android Video.mp4").build();
// Create an intent for the file chooser, and start it.
IntentSender intentSender = Drive.DriveApi
.newCreateFileActivityBuilder()
.setInitialMetadata(metadataChangeSet)
.setInitialDriveContents(result.getDriveContents())
.build(mGoogleApiClient);
try {
startIntentSenderForResult(
intentSender, REQUEST_CODE_CREATOR, null, 0, 0, 0);
} catch (SendIntentException e) {
Log.i(TAG, "Failed to launch file chooser.");
}
}
});
}
#Override
protected void onResume() {
super.onResume();
if (mGoogleApiClient == null) {
// Create the API client and bind it to an instance variable.
// We use this instance as the callback for connection and connection
// failures.
// Since no account name is passed, the user is prompted to choose.
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
// Connect the client. Once connected, the camera is launched.
mGoogleApiClient.connect();
}
#Override
protected void onPause() {
if (mGoogleApiClient != null) {
mGoogleApiClient.disconnect();
}
super.onPause();
}
#Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
switch (requestCode) {
case REQUEST_CODE_CAPTURE_VIDEO:
// Called after a photo has been taken.
if (resultCode == Activity.RESULT_OK) {
// Store the image data as a bitmap for writing later.
mVideoToSave = (Byte) data.getExtras().get("data");
}
break;
case REQUEST_CODE_CREATOR:
// Called after a file is saved to Drive.
if (resultCode == RESULT_OK) {
Log.i(TAG, "Image successfully saved.");
mVideoToSave = null;
// Just start the camera again for another photo.
startActivityForResult(new Intent(MediaStore.ACTION_VIDEO_CAPTURE),
REQUEST_CODE_CAPTURE_VIDEO);
}
break;
}
}
#Override
public void onConnectionFailed(ConnectionResult result) {
// Called whenever the API client fails to connect.
Log.i(TAG, "GoogleApiClient connection failed: " + result.toString());
if (!result.hasResolution()) {
// show the localized error dialog.
GoogleApiAvailability.getInstance().getErrorDialog(this, result.getErrorCode(), 0).show();
return;
}
// The failure has a resolution. Resolve it.
// Called typically when the app is not yet authorized, and an
// authorization
// dialog is displayed to the user.
try {
result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);
} catch (SendIntentException e) {
Log.e(TAG, "Exception while starting resolution activity", e);
}
}
#Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "API client connected.");
if (mVideoToSave == null) {
// This activity has no UI of its own. Just start the camera.
startActivityForResult(new Intent(MediaStore.ACTION_VIDEO_CAPTURE),
REQUEST_CODE_CAPTURE_VIDEO);
return;
}
saveFileToDrive();
}
#Override
public void onConnectionSuspended(int cause) {
Log.i(TAG, "GoogleApiClient connection suspended");
}
}