android notification应用之自定义来电通知
1.为了实现老板的各种要求 本人矜矜业业完成任务 随着这个软电话软件的日益完善 本来来电的时候是创建一条通知点亮屏幕 用户可以解锁屏幕后接起电话 但老板又觉得体验不好 想直接在锁屏状态下直接接起电话 我就寻思着 自带的notification通知栏样式肯定是不能实现这个接电话挂电话的功能的 那就相方设法自己写一个通知栏样式呗 我本来以为自定义通知栏不好实现 加上还有按钮的相关接电话和挂电话的功能 (ps:这个时候我请教了我的老师 其实非常感谢他的帮助 让我在四五个月内 学了不少android的开发技能 问他问题他会给我讲解大致思路 然后让我自己按照这个思路去完成要求 实在不会了 他也会给我提供具体的方法 总之就是很感谢那个大哥哥了)
2. 自定义通知的实现主要是用到了RemoteViews来对通知栏样式进行更改 ,本来通知栏的创建使用了 Notification.Builder(this, CHANNEL_ONE_ID) 自定义通知栏时使用了NotificationCompat.Builder(this) 下面来贴一下代码
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void showNotification(String phoneNum) {
if (phoneNums.size()>0) {
notificationId = phoneNums.indexOf(phoneNum);
} else{
notificationId = 100;
}
manager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
String CHANNEL_ONE_ID = getPackageName();
String CHANNEL_ONE_NAME = "Channel One";
NotificationChannel notificationChannel = null;
manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
notificationChannel = new NotificationChannel(CHANNEL_ONE_ID, CHANNEL_ONE_NAME, NotificationManager.IMPORTANCE_HIGH);
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.setShowBadge(true);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
manager.createNotificationChannel(notificationChannel);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.mipmap.ic_launcher);//使用RemoteViews时,设置的是状态栏中的小图标,必须要设置
builder.setAutoCancel(true);//设置是否点击通知后会自动消失
Notification notification = builder.build();
//通过xml创建RemoteViews,并且动态改变布局中的内容
RemoteViews views = new RemoteViews(getPackageName(), R.layout.layout_notification);
views.setTextViewText(R.id.notification_title, "WES");
views.setTextViewText(R.id.notification_content, Sys.details);
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
//按钮点击事件:
//接通电话的相关操作
PendingIntent acceptIntent = PendingIntent.getBroadcast(this,notificationId ,new Intent("action.accept"),PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.accept_icon,acceptIntent);//点击的id,点击事件
/挂断电话的相关操作(点击挂断电话的按钮会发送一个action为action.decline的广播,然后广接收者受到广播对广播进行处理 )
PendingIntent declineIntent = PendingIntent.getBroadcast(this,notificationId ,new Intent("action.decline"),PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.decline_icon,declineIntent);//点击的id,点击事件
String time = sdf.format(date);
views.setTextViewText(R.id.notification_time, time);
//这里需要注意,如果不设置 notification.bigContentView ,则由于通知的高度是固定的,如果remoteview的布局超过了其通知的高度,
//就会有一部分显示不出来了
notification.bigContentView = views;
notification.contentView = views;
notification.visibility = Notification.VISIBILITY_PUBLIC;
//给整个通知设置一个拉起来电页面的PendingIntent
Intent intentNotification = new Intent(SiphoneService.this, CallIncomingActivity.class);
intentNotification.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intentNotification.setPackage("com.sux.sip");
PendingIntent pi = PendingIntent.getActivity(this, notificationId, intentNotification, PendingIntent.FLAG_CANCEL_CURRENT);
notification.contentIntent = pi;
//单独给RemoteView中的控件设置PengdingIntent
// Intent intentNotification2 = new Intent();
// intentNotification2.setComponent(new ComponentName("com.netease.newsreader.activity","com.netease.nr.biz.ad.AdActivity"));
// intentNotification.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// PendingIntent pi2 = PendingIntent.getActivity(context, 123, intentNotification2, PendingIntent.FLAG_CANCEL_CURRENT);
// views.setOnClickPendingIntent(R.id.iv_banner,pi2);
manager.notify(notificationId, notification);
}
这里我给相同的电话号码设置了相同的notificationId,这样通知的时候就只会出现一条通知 还有一点没完善 应该要填上来电几条的 嗯 以后再加上吧
3.下面来实现广播接受者
public class NotificationBroadcast extends BroadcastReceiver {
private final static String TAG = "NotificationBroadcast";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();//动作
Log.e(TAG, "广播 Action = " + action);
if (action.equals("action.accept")) {
Log.e(TAG, "接通电话");
Call call = SiphoneService.getCore().getCurrentCall();
if(call != null){
Call.State state = call.getState();
if(state.equals(Call.State.IncomingEarlyMedia) ||state.equals(Call.State.IncomingReceived)){
if(SiphoneService.manager!=null){
System.out.println("call notificationId1:"+SiphoneService.notificationId);
SiphoneService.manager.cancel(SiphoneService.notificationId);
}
CallParams params = SiphoneService.getCore().createCallParams(call);
call.acceptWithParams( params );
}
}
}else if (action.equals("action.decline")) {
Log.e(TAG, "挂断电话");
Call call = SiphoneService.getCore().getCurrentCall();
if(call != null){
Call.State state = call.getState();
if(state.equals(Call.State.IncomingEarlyMedia) ||state.equals(Call.State.IncomingReceived)){
//这里的manager是前面代码中的关于notification的manager 挂断电话既是对这条通知的处理 接通电话同理 就直接取消掉前面的通知
if(SiphoneService.manager!=null){
System.out.println("call notificationId1:"+SiphoneService.notificationId);
SiphoneService.manager.cancel(SiphoneService.notificationId);
}
call.terminate();
}
}
}
}
//这里我没用这个方法对通知栏进行伸缩 因为当我选择挂断电话还是接听电话 都对这个消息进行了处理 直接使用了上面的取消通知的功能
// public void collapseStatusBar(Context context) {
// try {
// Object statusBarManager = context.getSystemService("statusbar");
// Method collapse;
// if (Build.VERSION.SDK_INT <= 16) {
// collapse = statusBarManager.getClass().getMethod("collapse");
// } else {
// collapse = statusBarManager.getClass().getMethod("collapsePanels");
// }
// collapse.invoke(statusBarManager);
// } catch (Exception localException) {
// localException.printStackTrace();
// }
}
广播是我们自己定义的action 所以在AndroidManifest.xml中需要拦截一下广播的action
<receiver
android:name=".receviers.NotificationBroadcast"
android:enabled="true">
<intent-filter>
<action android:name="action.accept"/>
<action android:name="action.decline"/>
</intent-filter>
</receiver>
4.贴一下我自定义的notification布局 layout_notification.xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp">
<TextView
android:id="@+id/notification_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="WES"/>
<TextView
android:id="@+id/notification_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text="23:34"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp">
<TextView
android:id="@+id/notification_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="111111111111111"/>
</LinearLayout>
<LinearLayout
android:id="@+id/acceptUnlock"
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/accept_icon"
android:src="@drawable/call_start"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="3dp"
android:layout_weight="1"/>
<ImageView
android:id="@+id/decline_icon"
android:src="@drawable/hangup"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"/>
</LinearLayout>
</LinearLayout>
5.总结一下 贴代码真的很爽 写起文字来真的很烦
最后实现的结果就是在锁屏下会有一条通知点亮屏幕 通知的内容是来电的相关信息 可以选择接电话和挂断电话 接电话后居然可以跨过锁屏来到通话界面 点击缩放可以使通话界面悬浮 再次进到通话界面需要解锁 解锁后也有悬浮窗也可以回到通话界面