使用自定義的 notification時,遇到這個錯誤:
android.app.RemoteServiceException: Bad notification posted: Couldn't expand RemoteViews for: StatusBarNotification
查了資料,發現原因不外乎是因為布局裡有不支援的布局或控件:
RemoteViews并不是支援全部的布局和控件,在RemoteViews中,隻能使用以下幾種界面元件,自定義的控件也不行:
布局Layout: FrameLayout, LinearLayout, RelativeLayout。
控件Component:
AnalogClock, Button, Chronometer, ImageButton, ImageView, ProgressBar, TextView, ViewFlipper, ListView, GridView, StackView, AdapterViewFlipper。
我檢視了下我用的布局和控件,根布局用的是LinearLayout,然後嵌套了一個LinearLayout,剩下的就是ImageView和TextView了,都符合這個啊。
後來又試,發現根布局使用layout_marginLeft這樣的屬性就會報上面的異常,或者根布局内使用了嵌套的LinearLayout也會報這個異常,是以就把layout_marginLeft放到了控件裡,并且把嵌套的LinearLayout去掉了,把根布局改成了RelativeLayout,然後問題就解決了。
最終的布局是view_notification.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_icon"
android:layout_width="20dp"
android:layout_height="20dp"
android:background="@drawable/ic_noti"
android:layout_marginLeft="@dimen/normal_padding"
android:layout_marginTop="@dimen/normal_padding"/>
<TextView
android:id="@+id/tv_appname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/normal_match"
android:layout_toRightOf="@+id/iv_icon"
android:layout_marginTop="@dimen/normal_padding"/>
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/iv_icon"
android:textColor="@color/black"
android:layout_marginLeft="@dimen/normal_padding"/>
<TextView
android:id="@+id/tv_content"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_below="@+id/tv_title"
android:layout_marginBottom="@dimen/normal_match"
android:layout_marginLeft="@dimen/normal_padding"/>
</RelativeLayout>
自定義的notification為:
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder notification = new Notification.Builder(this);
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.view_notification);
remoteViews.setTextViewText(R.id.tv_appname, getString(R.string.app_name));
remoteViews.setTextViewText(R.id.tv_title, title);
remoteViews.setImageViewResource(R.id.iv_icon, R.drawable.ic_noti);
remoteViews.setTextViewText(R.id.tv_content, content);
notification = new Notification.Builder(this)
.setSmallIcon(R.drawable.ic_noti)
// .setContentTitle(title)
// .setContentText(content)
.setTicker(title)
.setNumber(1)
.setTicker(title)//收到資訊後狀态欄顯示的文字資訊.setAutoCancel(true)//使用者點選Notification點選面闆後是否讓通知取消(預設不取消)
.setVibrate(new long[]{0, 1000, 1000, 1000})//設定震動
.setDefaults(Notification.DEFAULT_LIGHTS)
// .setSound(Uri.fromFile(new File("/system/media/audio/ui/VideoRecord.ogg")))//設定聲音
.setSound(Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "5"))//設定聲音
.setLights(Color.RED, 1000, 1000)//設定前置LED燈進行閃爍, 第一個為顔色值 第二個為亮的時長 第三個為暗的時長
.setContentIntent(pendingIntent);
Notification build = notification.build();
build.contentView = remoteViews;
build.flags = Notification.DEFAULT_VIBRATE | Notification.FLAG_SHOW_LIGHTS;//震動、
notificationManager.notify(0, build);