我正在尝试构建一个应用程序,当从Google的GCM服务器接收GCM消息时,我可以在屏幕顶部显示通知,如Facebook的应用程序Messenger。
我的问题是: 代码
windowManager.addView(chatHead, params);
函数addView()中的即使被调用也没有效果。 有谁知道问题是什么?谢谢你的帮助!
以下是我如何构建应用的详细信息:
首先我跟随 How to make a Facebook Messenger-like notification like this in Android
我已经通过创建一个新服务测试了函数“addView()”并在onCreate()中调用它并且它确实有效。 (即使我的活动暂停,它也会在我的HTC屏幕上显示一个图像。)
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");
}
其次,我遇到了“GcmListenerService”没有任何looper来处理UI更新的问题;因此,我跟随 https://github.com/quakerntj/SendMesageToPhoneByGCM/blob/master/src/com/ntj/GcmTest/MyGcmListenerService.java 添加处理程序和循环程序来处理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();
}
}
第三,我使用上面创建的线程在我的应用收到GCM消息时触发addView:
@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:整个源代码如下:
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();
}
}}