Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android push notification Firebase sometimes not sending a notif

I am creating android apps that has push notification feature. my problem is; sometimes my apps was receiving a notif but sometimes not. I have been searching this issue on Google and no one has the same problem. Please I need assistance. Below is my code.

this is a gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.0"
    defaultConfig {
        applicationId "com.example.rusla.manual_notif"
        minSdkVersion 16
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.0.1'
    compile 'com.google.firebase:firebase-messaging:10.0.0'
    testCompile 'junit:junit:4.12'
    compile 'com.mcxiaoke.volley:library:1.0.19'
}


apply plugin: 'com.google.gms.google-services'

this is the manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.rusla.manual_notif">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".RegisterActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name=".MyFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
        </service>


        <service android:name=".FirebaseIDService">
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
            </intent-filter>
        </service>
    </application>

</manifest>

this is my registration token class

package com.example.rusla.manual_notif;

import android.app.ProgressDialog;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.google.firebase.iid.FirebaseInstanceId;

import java.util.HashMap;
import java.util.Map;

public class RegisterActivity extends AppCompatActivity {
    private EditText editTextEmail;
    String REGISTER_URL = "http://192.168.0.7/fcm_server/register.php";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.register_layout);
        Button regBtn = (Button) findViewById(R.id.buttonRegister);
        editTextEmail = (EditText) findViewById(R.id.editTextEmail);
        regBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                // Get token
                String token = FirebaseInstanceId.getInstance().getToken();
                //Finally we need to implement a method to store this unique id to our server
                sendIdToServer(token);
            }
        });
    }

    private void sendIdToServer(final String token) {
        //Creating a progress dialog to show while it is storing the data on server
        final ProgressDialog progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("Registering device...");
        progressDialog.show();

        //getting the email entered
        final String email = editTextEmail.getText().toString().trim();

        //Creating a string request
        StringRequest req = new StringRequest(Request.Method.POST, REGISTER_URL,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        //dismissing the progress dialog
                        progressDialog.dismiss();
                        //if the server returned the string success
                        if (response.trim().equalsIgnoreCase("success")) {
                            //Displaying a success toast
                            Toast.makeText(RegisterActivity.this, "Registered successfully", Toast.LENGTH_SHORT).show();

                        } else {
                            Toast.makeText(RegisterActivity.this, "Choose a different email", Toast.LENGTH_SHORT).show();
                        }
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {

                    }
                }) {
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String, String> params = new HashMap<>();
                //adding parameters to post request as we need to send firebase id and email
                params.put("token", token);
                params.put("email", email);
                return params;
            }
        };

        //Adding the request to the queue
        RequestQueue requestQueue = Volley.newRequestQueue(this);
        requestQueue.add(req);
    }

}

this my Firebase service class

package com.example.rusla.manual_notif;

import android.util.Log;

import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;

public class FirebaseIDService extends FirebaseInstanceIdService {
    private static final String TAG = "FirebaseIDService";

    @Override
    public void onTokenRefresh() {
        // Get updated InstanceID token.
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        Log.d(TAG, "Refreshed token: " + refreshedToken);

        // TODO: Implement this method to send any registration to your app's servers.
        sendRegistrationToServer(refreshedToken);
    }

    private void sendRegistrationToServer(String token) {
        // Add custom implementation, as needed.
    }
}

and this is

package com.example.rusla.manual_notif;

import android.util.Log;

import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

public class MyFirebaseMessagingService extends FirebaseMessagingService {
    private static final String TAG = "FCM Service";
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        // TODO: Handle FCM messages here.
        // If the application is in the foreground handle both data and notification messages here.
        // Also if you intend on generating your own notifications as a result of a received FCM
        // message, here is where that should be initiated.
        Log.d(TAG, "From: " + remoteMessage.getFrom());
        Log.d(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody());
    }
}

and below is my server side php code i use to send notification

<!DOCTYPE html>
<html>
<head>
    <title>Firebase Push Notification</title>
</head>
<style type="text/css">
    html, body {
        height: 100%;
    }

    html {
        display: table;
        margin: auto;
    }

    body {
        display: table-cell;
        vertical-align: middle;
    }
    textarea {
        width: 300px;
        height: 150px;
    }
</style>

<body>
    <?php
    require_once 'database.php';
    $sql = "SELECT * FROM users";
    $result = mysqli_query($conn,$sql);

    ?>
    <?php
    //Displaying a success message when the notification is sent 
    if(isset($_REQUEST['success'])){
        ?>
        <strong>Great!</strong> Your message has been sent successfully...
        <?php
    }
    ?>

    <form action='send.php' method='post'>
        <select name='token'>
            <?php 
            //Traversing trhough all values 
            while($row = mysqli_fetch_array($result)){
            //displaying the values in a dropdown list 
                ?>
                <option value='<?php echo $row['token'];?>'><?php echo $row['email'];?></option>

                <?php
            }
            ?>
        </select><br /><br />
        <textarea name='message'></textarea><br />

        <button>Send Notification</button><br />
    </form>

</body>
</html>

and thi is

<?php 

function send_notification ($tokens, $message)
{
    $url = 'https://fcm.googleapis.com/fcm/send';

    $msg = array
    (
        'body'  => "$message",
        'title'     => "SATPOL PP SDA - SIAP",
        'sound'     => 'default'

        );
    $fields = array
    (
        'registration_ids'  => $tokens,
        'notification'          => $msg
        );


    $headers = array(
        'Authorization:key = AIzaSyAdnDaeFRbG7jD74-yo0R72n7b24Wzsh7k',
        'Content-Type: application/json'
        );

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);  
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
    $result = curl_exec($ch);           
    if ($result === FALSE) {
        die('Curl failed: ' . curl_error($ch));
    }
    curl_close($ch);
    return $result;
}

//Checking post request 
if($_SERVER['REQUEST_METHOD']=='POST'){
    //Geting email and message from the request 
    $tokens[] = $_POST['token'];
    $message = $_POST['message'];
    $message_status = send_notification($tokens, $message);
    $result = json_decode($message_status);

    if($result->success){
        header('Location: sendNotification.php?success');
    }else{
        echo "<pre>";print_r($result);die; 
    }
}else{
    header('Location: sendNotification.php');
}


?>

maybe any someone can recorrect my code so i will give thanks so much..

like image 787
Ruslan Wahyudi Avatar asked Dec 22 '16 02:12

Ruslan Wahyudi


2 Answers

If you are not updating the firebase registration token, there is a possibility that your server sided token has expired. Tokens do update dynamically, so the message never received.

You need to update the token from the device.

From my research it is either that, your payloads sometimes exceed the "4KB" size limit, or there is a bug with firebase which i'd like to doubt.

like image 21
Joe Avatar answered Sep 27 '22 17:09

Joe


I recommend that you use data instead of notification. The data message always load onMessageReceived.

Read how to use data, edit your script (php) to use data instead of notification.

Then, make your own notification like this:

@Override
    public void onMessageReceived(RemoteMessage remoteMessage) {

        // Use data! (:
        if(remoteMessage.getData().size() > 0) {

            if (remoteMessage.getData().get("message") != null) {

                String title = (remoteMessage.getData().get("title") != null) ? remoteMessage.getData().get("title") : "Default Notification Title";
                showNotification(title, remoteMessage.getData().get("message"));

            }

        }

        // When you send notification from the firebase console (avoid it for now. Is still very new)
        if (remoteMessage.getNotification() != null) {

            String title = (remoteMessage.getNotification().getTitle() != null) ? remoteMessage.getNotification().getTitle() : "Default Notification Title";

            showNotification(title, remoteMessage.getNotification().getBody());


        }
    }

private void showNotification(String title, String message){

Intent iNotifi;
iNotifi = new Intent(this, MainActivity.class);
            iNotifi.setAction(Intent.ACTION_MAIN);
            iNotifi.addCategory(Intent.CATEGORY_LAUNCHER);

PendingIntent pi = PendingIntent.getActivity(this, 0, iNotifi, 0);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this);

        builder.setSmallIcon(R.drawable.yourNotificationIcon);
        builder.setTicker(title);
        builder.setContentTitle(title);
        builder.setContentText(message);
builder.setContentIntent(pi);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            int color = ContextCompat.getColor(this, R.color.yourAccentColor);
            builder.setColor(color);
        }

NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        try {
            nm.notify(0, builder.build());
        } catch (Exception e) {
            e.printStackTrace();
        }

}

Add this in your Manifest:

<application...>


<!-- Firebase notification icon -->
        <meta-data android:name="com.google.firebase.messaging.default_notification_icon"
            android:resource="@drawable/yourNotificationIcon" />
        <meta-data android:name="com.google.firebase.messaging.default_notification_color"
            android:resource="@color/yourAccentColor" />

</application>

I hope I've helped (:

like image 86
Arnaldo Avatar answered Sep 27 '22 17:09

Arnaldo