常用代码整理:Android 自定义推送(Notification)

说明:大部分内容都是参考别的文章,这里做整理是为了以后的编程有实用的模板,可以即需即用。

默认的通知栏样式:
    private void sendDefaultNotification() {
        NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        Intent intent = new Intent(this, TestActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        Notification.Builder builder = new Notification
                .Builder(getApplicationContext())
                .setSmallIcon(R.mipmap.ic_launcher)// 一定要设置
                .setTicker("状态栏标题")
                .setContentTitle("内容标题")
                .setContentText("内容")
                .setDefaults(Notification.DEFAULT_ALL)
                .setPriority(Notification.PRIORITY_MAX)
                .setAutoCancel(true)
                .setContentIntent(pendingIntent);

        //8.0 以后需要加上channelId 才能正常显示
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            String channelId = getApplicationContext().getPackageName();
            String channelName = "默认通知";
            notificationManager.createNotificationChannel(new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH));
            // 一定要加上,不然不显示
            builder.setChannelId(getApplicationContext().getPackageName());
        }

        notificationManager.notify(1, builder.build());
    }
自定义的通知栏样式:
    private void sendCustomNotification() {
        final NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        Intent intent = new Intent(this, TestActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        Uri soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + getApplicationContext().getPackageName() + "/" + R.raw.ring);
        // 如果音频文件已保存到本地,则采用下面代码
        /*Uri soundUri;
        String path = "xxx/xxx.mp"
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
            soundUri = FileProvider.getUriForFile(this, getApplicationContext().getPackageName() + ".provider", new File(path));
        } else {
            soundUri = Uri.fromFile(new File(path));
        }*/

        mRemoteViews = new RemoteViews(getPackageName(), R.layout.notification_custom);

        Notification.Builder builder = new Notification
                .Builder(getApplicationContext())
                .setSmallIcon(R.mipmap.zzjeohbs)// 一定要设置
                .setContent(mRemoteViews)// 默认情况下通知高度为64dp(但是又有一些不止64,比如vivo)
                //.setDefaults(Notification.DEFAULT_ALL)
                .setSound(soundUri)
                .setPriority(Notification.PRIORITY_MAX)
                .setAutoCancel(true)
                .setContentIntent(pendingIntent);

        //8.0 以后需要加上channelId 才能正常显示
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            String channelId = getApplicationContext().getPackageName();
            String channelName = "默认通知";
            NotificationChannel notificationChannel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH);
            // For API 26+ you need to set the sound on the notification channel
            AudioAttributes audioAttributes = new AudioAttributes.Builder()
                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                    .setUsage(AudioAttributes.USAGE_NOTIFICATION)
                    .build();
            notificationChannel.setSound(soundUri, audioAttributes);
            notificationManager.createNotificationChannel(notificationChannel);
            // 一定要加上,不然不显示
            builder.setChannelId(getApplicationContext().getPackageName());
        } else {
            builder.setSound(soundUri);
            //.setSound(soundUri, AudioManager.STREAM_MUSIC)
        }

        final Notification notification = builder.build();
        // 适配oppo自定义通知栏无法显示问题
        notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_ONGOING_EVENT;

        // api 24 builder.setCustomBigContentView(getBigRemoteViews());
        // notification.bigContentView = getBigRemoteViews(); // api 16 bigContentView 的最大高度是256dp

        Glide.with(this)
                .load("https://imgs.gmilesquan.com/img/home/titlebar_tab.png")
                .asBitmap()
                .into(new SimpleTarget<Bitmap>() {
                    @Override
                    public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
                        mRemoteViews.setImageViewBitmap(R.id.iv_title, resource);
                        mRemoteViews.setTextViewText(R.id.tv_content, "推送内容");
                        // TODO: 2019/8/12 通知之前要完成数据装载
                        notificationManager.notify(1, notification);
                    }
                });
    }

    private RemoteViews getBigRemoteViews() {
        RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.notification_big_custom);
        remoteViews.setTextViewText(R.id.tv_content, "推送内容");
        return remoteViews;
    }

notification_custom.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="70dp"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/iv_title"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        tools:src="@mipmap/ic_launcher" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginTop="5dp"
        android:layout_toRightOf="@id/iv_title"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_title"
            style="@style/NotificationTitle"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:maxLines="2"
            android:text="测试title" />

        <TextView
            android:id="@+id/tv_content"
            style="@style/NotificationInfo"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:ellipsize="end"
            android:maxLines="1"
            android:text="测试" />

    </LinearLayout>

</RelativeLayout>

notification_big_custom.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="256dp"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/iv_title"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:src="@mipmap/ic_launcher" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_toRightOf="@id/iv_title"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_title"
            style="@style/NotificationTitle"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:text="测试title" />

        <TextView
            android:id="@+id/tv_content"
            style="@style/NotificationInfo"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:text="测试" />

    </LinearLayout>

</RelativeLayout>

自定义通知栏时,因为各手机系统通知栏的背景主题明暗不同,所以建议内容文本颜色采用系统提供样式,api_21前后不同,所以要在values-v21文件中做适配:

1、默认 values
    <!-- Android 自定义Notification字体颜色适配 -->
    <style name="NotificationInfo" parent="android:TextAppearance.StatusBar.EventContent" />
    <style name="NotificationTitle" parent="android:TextAppearance.StatusBar.EventContent.Title" />

2、values-v21
    <!-- Android 自定义Notification字体颜色适配 -->
    <style name="NotificationInfo" parent="android:TextAppearance.Material.Notification.Info" />
    <style name="NotificationTitle" parent="android:TextAppearance.Material.Notification.Title" />

上面的内容文本颜色适配方案,在某些手机系统上还是生效不了,所以在网上找到了下面这个方案,通过分析系统通知栏主题色系是明还是暗,来设置内容文本颜色明暗:

    private boolean isDarkNotificationTheme(Context context) {
        return !isSimilarColor(Color.BLACK, getNotificationColor(context));
    }

    private int getNotificationColor(Context context) {
        Notification.Builder builder = new Notification.Builder(context);
        Notification notification = builder.build();
        int layoutId = notification.contentView.getLayoutId();
        ViewGroup viewGroup = (ViewGroup) LayoutInflater.from(context).inflate(layoutId, null, false);
        if (viewGroup.findViewById(android.R.id.title) != null) {
            return ((TextView) viewGroup.findViewById(android.R.id.title)).getCurrentTextColor();
        }
        return findColor(viewGroup);
    }

    private boolean isSimilarColor(int baseColor, int color) {
        int simpleBaseColor = baseColor | 0xff000000;
        int simpleColor = color | 0xff000000;
        int baseRed = Color.red(simpleBaseColor) - Color.red(simpleColor);
        int baseGreen = Color.green(simpleBaseColor) - Color.green(simpleColor);
        int baseBlue = Color.blue(simpleBaseColor) - Color.blue(simpleColor);
        double value = Math.sqrt(baseRed * baseRed + baseGreen * baseGreen + baseBlue * baseBlue);
        if (value < 180.0) {
            return true;
        }
        return false;
    }

    private int findColor(ViewGroup viewGroupSource) {
        int color = Color.TRANSPARENT;
        LinkedList<ViewGroup> viewGroups = new LinkedList<>();
        viewGroups.add(viewGroupSource);
        while (viewGroups.size() > 0) {
            ViewGroup viewGroup1 = viewGroups.getFirst();
            for (int i = 0; i < viewGroup1.getChildCount(); i++) {
                if (viewGroup1.getChildAt(i) instanceof ViewGroup) {
                    viewGroups.add((ViewGroup) viewGroup1.getChildAt(i));
                } else if (viewGroup1.getChildAt(i) instanceof TextView) {
                    if (((TextView) viewGroup1.getChildAt(i)).getCurrentTextColor() != -1) {
                        color = ((TextView) viewGroup1.getChildAt(i)).getCurrentTextColor();
                    }
                }
            }
            viewGroups.remove(viewGroup1);
        }
        return color;
    }

这个适配方案在某些国产手机系统上运行分析时,会奔溃,呵呵:

        try {
            if (isDarkNotificationTheme(context)) {
                remoteViews.setTextColor(R.id.tv_title, context.getResources().getColor(R.color.custom_notification_title_color));
                remoteViews.setTextColor(R.id.tv_content, context.getResources().getColor(R.color.custom_notification_content_color));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    private int getNotificationColor(Context context) {
        Notification.Builder builder = new Notification.Builder(context);
        Notification notification = builder.build();
        RemoteViews contentView = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            contentView = builder.createContentView();
        } else {
            // As of N, this field may be null.
            contentView = notification.contentView;
        }
        int layoutId = contentView.getLayoutId();
        ViewGroup viewGroup = (ViewGroup) LayoutInflater.from(context).inflate(layoutId, null, false);
        if (viewGroup.findViewById(android.R.id.title) != null) {
            return ((TextView) viewGroup.findViewById(android.R.id.title)).getCurrentTextColor();
        }
        return findColor(viewGroup);
    }

还有一点,我们有时只想设置不带icon的文本通知,但是在某些国产手机系统上,还是会在左上角展示一个小icon,甚至有些会在左边展示一个大icon。。。


参考文章:
1、https://blog.csdn.net/u010005281/article/details/78708172
2、https://blog.csdn.net/cloudzyy/article/details/83151090

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值