0

I have problem that sometimes my app(background) not receive notification. I need to restart application then run notification.php after that notification will appear.

I don't know if im handle notification data message is wrong. But i already added click_action"=>".EventDetailsActivity" at notification.php file, handle the intent at EventDetailsActivity.java and intent-filter tag at AndroidManifest.xml

<intent-filter>
            <action android:name=".EventDetailsActivity" />
            <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

I hope you guys can help me solve this problem. Thanks you in advance.

Notification.php

<?php

require "../../init.php";
include("../../function_lib.php");

$id  = $_GET['id'];
$title_reminder = $_GET['title_reminder'];


$title = "[MSAS] upcoming program";
$message = $title_reminder;
$path_to_fcm = "https://fcm.googleapis.com/fcm/send"; //send push notification through this firebase url
$server_key = "####";

$topic = "/topics/reminder";
$type = "reminder";



//create http request to firease server
//request need 2 section : 1.header section 2. payload section
//add push notification in payload section

//header section for http request : that content authorization key and content_type of this application

//below are the header section of the http request
$headers = array(
            'Authorization:key='.$server_key,
            'Content-Type:application/json'
        );





$field = array('to'=>$topic,'notification'=>array("title"=>$title,"text"=>$message,"click_action"=>".EventDetailsActivity"),
                'data'=>array('title'=>$title,'body'=>$message,'type'=>$type,'id'=>$id),'priority'=>"high");

//echo "\n".$key;
// to = refer to fcm token, notification refer to message that wull be use in push notification.
///below are the payload section.

/*
$field = array('to'=>$topic,
                'data'=>array('title'=>$title,'body'=>$message,'type'=>$type,'id'=>$id));
*/
//perform json encode
$payload = json_encode($field);


//pass $payload (content json encode) variable to firebase server

//below  gonna start url section.gonna use firebase url http to send json to firebase server.
$curl_session = curl_init();
curl_setopt($curl_session,CURLOPT_URL, $path_to_fcm);
curl_setopt($curl_session,CURLOPT_POST,true);
curl_setopt($curl_session,CURLOPT_HTTPHEADER,$headers);
curl_setopt($curl_session,CURLOPT_RETURNTRANSFER,true); 
curl_setopt($curl_session,CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl_session,CURLOPT_IPRESOLVE,CURL_IPRESOLVE_V4);
curl_setopt($curl_session,CURLOPT_POSTFIELDS, $payload);

//execute curl
$result = curl_exec($curl_session);

//close curl
curl_close($curl_session);

//close  mysqli
//mysql_close($conn);


$path = "../dashboard.php?act=home";
echo ('<script>location.href="'.$path.'"</script>');

?>

AndroidManifest.xml

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

    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/icon_logo_only"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">


        <service android:name=".firebase.FcmInstanceIdService">
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
            </intent-filter>
        </service>
        <service android:name=".firebase.FcmMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>

        <activity android:name=".ScreenActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".fragment.MainActivity">
            <intent-filter>
                <action android:name=".fragment.MainActivity" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
        <activity android:name=".EventDetailsActivity">
            <intent-filter>
                <action android:name=".EventDetailsActivity" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

    </application>

EventDetailsActivity.java

public class EventDetailsActivity extends AppCompatActivity {

    Toolbar toolbar;
    TextView textViewTitle,textViewDate,textViewTime,textViewLocation,textViewDescription;
    //NetworkImageView networkImageViewEvent;
    Animation animation;
    String send_id_to_server;
    ImageView imageViewEvent;
    //ImageLoader imageLoader;
    Event event;
    Context context;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_event_details);

        this.context = getApplicationContext();

        textViewTitle = (TextView) findViewById(R.id.event_details_title_id);
        textViewDate = (TextView) findViewById(R.id.event_details_date_id);
        textViewDescription = (TextView) findViewById(R.id.event_details_description_id);
        textViewLocation = (TextView) findViewById(R.id.event_details_location_id);
        textViewTime = (TextView) findViewById(R.id.event_details_time_id);
        //networkImageViewEvent = (NetworkImageView) findViewById(R.id.event_details_image_id);
        imageViewEvent = (ImageView) findViewById(R.id.event_details_image_id);
        toolbar = (Toolbar) findViewById(R.id.toolbar__details_top);

        //add toolbar
        setSupportActionBar(toolbar);
        //hide default Title Text
        getSupportActionBar().setDisplayShowTitleEnabled(false);

        //get data from intent
        getDataFromIntent();

        //handleNotificationFromBackground();



        //set each value to component
        setupValueEachComponent();

        //set animation
        //setAnimation();
    }


    //get data from intent
    public void getDataFromIntent(){

        Bundle bundle = getIntent().getExtras();
        //event =  bundle.getParcelable("eventDetails");

        if(bundle.getParcelable("eventDetails") != null){
            //go here if user from main_activity.java
            event =  bundle.getParcelable("eventDetails");

        }else if(bundle.getString("id") != null){


            // will go here if intent from notification (background/foreground)
            event = new Event();
            send_id_to_server = bundle.getString("id");
            requestDataFromServer();
        }

    }



    public void requestDataFromServer(){
        StringRequest stringRequest = new StringRequest(Request.Method.POST, Config.URL_PATH_REMINDER, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                try {
                    JSONArray jsonArray = new JSONArray(response);
                    JSONObject jsonObject = jsonArray.getJSONObject(0);

                    event.setId(jsonObject.getString("id"));
                    event.setTitle(jsonObject.getString("title"));
                    event.setDate(jsonObject.getString("date"));
                    event.setTime(jsonObject.getString("time"));
                    event.setPlace(jsonObject.getString("location"));
                    event.setImage_path(Config.URL_PATH_IMAGE+jsonObject.getString("image_path"));
                    event.setDescription(jsonObject.getString("description"));

                    setupValueEachComponent();

                } catch (JSONException e) {
                    e.printStackTrace();
                }

            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Toast.makeText(EventDetailsActivity.this,"Reminder function error..",Toast.LENGTH_SHORT).show();
                error.printStackTrace();
            }
        }){

            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String,String> params = new HashMap<String,String>();
                params.put("id",send_id_to_server);
                return params;            }
        };

        MySingleton.getmInstances(EventDetailsActivity.this).addRequestQueue(stringRequest);
    }

    public void setupValueEachComponent(){
        textViewTime.setText(event.getTime());
        textViewDescription.setText(event.getDescription());
        textViewDate.setText(event.getDate());
        textViewTitle.setText(event.getTitle());
        textViewLocation.setText(event.getPlace());


        Picasso.with(this).load(event.getImage_path()).into(imageViewEvent);


        imageViewEvent.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Bundle bundle = new Bundle();
                bundle.putString("url",event.getImage_path());
                FragmentManager fm = getSupportFragmentManager();
                ImageZoomDialog imageZoomDialog = new ImageZoomDialog();
                imageZoomDialog.setArguments(bundle);
                imageZoomDialog.show(fm,"open fragment");
            }
        });

    }


    public void setAnimation(){
        //initialize animation
        animation = AnimationUtils.loadAnimation(this,R.anim.shake);

        //start animation
        imageViewEvent.setAnimation(animation);
    }


}

FcmMessagingService.java

public class FcmMessagingService extends FirebaseMessagingService {

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    //if want to use function below need to used change data to notification at $field at server side.
    //String message = remoteMessage.getNotification().getBody();
    //String title = remoteMessage.getNotification().getTitle();

    if(remoteMessage.getData().size()>0){
        Log.i("notification",""+remoteMessage.getData());
        startNotification(remoteMessage);
    }else{
        Log.i("notification",""+remoteMessage.getData());
    }

}





public void startNotification(RemoteMessage remoteMessage){
    String title = remoteMessage.getData().get("title");
    String messsge = remoteMessage.getData().get("body");
    String type = remoteMessage.getData().get("type");
    String id = remoteMessage.getData().get("id");


    Log.i("notification","active");
    //Log.i("Notificaition","type:"+type);
    //Log.i("Notificaition","id:"+id);

    //check if notification eihter is reminder or new quote/event
    if (!type.equals("reminder") && id.equals("none")) {

        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);

        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this);
        notificationBuilder.setContentTitle(title);
        notificationBuilder.setContentText(messsge);
        notificationBuilder.setSmallIcon(R.drawable.icon_no_bg);
        notificationBuilder.setAutoCancel(true);
        notificationBuilder.setContentIntent(pendingIntent);

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0, notificationBuilder.build());
        //super.onMessageReceived(remoteMessage);
    }else

    if(type.equals("reminder") && ! id.equals("none")) {

        Intent intent = new Intent(this, EventDetailsActivity.class);
        intent.putExtra("id",id);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);

        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this);
        notificationBuilder.setContentTitle(title);
        notificationBuilder.setContentText(messsge);
        notificationBuilder.setSmallIcon(R.drawable.icon_logo_only);
        notificationBuilder.setAutoCancel(true);
        notificationBuilder.setContentIntent(pendingIntent);

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0, notificationBuilder.build());
    }

}

}

khoi
  • 940
  • 1
  • 14
  • 29
  • Not too sure about the Android part, but have you subscribed to the topic on the mobile app? https://firebase.google.com/docs/cloud-messaging/android/topic-messaging – Lionel Chan Jan 22 '18 at 09:51
  • I have subscribed the topic.Added difference file. – khoi Jan 22 '18 at 09:52

3 Answers3

0

Do not use notification key in the json payload. Try this instead?

$field = array(
    'to' => $topic,
    'data' => array(
        'title' => $title,
        'body' => $message,
        'type' => $type,
        'id' => $id,
        'click_action' => '.EventDetailsActivity'
    ),
    'priority' => 'high'
);

Reason being, when both notification and data key are used, it is considered as notification message. A notification message only works in the foreground. This is the comment in the android sample:

There are two types of messages data messages and notification messages. Data messages are handled here in onMessageReceived whether the app is in the foreground or background. Data messages are the type traditionally used with GCM. Notification messages are only received here in onMessageReceived when the app is in the foreground. When the app is in the background an automatically generated notification is displayed. When the user taps on the notification they are returned to the app. Messages containing both notification and data payloads are treated as notification messages. The Firebase console always sends notification messages. For more see: https://firebase.google.com/docs/cloud-messaging/concept-options

See this similar question: How to handle notification when app in background in Firebase

Lionel Chan
  • 7,894
  • 5
  • 40
  • 69
  • I already replace the code,but still not working.after 30 minute, apps not received notification after trigger notification.php – khoi Jan 22 '18 at 15:51
0

I have faced the same issue when I kill my app. This code help to resolve this issue.

Add receiver in Manifest.xml

<uses-permission android:name="android.permission.WAKE_LOCK" />
<receiver android:name=".OnBootBroadcastReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
</receiver>

OnBootBroadcastReceiver.class

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class OnBootBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Intent i = new Intent("com.examle.FirebaseMessagingReceiveService");
        i.setClass(context, FirebaseMessagingReceiveService.class);
        context.startService(i);
    }
}
jessica
  • 1,700
  • 1
  • 11
  • 17
0

I had a similar issue . What was preventing it to send to app was the

echo

Try removing the echo

Kofi Sammie
  • 3,237
  • 1
  • 17
  • 17