Android Notification通知简单封装(适配8.0)

《Android Notification通知简单封装(适配8.0)》 image

一、简介
二、效果预览
三、实现步骤
四、源码分析
五、Demo地址
六、内容推荐

一、简介

这是一篇介绍简单实现通知notification的文章,并不会太深入。只是让大家使用通知的时候,能够节省开发时间。详细使用步骤或者方法可以到官网查看API文档https://developer.android.google.cn/reference/android/support/v4/app/NotificationCompat.Builder。简单的给大家推荐一个工具类,后续若有更好的发现会及时更新。

二、效果预览

《Android Notification通知简单封装(适配8.0)》 image

​三、实现步骤

1、工具类

import android.annotation.TargetApi;
import android.app.AppOpsManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.support.annotation.RequiresApi;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.text.TextUtils;
import android.widget.RemoteViews;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import blcs.lwb.lwbtool.R;

import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
import static android.content.Context.NOTIFICATION_SERVICE;
import static android.support.v4.app.NotificationCompat.PRIORITY_DEFAULT;

/**
 * TODO 通知栏工具 BLCS
 * https://developer.android.google.cn/reference/android/support/v4/app/NotificationCompat.Builder
 */
public class LinNotify {

    public static final int RequestCode = 1;
    public static final String NEW_MESSAGE = "chat";
    public static final String NEW_GROUP = "chat_group";
    public static final String OTHER_MESSAGE = "other";
    public static final String Ticker = "您有一条新的消息";
    public static final String CHECK_OP_NO_THROW = "checkOpNoThrow";
    public static final String OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION";
    public static int notifyId = 0;

    /**
     * TODO 适配 Android8.0  创建通知渠道
     * tips:可以写在MainActivity中,也可以写在Application中,实际上可以写在程序的任何位置,
     * 只需要保证在通知弹出之前调用就可以了。并且创建通知渠道的代码只在第一次执行的时候才会创建,
     * 以后每次执行创建代码系统会检测到该通知渠道已经存在了,因此不会重复创建,也并不会影响任何效率。
     */
    public static void setNotificationChannel(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            String channelId = NEW_MESSAGE;
            String channelName = "新消息通知";
            createNotificationChannel(context, channelId, channelName, NotificationManager.IMPORTANCE_HIGH);
            channelId = OTHER_MESSAGE;
            channelName = "其他通知";
            createNotificationChannel(context, channelId, channelName, NotificationManager.IMPORTANCE_HIGH);
        }
    }

    /**
     * 创建配置通知渠道
     * @param channelId   渠道id
     * @param channelName 渠道nanme
     * @param importance  优先级
     */
    @TargetApi(Build.VERSION_CODES.O)
    private static void createNotificationChannel(Context context, String channelId, String channelName, int importance) {
//        createNotifycationGroup(context,channelId,channelName);
        NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
        channel.setShowBadge(false);//禁止该渠道使用角标
//        channel.setGroup(channelId); //设置渠道组id
        // 配置通知渠道的属性
//        channel .setDescription("渠道的描述");
        // 设置通知出现时的闪灯(如果 android 设备支持的话)
        channel.enableLights(true);
        // 设置通知出现时的震动(如果 android 设备支持的话)
        channel.enableVibration(false);
        //如上设置使手机:静止1秒,震动2秒,静止1秒,震动3秒
//        channel.setVibrationPattern(new long[]{1000, 2000, 1000,3000});
        channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);//设置锁屏是否显示通知
        channel.setLightColor(Color.BLUE);
        channel.setBypassDnd(true);//设置是否可以绕过请勿打扰模式
        NotificationManager notificationManager = (NotificationManager) context.getSystemService(
                NOTIFICATION_SERVICE);
        notificationManager.createNotificationChannel(channel);
    }

    /**
     * 创建渠道组(若通知渠道比较多的情况下可以划分渠道组)
     * @param groupId
     * @param groupName
     */
    @RequiresApi(api = Build.VERSION_CODES.O)
    public static void createNotifycationGroup(Context context,String groupId, String groupName) {
        NotificationChannelGroup group = new NotificationChannelGroup(groupId, groupName);
        NotificationManager notificationManager = (NotificationManager)context.getSystemService(
                NOTIFICATION_SERVICE);
        notificationManager.createNotificationChannelGroup(group);
    }

    /**
     * TODO: 发送通知(刷新前面的通知)
     *
     * @param context
     * @param contentTitle 标题
     * @param contentText  内容
     */
    public static void show(Context context, String contentTitle, String contentText, Class<?> cls) {
        show(context, contentTitle, contentText,null, 0, NEW_MESSAGE, cls);
    }

    /**
     * TODO: 发送自定义通知(刷新前面的通知)
     *
     * @param context
     * @param contentTitle 标题
     * @param contentText  内容
     */
    public static void show(Context context, String contentTitle, String contentText,RemoteViews views ,Class<?> cls) {
        show(context, contentTitle, contentText, views,0, NEW_MESSAGE, cls);
    }

    /**
     * 发送通知(刷新前面的通知,指定通知渠道)
     *
     * @param contentTitle 标题
     * @param contentText  内容
     * @param channelId    渠道id
     */
    public static void show(Context context, String contentTitle, String contentText, String channelId, Class<?> cls) {
        show(context, contentTitle, contentText,null, 0, channelId, cls);
    }

    /**
     * 发送自定义通知(刷新前面的通知,指定通知渠道)
     *
     * @param contentTitle 标题
     * @param contentText  内容
     * @param channelId    渠道id
     */
    public static void show(Context context, String contentTitle, String contentText,RemoteViews views, String channelId, Class<?> cls) {
        show(context, contentTitle, contentText,views, 0, channelId, cls);
    }

    /**
     * 发送多条通知(默认通知渠道)
     *
     * @param contentTitle 标题
     * @param contentText  内容
     */
    public static void showMuch(Context context, String contentTitle, String contentText, Class<?> cls) {
        show(context, contentTitle, contentText,null, ++notifyId, NEW_MESSAGE, cls);
    }

    /**
     * 发送多条自定义通知(默认通知渠道)
     *
     * @param contentTitle 标题
     * @param contentText  内容
     */
    public static void showMuch(Context context, String contentTitle, String contentText,RemoteViews views, Class<?> cls) {
        show(context, contentTitle, contentText,views, ++notifyId, NEW_MESSAGE, cls);
    }

    /**
     * 发送多条通知(指定通知渠道)
     *
     * @param contentTitle 标题
     * @param contentText  内容
     * @param channelId    渠道id
     */
    public static void showMuch(Context context, String contentTitle, String contentText, String channelId, Class<?> cls) {
        show(context, contentTitle, contentText,null, ++notifyId, channelId, cls);
    }

    /**
     * 发送多条自定义通知(指定通知渠道)
     *
     * @param contentTitle 标题
     * @param contentText  内容
     * @param channelId    渠道id
     */
    public static void showMuch(Context context, String contentTitle, String contentText, String channelId,RemoteViews views, Class<?> cls) {
        show(context, contentTitle, contentText,views, ++notifyId, channelId, cls);
    }

    /**
     * 发送通知(设置默认:大图标/小图标/小标题/副标题/优先级/首次弹出文本)
     *
     * @param contentTitle 标题
     * @param contentText  内容
     * @param notifyId     通知栏id
     * @param channelId    设置渠道id
     * @param cls          意图类
     */
    public static void show(Context context, String contentTitle, String contentText, RemoteViews views,int notifyId, String channelId, Class<?> cls) {
        show(context, 0, 0, contentTitle, null, contentText, PRIORITY_DEFAULT, null,views ,notifyId, channelId, cls);
    }

    /**
     * 发送通知
     *
     * @param largeIcon    大图标
     * @param smallIcon    小图标
     * @param contentTitle 标题
     * @param subText      小标题/副标题
     * @param contentText  内容
     * @param priority     优先级
     * @param ticker       通知首次弹出时,状态栏上显示的文本
     * @param notifyId     定义是否显示多条通知栏
     * @param cls          意图类
     */
    public static void show(Context context, int largeIcon,
                            int smallIcon, String contentTitle,
                            String subText, String contentText,
                            int priority, String ticker, RemoteViews view,
                            int notifyId, String channelId, Class<?> cls) {
        //flags
        // FLAG_ONE_SHOT:表示此PendingIntent只能使用一次的标志
        // FLAG_IMMUTABLE:指示创建的PendingIntent应该是不可变的标志
        // FLAG_NO_CREATE : 指示如果描述的PendingIntent尚不存在,则只返回null而不是创建它。
        // FLAG_CANCEL_CURRENT :指示如果所描述的PendingIntent已存在,则应在生成新的PendingIntent,取消之前PendingIntent
        // FLAG_UPDATE_CURRENT : 指示如果所描述的PendingIntent已存在,则保留它,但将其额外数据替换为此新Intent中的内容
        PendingIntent pendingIntent = null;
        //添加隐示意图
        if (cls != null) {
            Intent intent = new Intent(context, cls);
            pendingIntent = PendingIntent.getActivity(context, RequestCode, intent, FLAG_UPDATE_CURRENT);
        }
        //获取通知服务管理器
        NotificationManager manager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
        //判断应用通知是否打开
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            if (!openNotificationChannel(context, manager, channelId)) return;
        }

        //创建 NEW_MESSAGE 渠道通知栏  在API级别26.1.0中推荐使用此构造函数 Builder(context, 渠道名)
        NotificationCompat.Builder builder = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) ? new NotificationCompat.Builder(context, channelId) : new NotificationCompat.Builder(context);
        builder.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), largeIcon == 0 ? R.mipmap.ic_launcher : largeIcon)) //设置自动收报机和通知中显示的大图标。
                .setSmallIcon(smallIcon == 0 ? R.mipmap.ic_launcher : smallIcon) // 小图标
                .setContentText(TextUtils.isEmpty(contentText)? null : contentText) // 内容
                .setContentTitle(TextUtils.isEmpty(contentTitle) ? null : contentTitle) // 标题
                .setSubText(TextUtils.isEmpty(subText) ? null : subText) // APP名称的副标题
                .setPriority(priority) //设置优先级 PRIORITY_DEFAULT
                .setTicker(TextUtils.isEmpty(ticker) ? Ticker : ticker) // 设置通知首次弹出时,状态栏上显示的文本
                .setContent(view)
                .setWhen(System.currentTimeMillis()) // 设置通知发送的时间戳
                .setShowWhen(true)//设置是否显示时间戳
                .setAutoCancel(true)// 点击通知后通知在通知栏上消失
                .setDefaults(Notification.PRIORITY_HIGH)// 设置默认的提示音、振动方式、灯光等 使用的默认通知选项
                .setContentIntent(pendingIntent) // 设置通知的点击事件
                //锁屏状态下显示通知图标及标题 1、VISIBILITY_PUBLIC 在所有锁定屏幕上完整显示此通知/2、VISIBILITY_PRIVATE 隐藏安全锁屏上的敏感或私人信息/3、VISIBILITY_SECRET 不显示任何部分
                .setVisibility(Notification.VISIBILITY_PUBLIC)//部分手机没效果
                .setFullScreenIntent(pendingIntent,true)//悬挂式通知8.0需手动打开
//                .setColorized(true)
//                .setGroupSummary(true)//将此通知设置为一组通知的组摘要
//                .setGroup(NEW_GROUP)//使用组密钥
//                .setDeleteIntent(pendingIntent)//当用户直接从通知面板清除通知时 发送意图
//                .setFullScreenIntent(pendingIntent,true)
//                .setContentInfo("大文本")//在通知的右侧设置大文本。
//                .setContent(RemoteViews RemoteView)//设置自定义通知栏
//                .setColor(Color.parseColor("#ff0000"))
//                .setLights()//希望设备上的LED闪烁的argb值以及速率
//                .setTimeoutAfter(3000)//指定取消此通知的时间(如果尚未取消)。
        ;

        // 通知栏id
        manager.notify(notifyId, builder.build()); // build()方法需要的最低API为16 ,
    }

    /**
     * 判断应用渠道通知是否打开(适配8.0)
     * @return true 打开
     */
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public static Boolean openNotificationChannel(Context context, NotificationManager manager, String channelId) {
        //判断通知是否有打开
        if (!isNotificationEnabled(context)) {
            toNotifySetting(context, null);
            return false;
        }
        //判断渠道通知是否打开
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = manager.getNotificationChannel(channelId);
            if (channel.getImportance() == NotificationManager.IMPORTANCE_NONE) {
                //没打开调往设置界面
                toNotifySetting(context, channel.getId());
                return false;
            }
        }

        return true;
    }

    /**
     * 判断应用通知是否打开
     * @return
     */
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public static boolean isNotificationEnabled(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(context);
            return notificationManagerCompat.areNotificationsEnabled();
        }
        AppOpsManager mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        Class appOpsClass = null;
        /* Context.APP_OPS_MANAGER */
        try {
            appOpsClass = Class.forName(AppOpsManager.class.getName());
            Method checkOpNoThrowMethod = appOpsClass.getMethod(CHECK_OP_NO_THROW, Integer.TYPE, Integer.TYPE,
                    String.class);
            Field opPostNotificationValue = appOpsClass.getDeclaredField(OP_POST_NOTIFICATION);
            int value = (Integer) opPostNotificationValue.get(Integer.class);
            return ((Integer) checkOpNoThrowMethod.invoke(mAppOps, value, context.getApplicationInfo().uid, context.getPackageName()) == AppOpsManager.MODE_ALLOWED);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 手动打开应用通知
     */
    public static void toNotifySetting(Context context, String channelId) {
        Intent intent = new Intent();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { //适配 8.0及8.0以上(8.0需要先打开应用通知,再打开渠道通知)
            if(TextUtils.isEmpty(channelId)){
                intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
                intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName());
            }else{
                intent.setAction(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
                intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName());
                intent.putExtra(Settings.EXTRA_CHANNEL_ID, channelId);
            }
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//适配 5.0及5.0以上
            intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
            intent.putExtra("app_package", context.getPackageName());
            intent.putExtra("app_uid", context.getApplicationInfo().uid);
        } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {// 适配 4.4及4.4以上
            intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
            intent.addCategory(Intent.CATEGORY_DEFAULT);
            intent.setData(Uri.fromParts("package", context.getPackageName(), null));
        } else {
            intent.setAction(Settings.ACTION_SETTINGS);
        }
        context.startActivity(intent);
    }

}

2、工具的使用方法

//通知栏初始化(适配8.0)
LinNotify.setNotificationChannel(context);

//发送同一个通知
LinNotify.show(activity, "通知栏标题", "通知栏内容", null);

//发送自定义通知
RemoteViews mViews = new RemoteViews(activity.getPackageName(), R.layout.custom_notify);
mViews.setTextViewText(R.id.tv_custom_notify,"正在下载");
mViews.setTextViewText(R.id.tv_custom_notify_number,++progress+"0%");
mViews.setProgressBar(R.id.pb_custom_notify,10,progress,false);
LinNotify.show(activity, StringUtils.getString(et_notification_title), StringUtils.getString(etNotificationContent),mViews, null);

总结:在Application中调用工具初始化通知渠道 ,发送通知时调用工具Show方法即可。

四、源码分析

1、创建通知渠道

    /**
     * TODO 适配 Android8.0  创建通知渠道
     * tips:可以写在MainActivity中,也可以写在Application中,实际上可以写在程序的任何位置,
     * 只需要保证在通知弹出之前调用就可以了。并且创建通知渠道的代码只在第一次执行的时候才会创建,
     * 以后每次执行创建代码系统会检测到该通知渠道已经存在了,因此不会重复创建,也并不会影响任何效率。
     */
    public static void setNotificationChannel(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            String channelId = NEW_MESSAGE;
            String channelName = "新消息通知";
            createNotificationChannel(context, channelId, channelName, NotificationManager.IMPORTANCE_HIGH);
            channelId = OTHER_MESSAGE;
            channelName = "其他通知";
            createNotificationChannel(context, channelId, channelName, NotificationManager.IMPORTANCE_HIGH);
        }
    }

可以在这个方法中添加应用所需的渠道,android 8.0新增的功能

//创建一个渠道
NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);

//渠道添加到通知管理当中
NotificationManager notificationManager = (NotificationManager) context.getSystemService(
                NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);

当然也可以划分渠道组

 /**
     * 创建渠道组(若通知渠道比较多的情况下可以划分渠道组)
     * @param groupId
     * @param groupName
     */
    @RequiresApi(api = Build.VERSION_CODES.O)
    public static void createNotifycationGroup(Context context,String groupId, String groupName) {
        NotificationChannelGroup group = new NotificationChannelGroup(groupId, groupName);
        NotificationManager notificationManager = (NotificationManager)context.getSystemService(
                NOTIFICATION_SERVICE);
        notificationManager.createNotificationChannelGroup(group);
    }

经过测试有些机型并不会显示(没效果)。原因未知…作者是个小菜鸟 。知道的读者可以留言分享下。作者在这里先谢过

《Android Notification通知简单封装(适配8.0)》 1

2、发送通知

感觉都不用解释分析了,已经注释的很明显。

 /**
     * 发送通知
     *
     * @param largeIcon    大图标
     * @param smallIcon    小图标
     * @param contentTitle 标题
     * @param subText      小标题/副标题
     * @param contentText  内容
     * @param priority     优先级
     * @param ticker       通知首次弹出时,状态栏上显示的文本
     * @param notifyId     定义是否显示多条通知栏
     * @param cls          意图类
     */
    public static void show(Context context, int largeIcon,
                            int smallIcon, String contentTitle,
                            String subText, String contentText,
                            int priority, String ticker, RemoteViews view,
                            int notifyId, String channelId, Class<?> cls) {
        //flags
        // FLAG_ONE_SHOT:表示此PendingIntent只能使用一次的标志
        // FLAG_IMMUTABLE:指示创建的PendingIntent应该是不可变的标志
        // FLAG_NO_CREATE : 指示如果描述的PendingIntent尚不存在,则只返回null而不是创建它。
        // FLAG_CANCEL_CURRENT :指示如果所描述的PendingIntent已存在,则应在生成新的PendingIntent,取消之前PendingIntent
        // FLAG_UPDATE_CURRENT : 指示如果所描述的PendingIntent已存在,则保留它,但将其额外数据替换为此新Intent中的内容
        PendingIntent pendingIntent = null;
        //添加隐示意图
        if (cls != null) {
            Intent intent = new Intent(context, cls);
            pendingIntent = PendingIntent.getActivity(context, RequestCode, intent, FLAG_UPDATE_CURRENT);
        }
        //获取通知服务管理器
        NotificationManager manager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
        //判断应用通知是否打开
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            if (!openNotificationChannel(context, manager, channelId)) return;
        }

        //创建 NEW_MESSAGE 渠道通知栏  在API级别26.1.0中推荐使用此构造函数 Builder(context, 渠道名)
        NotificationCompat.Builder builder = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) ? new NotificationCompat.Builder(context, channelId) : new NotificationCompat.Builder(context);
        builder.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), largeIcon == 0 ? R.mipmap.ic_launcher : largeIcon)) //设置自动收报机和通知中显示的大图标。
                .setSmallIcon(smallIcon == 0 ? R.mipmap.ic_launcher : smallIcon) // 小图标
                .setContentText(TextUtils.isEmpty(contentText)? null : contentText) // 内容
                .setContentTitle(TextUtils.isEmpty(contentTitle) ? null : contentTitle) // 标题
                .setSubText(TextUtils.isEmpty(subText) ? null : subText) // APP名称的副标题
                .setPriority(priority) //设置优先级 PRIORITY_DEFAULT
                .setTicker(TextUtils.isEmpty(ticker) ? Ticker : ticker) // 设置通知首次弹出时,状态栏上显示的文本
                .setContent(view)
                .setWhen(System.currentTimeMillis()) // 设置通知发送的时间戳
                .setShowWhen(true)//设置是否显示时间戳
                .setAutoCancel(true)// 点击通知后通知在通知栏上消失
                .setDefaults(Notification.PRIORITY_HIGH)// 设置默认的提示音、振动方式、灯光等 使用的默认通知选项
                .setContentIntent(pendingIntent) // 设置通知的点击事件
                //锁屏状态下显示通知图标及标题 1、VISIBILITY_PUBLIC 在所有锁定屏幕上完整显示此通知/2、VISIBILITY_PRIVATE 隐藏安全锁屏上的敏感或私人信息/3、VISIBILITY_SECRET 不显示任何部分
                .setVisibility(Notification.VISIBILITY_PUBLIC)//部分手机没效果
                .setFullScreenIntent(pendingIntent,true)//悬挂式通知8.0需手动打开
//                .setColorized(true)
//                .setGroupSummary(true)//将此通知设置为一组通知的组摘要
//                .setGroup(NEW_GROUP)//使用组密钥
//                .setDeleteIntent(pendingIntent)//当用户直接从通知面板清除通知时 发送意图
//                .setFullScreenIntent(pendingIntent,true)
//                .setContentInfo("大文本")//在通知的右侧设置大文本。
//                .setContent(RemoteViews RemoteView)//设置自定义通知栏
//                .setColor(Color.parseColor("#ff0000"))
//                .setLights()//希望设备上的LED闪烁的argb值以及速率
//                .setTimeoutAfter(3000)//指定取消此通知的时间(如果尚未取消)。
        ;

        // 通知栏id
        manager.notify(notifyId, builder.build()); // build()方法需要的最低API为16 ,
    }

这篇算是一个笔记,内容不多 。但是使用比较频繁。就归类总结了一下。大家浏览一下估计就懂了,所以也不需要啰啰嗦嗦一大堆。

《Android Notification通知简单封装(适配8.0)》 2.jpg

五、Demo地址

源码地址:https://github.com/DayorNight/BLCS

apk下载体验地址:https://www.pgyer.com/BLCS

《Android Notification通知简单封装(适配8.0)》 image

六、内容推荐

CSDN:《Android Notification通知简单封装(适配8.0)》

《Android 仿RxDialog自定义DialogFragment》
《Android 获取App应用、缓存、数据等大小适配8.0(仿微信存储空间)》
《Android 仿微信多语言切换》
《Android 仿微信全局字体大小调整》
《Android Rxjava+Retrofit网络请求框架封装(一)》

如果你觉得写的不错或者对您有所帮助的话

不妨顶一个【微笑】,别忘了点赞、收藏、加关注哈

看在花了这么多时间整理写成文章分享给大家的份上,记得手下留情哈

您的每个举动都是对我莫大的支持

《Android Notification通知简单封装(适配8.0)》 gif

    原文作者:斌林诚上
    原文地址: https://www.jianshu.com/p/bc2917c3bca8
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞