2

I'm trying to build an app that when receiving GCM message from Google's GCM server, then I can show a notification on the top of the screen like Facebook's app Messenger.

My problem is: The code

windowManager.addView(chatHead, params);

in function addView() showed below has no effect even it was called. Does anyone know what the problem is? Thanks for help!

The following is the detail that how I build my app:

First I follow How to make a Facebook Messenger-like notification like this in Android

I have tested the function "addView()" by creating a new service and call it in onCreate() and it did work. (It would appear an image on my HTC screen even when my activity is paused.)

public void addView(){
    windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);

    chatHead = new ImageView(this);
    chatHead.setImageResource(R.drawable.climia);
    WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.TYPE_PHONE,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
            PixelFormat.TRANSLUCENT);
    params.gravity = Gravity.TOP | Gravity.LEFT;
    params.x = 0;
    params.y = 0;

    windowManager.addView(chatHead, params);
    Log.i("addview","after windowManager.addView");
}

Second, I faced the problem that "GcmListenerService" doesn't have any looper to deal with UI update; thus I follow https://github.com/quakerntj/SendMesageToPhoneByGCM/blob/master/src/com/ntj/GcmTest/MyGcmListenerService.java to add handler and looper to handle WindowManager.

class MyThread extends Thread {
    private Context mContext = null;
    private Handler mHandler = null;

    public MyThread(String s, Context context) {
        super(s);
        this.mContext = context;
    }
    public void setMessage(String message) {
        Message msg = Message.obtain(mHandler, 0, message);
        mHandler.sendMessage(msg);
    }
    @Override
    public void run() {
        Looper.prepare();
        mHandler = new Handler() {
            public void handleMessage(Message msg) {
                Log.i("Handler", "start handleMessage");
                addView();
                getLooper().quit();
            }
        };
        Looper.loop();
    }
}

Third, I use the thread created above to trigger addView whenever my app receives a GCM message:

@Override
public void onMessageReceived(String from, Bundle data) {
    GCMData GCMdata = new GCMData();

    GCMdata.title = data.getString("title");
    GCMdata.body = data.getString("body");
    GCMdata.detail  = data.getString("detail");
    GCMdata.type  = data.getString("type");
 /*
     show a notification indicating to the user
     */ sendNotification(GCMdata);

    mThread = new MyThread("nitamaGCM", this);
    mThread.start();
    synchronized (this) {
        try {
            // Wait the looper begin
            wait(10);
        } catch (InterruptedException e) {
        }
    }
    mThread.setMessage(GCMdata.body);
}

PS: The whole source code is below:

public class MyGcmListenerService extends GcmListenerService {

public class GCMData{
    String title;
    String body;
    String detail;
    String type;
}

private static final String TAG = "MyGcmListenerService";
private WindowManager windowManager;
private ImageView chatHead;

private MyThread mThread = null;
/**
 * Called when message is received.
 *
 * @param from SenderID of the sender.
 * @param data Data bundle containing message data as key/value pairs.
 *             For Set of keys use data.keySet().
 */
// [START receive_message]
@Override
public void onMessageReceived(String from, Bundle data) {
    GCMData GCMdata = new GCMData();

    GCMdata.title = data.getString("title");
    GCMdata.body = data.getString("body");
    GCMdata.detail  = data.getString("detail");
    GCMdata.type  = data.getString("type");
 /*
     show a notification indicating to the user
     */ sendNotification(GCMdata);

    mThread = new MyThread("nitamaGCM", this);
    mThread.start();
    synchronized (this) {
        try {
            // Wait the looper begin
            wait(10);
        } catch (InterruptedException e) {
        }
    }
    mThread.setMessage(GCMdata.body);
}
// [END receive_message]

/**
 * Create and show a simple notification containing the received GCM message.
 *
 * @param message GCM message received.
 */
private void sendNotification(GCMData GCMdata) {

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

    Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    NotificationCompat.Builder notificationBuilder =
            new NotificationCompat.Builder(this)
            .setSmallIcon(R.drawable.climia)                //required, small icon in notification area
            .setContentTitle(GCMdata.title)                      //required, notification title in notification drawer
            .setContentText(GCMdata.body)             //required, notification content in notification drawer
            .setContentInfo(GCMdata.detail)
            .setAutoCancel(true)                            //after clicking notification, dismiss notification
                    .setSound(defaultSoundUri)
            .setVibrate(new long[]{0, 100, 100, 200})   //Vibrate   format:  stop, vibrate, stop, vibrate, ...   unit: 1/1000 s
            //.setDeleteIntent(pendingIntent)                                        //trigger intent when the notification is cleared explicitly by the user
            .setContentIntent(pendingIntent)
            .setOnlyAlertOnce(true);                    //same notification ID  will not Vibrate or Sound again

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

    notificationManager.notify(
            Integer.parseInt(GCMdata.type) /* ID of notification */,
            notificationBuilder.build());
}
public void addView(){
    windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);

    chatHead = new ImageView(this);
    chatHead.setImageResource(R.drawable.climia);
    WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.TYPE_PHONE,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
            PixelFormat.TRANSLUCENT);
    params.gravity = Gravity.TOP | Gravity.LEFT;
    params.x = 0;
    params.y = 0;

    windowManager.addView(chatHead, params);
    Log.i("addview","after windowManager.addView");
}

class MyThread extends Thread {
    private Context mContext = null;
    private Handler mHandler = null;

    public MyThread(String s, Context context) {
        super(s);
        this.mContext = context;
    }
    public void setMessage(String message) {
        Message msg = Message.obtain(mHandler, 0, message);
        mHandler.sendMessage(msg);
    }
    @Override
    public void run() {
        Looper.prepare();
        mHandler = new Handler() {
            public void handleMessage(Message msg) {
                Log.i("Handler", "start handleMessage");
                addView();
                getLooper().quit();
            }
        };
        Looper.loop();
    }
}}
Community
  • 1
  • 1
W.J Chen
  • 21
  • 3
  • This is a bit long - I would consider reiterating your question towards the beginning, so people know what your end goal is as they read through your code. – cryptic_star Sep 23 '15 at 14:16
  • Thanks for advising! I've put my question towards the beginning. – W.J Chen Sep 24 '15 at 06:51
  • In the end, I created a new service that extends Service to call the function "addView()" and it did work though it's not the perfect answer. – W.J Chen Oct 01 '15 at 06:26
  • @W.JChen can you please share your solution? I'm currently facing the same problem. I have all the code of the addView method inside a different service that I start when I receive a push notification. If the push note is received while the app is opened, the floating image is displayed. If the app is not in foreground I receive the push note but the floating image is not displayed :-/ – Juanvi Martinez Jun 27 '16 at 15:24

0 Answers0