极力推荐文章:欢迎收藏
Android 干货分享

阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android

本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容:

  1. 广播的生命周期
  2. 四大组件之一,必须在Androidmainfest.xml中注册
  3. 广播的注册(静态广播、动态广播)
  4. 广播的发送(正常、有序、持续)
  5. 广播接收(系统广播、自定义广播)

BroadcastAndroid 四大组件之一,是一种广泛运用在应用程序之间异步传输信息的机制。
Broadcast 本质上是一个Intent 对象,差别在于Broadcast可以被多个 BroadcastReceiver处理。BroadcastReceiver 是一个全局监听器,通过它的 onReceive() 可以过滤用户想要的广播,进而进行其它操作。

1. BroadcastReceiver简介

BroadcastReceiver继承关系

BroadcastReceiver 默认是在主线程中执行,如果onReceiver()方法处理事件超过10s,则应用将会发生ANR(Application Not Responding),此时,如果建立工作线程并不能解决此问题,因此建议:如处理耗时操作,请用 Service代替。

BroadcastReceiver继承关系 如下:

java.lang.Object↳    android.content.BroadcastReceiver

BroadcastReceiver的主要声明周期方法onReceiver(),此方法执行完之后,BroadcastReceiver实例将被销毁。

2.四大组件之一,必须在Androidmainfest.xml中注册

        <receiverandroid:name="ReceiverMethod"android:enabled="true"android:exported="true"><intent-filter><action android:name="String....." /></intent-filter></receiver>

注意:
如不注册,将导致无法接收处理广播消息

3.广播的注册(静态注册、动态注册)

广播的注册分两种,一种在ndroidMfest.xml中静态注册,另一种是在Java代码中动态注册。

1.静态注册

一些系统发送的广播需要在Androidmainfest.xml中静态注册,例如 开机广播,apk状态改变广播,电量状态改变广播等。这些静态注册的广播,通常在Androidmainfest.xml中拦截特定的字符串。

静态注册广播的方法如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.programandroid"android:versionCode="1"android:versionName="1.0" >... ...<receiverandroid:name="com.programandroid.BroadcastReceiver.NotificationReceived"android:enabled="true"android:exported="true" ><intent-filter><action android:name="Notification_cancel" /><action android:name="Notification_music_pre" /><action android:name="Notification_music_play" /><action android:name="Notification_music_next" /></intent-filter></receiver>... ...

1.静态注册开机广播方法

开机广播比较特殊,需要在Androidmainfest.xml中添加权限。否则,无法获取开机广播。

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>//静态注册广播的方法<receiverandroid:name=".component.BroadcastReceiver.BootReceiverMethod"android:enabled="true"android:exported="true"><intent-filter><action android:name="android.intent.action.BOOT_COMPLETED" /></intent-filter></receiver>

2.动态注册广播

在Java中动态注册广播,通常格式如下:

  //动态注册广播registerReceiver(BroadcastReceiver, IntentFilter);

动态注册 监听灭屏、点亮屏幕的广播

在广播中动态注册广播请注意一定要使用context.getApplicationContext(),防止context 为空 ,引起空指针异常。

public class ScreenOnOffReceiver {public static void ReceiverScreenOnOff(Context context) {IntentFilter screenOffFilter = new IntentFilter();screenOffFilter.addAction(Intent.ACTION_SCREEN_OFF);screenOffFilter.addAction(Intent.ACTION_SCREEN_ON);BroadcastReceiver mScreenOnOffReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {// TODO Auto-generated method stubString action = intent.getAction();if (action.equals(Intent.ACTION_SCREEN_OFF)) {Toast.makeText(context, "接收屏幕熄灭广播", Toast.LENGTH_SHORT).show();}if (action.equals(Intent.ACTION_SCREEN_ON)) {Toast.makeText(context, "接收屏幕点亮广播", Toast.LENGTH_SHORT).show();}}};/*** context.getApplicationContext()* 在广播中注册广播时候需要注意,防止context 为空 ,引起空指针异常* **/
// 2.动态注册广播的方法context.registerReceiver(mScreenOnOffReceiver, screenOffFilter);}
}

4.广播的发送(无序、有序、持续)

1.发送无序广播的方法

发送无序广播在Android 中很常见,是一种一对多的关系,主要通过 sendBroadcast(intent);发送广播。

发送自定义广播案例

广播说白了就是一个带Action等字符串标记的Intent。发送自定义广播举例如下:

        Intent customIntent=new Intent();customIntent.setAction("SendCustomBroadcast");sendBroadcast(customIntent);

接收自定义广播的方法

当用户对某些广播感兴趣的话,此时可以获取此广播,然后在onReceive方法中处理接收广播的一下操作。


public class CustomBroadcast extends BroadcastReceiver {public CustomBroadcast() {}@Overridepublic void onReceive(Context context, Intent intent) {if (intent.getAction().equals("SendCustomBroadcast")){Toast.makeText(context,"自定义广播接收成功:Action:SendCustomBroadcast",Toast.LENGTH_SHORT).show();}}
}

注意自定义广播是在Androidmanfest.xml中静态注册的。

2.发送有序广播

广播在Android是有优先级的,优先级高的广播可以终止或修改广播内容。发送有序广播的方法如下sendOrderedBroadcast(intent,"str_receiver_permission");

例如:发送自定义有序广播

        Intent customOrderIntent=new Intent();customOrderIntent.setAction("SendCustomOrderBroadcast");customOrderIntent.putExtra("str_order_broadcast","老板说:公司每人发 10 个 月饼");sendOrderedBroadcast(customOrderIntent,"android.permission.ORDERBROADCAST");

广播属于四大组件,一定要在AndroidMainfest.xml中注册。

有序广播静态注册

接收有序广播的静态注册方法如下:

       <receiverandroid:name=".component.BroadcastReceiver.CustomHightBrodcast"android:enabled="true"android:exported="true"><intent-filter android:priority="1000"><action android:name="SendCustomOrderBroadcast" /></intent-filter></receiver><receiverandroid:name=".component.BroadcastReceiver.CustomMiddleBroadcast"android:enabled="true"android:exported="true"><intent-filter android:priority="500"><action android:name="SendCustomOrderBroadcast" /></intent-filter></receiver><receiverandroid:name=".component.BroadcastReceiver.CustomLowerBroadcast"android:enabled="true"android:exported="true"><intent-filter android:priority="100"><action android:name="SendCustomOrderBroadcast" /></intent-filter></receiver>
    1. 有序广播,高优先级广播可以优先处理
public class CustomHightBrodcast extends BroadcastReceiver {public CustomHightBrodcast() {}@Overridepublic void onReceive(Context context, Intent intent) {if (intent.getAction().equals("SendCustomOrderBroadcast")) {Toast.makeText(context, intent.getStringExtra("str_order_broadcast"), Toast.LENGTH_SHORT).show();Bundle bundle=new Bundle();bundle.putString("str_order_broadcast","经理说:公司每人发 5 个 月饼");
//            修改广播传输数据setResultExtras(bundle);}}
}
    1. 中优先级的广播后序处理
public class CustomMiddleBroadcast extends BroadcastReceiver {public CustomMiddleBroadcast() {}@Overridepublic void onReceive(Context context, Intent intent) {if (intent.getAction().equals("SendCustomOrderBroadcast")) {Toast.makeText(context, getResultExtras(true).getString("str_order_broadcast"), Toast.LENGTH_SHORT).show();Bundle bundle=new Bundle();bundle.putString("str_order_broadcast","主管说:公司每人发 2 个 月饼");setResultExtras(bundle);}}
}
    1. 低优先级广播最后处理
public class CustomLowerBroadcast extends BroadcastReceiver {public CustomLowerBroadcast() {}@Overridepublic void onReceive(Context context, Intent intent) {if (intent.getAction().equals("SendCustomOrderBroadcast")) {String notice= getResultExtras(true).getString("str_order_broadcast");Toast.makeText(context,notice, Toast.LENGTH_SHORT).show();
//          终止广播继续传播下去abortBroadcast();}}
}

注意 :
有序广播需要声明并使用权限

  • 1.声明使用权限
 <!-- 申请使用自定义 有序广播的权限 --><uses-permission >   android:name="android.permission.ORDERBROADCAST" />
  • 2.声明权限
 <!-- 自定义 有序广播的权限 --><permission>
android:name="android.permission.ORDERBROADCAST"/>

在有序广播中高优先级的广播接收广播,可以修改数据,然后传给低优先级的广播。

3.发送持续广播(已经被弃用)

粘性广播会在Android系统中一直存在,不过随着 Android系统的不断更新,此方法逐渐被抛弃,使用方法如下:sendStickyBroadcast(intent);

5.广播接收(系统广播、自定义广播)

当广播发出后,如何接收广播呢,下面将介绍接收广播的方法。
接受广播类 主要继承 BroadcastReceiver,然后在onReceive方法,过滤广播Action中携带的Intent,然后进行相关处理。

接收开机广播的方法

1. 实现BootReceiverMethod 继承 BroadcastReceiver

p ublic class BootReceiverMethod extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {//   接收开机广播处理事情,比如启动服务Intent mStartIntent = new Intent(context, StartServiceMethods.class);context.startService(mStartIntent);}
}

2.在Androidmainfest.xml 声明组件信息,并过滤开机完成 Action

        <receiverandroid:name=".component.BroadcastReceiver.BootReceiverMethod"android:enabled="true"android:exported="true"><intent-filter><action android:name="android.intent.action.BOOT_COMPLETED" /></intent-filter></receiver>

3.声明接收开机广播完成的权限

   <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

极力推荐文章:欢迎收藏
Android 干货分享

阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android

本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容:

  1. Service 简介
  2. 四大组件之一,必须在Androidmainfest.xml 中注册
  3. 启动模式启动服务
  4. 绑定模式绑定服务
  5. 前台服务
  6. AIDL远程服务

ServiceAndroid四大组件之一(Activity 活动,Service 服务,ContentProvider内容提供者,BroadcastReceiver 广播),与Activity相比,Activity是运行在前台,用户可以看得见,Service则是运行在后台,无用户界面,用户无法看到。

Service主要用于组件之间交互(例如:与ActivityContentProviderBroadcastReceiver进行交互)、后台执行耗时操作等(例如下载文件,播放音乐等,但Service在主线程运行时长不能超过20s,否则会出现ANR,耗时操作一般建议在子线程中进行操作)。

1.Service 简介

在了解Service 的生命周期的之前,我们先了解一下Service的继承关系,方便我们更好的了解Service

Service 继承关系如下:

java.lang.Object↳    android.content.Context↳    android.content.ContextWrapper↳    android.app.Service

Service 的两种启动模式

Service 有两种不同的启动模式 ,不同的启动模式对应不同生命周期.
Service启动模式主要分两种: 1. 启动模式。 2. 绑定模式。

1.启动模式

此模式通过 startService()方法启动,此服务可以在后台一直运行,不会随启动组件的消亡而消亡。只能执行单一操作,无法返回结果给调用方,常用于网络下载、上传文件,播放音乐等。

2.绑定模式

此模式 通过绑定组件(Activity等)调用 bindService() 启动,此服务随绑定组件的消亡而解除绑定。

如果此时没有其它通过startService()启动,则此服务会随绑定组件的消亡而消亡。
多个组件不仅可以同时绑定一个Service,而且可以通过进程间通信(IPC)执行跨进程操作等。

3.两种服务可以同时运行

启动模式与绑定模式的服务可以同时运行,在销毁服务时,只有两种模式都不在使用Service时候,才可以销毁服务,否则会引起异常。

4. 两种 Service 模式的生命周期

两种 Service模式的生命周期如下:

2.四大组件之一,必须在Androidmainfest.xml 中注册

Service 注册方法如下:

<manifest ... >...<application ... ><service android:name=".ServiceMethods" />...</application>
</manifest>

注意:

Service如不注册 ,不会像Activity那样会导致App CrashService 不注册 不会报异常信息,但是服务会起不来,如不注意很容易迷惑。

3.启动模式

通过启动模式启动的Service,如不主动关闭,Service会一直在。

启动模式启动服务的方法

        Intent  mBindIntent = new Intent(ServiceMethods.this, BindServiceMethods.class);startService(mStartIntent);

启动模式启动服务的生命周期

下面是验证启动模式启动服务的生命周期的方法,详细生命周期请查看上方Service的生命周期图。

01-03 17:16:36.147 23789-23789/com.android.program.programandroid I/StartService wjwj:: ----onCreate----
01-03 17:16:36.223 23789-23789/com.android.program.programandroid I/StartService wjwj:: ----onStartCommand----
01-03 17:16:38.174 23789-23789/com.android.program.programandroid I/StartService wjwj:: ----onDestroy----

启动模式 启动服务案例

此案例功能:启动服务,在服务中创建通知

    // Service 创建方法@Overridepublic void onCreate() {super.onCreate();Log.i(TAG, "----onCreate----");}// Service  启动方法@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Log.i(TAG, "----onStartCommand----");// 获取NotificationManager实例notifyManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);// 实例化NotificationCompat.Builder并设置相关属性NotificationCompat.Builder builder = new NotificationCompat.Builder(this)// 设置小图标.setSmallIcon(R.drawable.ic_launcher).setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher))// 设置通知标题.setContentTitle("我是通过StartService服务启动的通知")// 设置通知不能自动取消.setAutoCancel(false).setOngoing(true)// 设置通知时间,默认为系统发出通知的时间,通常不用设置// .setWhen(System.currentTimeMillis())// 设置通知内容.setContentText("请使用StopService 方法停止服务");// 通过builder.build()方法生成Notification对象,并发送通知,id=1notifyManager.notify(1, builder.build());return super.onStartCommand(intent, flags, startId);}// Service  销毁方法@Overridepublic void onDestroy() {Log.i(TAG, "----onDestroy----");notifyManager.cancelAll();super.onDestroy();}

4. 绑定模式启动绑定服务

绑定模式启动的服务会随着绑定逐渐的消亡而解除Service绑定,如果此时Service没有通过启动模式启动,则此服务将会被销毁。

绑定模式启动绑定服务的方法

绑定模式,是通过其他组件启动的Service

启动绑定模式服务的方法

    // 启动绑定服务处理方法public void BtnStartBindService(View view) {// 启动绑定服务处理方法bindService(mBindIntent, serviceConnection, Context.BIND_AUTO_CREATE);isBindService = true;Toast.makeText(ServiceMethod.this, "启动 " + mBindCount + " 次绑定服务",Toast.LENGTH_SHORT).show();}public void BtnSopBindService(View view) {if (isBindService) {// 解除绑定服务处理方法unbindService(serviceConnection);Toast.makeText(ServiceMethod.this, "解除 " + mUnBindCount + " 次绑定服务",Toast.LENGTH_SHORT).show();isBindService = false;}}

绑定服务 随绑定组件的消亡而消亡

绑定模式 生命周期回调代码如下:

    // Service 创建方法@Overridepublic void onCreate() {super.onCreate();Log.i(TAG, "----onCreate----");}// Service 绑定方法@Overridepublic IBinder onBind(Intent intent) {Log.i(TAG, "----onBind----");MyBinder myBinder = new MyBinder();return myBinder;}// Service 解除绑定方法@Overridepublic boolean onUnbind(Intent intent) {Log.i(TAG, "----onUnbind----");return super.onUnbind(intent);}// Service 销毁方法@Overridepublic void onDestroy() {Log.i(TAG, "----onDestroy----");super.onDestroy();}

绑定服务的生命周期代码打印Log信息如下:

01-03 20:32:59.422 13306-13306/com.android.program.programandroid I/BindService wjwj:: ----onCreate----
01-03 20:32:59.423 13306-13306/com.android.program.programandroid I/BindService wjwj:: -----onBind-----
01-03 20:33:09.265 13306-13306/com.android.program.programandroid I/BindService wjwj:: ----onUnbind----
01-03 20:33:09.266 13306-13306/com.android.program.programandroid I/BindService wjwj:: ----onDestroy----

绑定服务案例

功能:获取绑定模式启动 绑定服务及解除绑定服务的次数

绑定服务类

package com.android.program.programandroid.component.Service;import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;public class BindServiceMethods extends Service {private static final String TAG = "BindService wjwj:";public BindServiceMethods() {}@Overridepublic void onCreate() {super.onCreate();Log.i(TAG, "----onCreate----");}@Overridepublic IBinder onBind(Intent intent) {Log.i(TAG, "----onBind----");MyBinder myBinder = new MyBinder();return myBinder;}@Overridepublic boolean onUnbind(Intent intent) {Log.i(TAG, "----onUnbind----");return super.onUnbind(intent);}@Overridepublic void onDestroy() {Log.i(TAG, "----onDestroy----");super.onDestroy();}
}
  • 组件与绑定服务类之间的交互
 //    启动绑定服务处理方法public void BtnStartBindService(View view) {bindService(mBindIntent, serviceConnection, Context.BIND_AUTO_CREATE);isBindService = true;Toast.makeText(ServiceMethods.this,"启动 "+mBindCount+" 次绑定服务",Toast.LENGTH_SHORT).show();}//    解除绑定服务处理方法public void BtnSopBindService(View view) {if (isBindService) {unbindService(serviceConnection);Toast.makeText(ServiceMethods.this,"解除 "+mUnBindCount+" 次绑定服务",Toast.LENGTH_SHORT).show();isBindService=false;}}
  • 组件之间交互所需的 Binder 接口类
/**
* 该类提供 绑定组件与绑定服务提供接口
* */
public class MyBinder extends Binder {private int count = 0;public int getBindCount() {return ++count;}public int getUnBindCount() {return count> 0 ? count-- : 0;}
}

5. 提高服务的优先级

服务默认启动方式是后台服务,但是可以通过设置服务为前台服务,提高服务的优先级,进而避免手机内存紧张时,服务进程被杀掉。

设置前台服务的两种方法

1.设置为前台服务

//设置为前台服务
startForeground(int, Notification)

2.取消前台服务
//取消为前台服务 stopForeground(true);

startForeground 前台服务案例

功能:前台服务绑定通知信息,提高服务进程优先级,否则取消通知信息

package com.android.program.programandroid.component.Service;import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;import com.android.program.programandroid.R;public class MyStartForcegroundService extends Service {public MyStartForcegroundService() {}@Overridepublic IBinder onBind(Intent intent) {// TODO: Return the communication channel to the service.throw new UnsupportedOperationException("Not yet implemented");}@Overridepublic void onCreate() {super.onCreate();}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {if (intent.getAction().equals("start_forceground_service")) {//        获取NotificationManager实例NotificationManager notifyManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
//        实例化NotificationCompat.Builder并设置相关属性NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
//                设置小图标.setSmallIcon(R.mipmap.ic_launcher).setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
//                设置通知标题.setContentTitle("我是通过startForeground 启动前台服务通知")
//                设置通知不能自动取消.setAutoCancel(false).setOngoing(true)
//                设置通知时间,默认为系统发出通知的时间,通常不用设置
//                .setWhen(System.currentTimeMillis())
//               设置通知内容.setContentText("请使用stopForeground 方法改为后台服务");//通过builder.build()方法生成Notification对象,并发送通知,id=1
//        设置为前台服务startForeground(1, builder.build());} else if (intent.getAction().equals("stop_forceground_service")) {stopForeground(true);}return super.onStartCommand(intent, flags, startId);}
}

6. 使用AIDL接口实现远程绑定

由于内容较多,后续另开一篇详细介绍。

至此,本篇已结束,如有不对的地方,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!

转载于:https://www.cnblogs.com/wangjie1990/p/11310608.html

Broadcast 使用详解相关推荐

  1. Vue中的情侣属性$dispatch和$broadcast详解

    $dispatch 和 $broadcast 作为一对情侣 ?属性,在 Vue 1.0 中主要用来实现基于组件树结构的事件流通信 -- 通过向上或向下以冒泡的形式传递事件流,以实现嵌套父子组件的通信. ...

  2. LVS详解及基于LVS实现web服务器负载均衡

    前言 LVS(Linux Virtual Server)Linux虚拟服务器,是一个虚拟的服务器集群系统.本项目在1998年5月由章文嵩博士成立,是中国国内最早出现的自由软件项目之一.通过LVS提供的 ...

  3. [置顶] ros的navigation之———gmapping应用详解(in ros)

    gmapping是一个比较完善的地图构建开源包,使用激光和里程计的数据来生成二维地图.  博主最近也一直在使用gmapping,在前期着实被它卡了好久,因为好多东西不明白(原谅我是ros小白).  现 ...

  4. Numpy的广播机制详解(broadcasting)

    Numpy的广播机制详解(broadcasting) 广播(Broadcast)是 numpy 对不同形状(shape)的数组进行数值计算的方式, 对数组的算术运算通常在相应的元素上进行. 如果两个数 ...

  5. Docker(十四):Docker:网络模式详解

    Docker作为目前最火的轻量级容器技术,牛逼的功能,如Docker的镜像管理,不足的地方网络方面. Docker自身的4种网络工作方式,和一些自定义网络模式 安装Docker时,它会自动创建三个网络 ...

  6. Docker网络详解——原理篇

    前言 当你开始大规模使用Docker时,你会发现需要了解很多关于网络的知识.Docker作为目前最火的轻量级容器技术,有很多令人称道的功能,如Docker的镜像管理.然而,Docker同样有着很多不完 ...

  7. Android笔记——四大组件详解与总结

    android四大组件分别为activity.service.content provider.broadcast receiver. -------------------------------- ...

  8. 红帽企业集群和存储管理之DRBD+Heartbeat+NFS实现详解

    红帽企业集群和存储管理之 DRBD+Heartbeat+NFS实现详解 案例应用背景 本实验部署DRBD + HEARDBEAT + NFS 环境,建立一个高可用(HA)的文件服务器集群.在方案中,通 ...

  9. Linux 高可用(HA)集群之keepalived详解

    大纲 一.前言 二.Keepalived 详解 三.环境准备 四.LVS+Keepalived 实现高可用的前端负载均衡器 一.前言 这篇文章是前几篇文章的总结,我们先简单的总结一下我们前面讲解的内容 ...

最新文章

  1. 一些与算法有关的网站
  2. 你准备好持续交付(CD)了吗?
  3. Java程序员到架构师的推荐阅读书籍
  4. ICPR 2020国际学术竞赛:大规模无噪声精细商品图像识别
  5. SpringMVC + Apache POI 实现WEB中Excel下载功能
  6. fedora java 开发环境_在Linux(Fedora)下搭建JAVA开发环境
  7. 分布式——ACID原则 CAP理论
  8. 他为华裔写了几封信......
  9. 递归-Hanoi塔问题
  10. mysql中datetime有带时区_如何在MySQL中存储datetime与时区信息
  11. [JZOJ5424]【NOIP2017提高A组集训10.25】凤凰院凶真
  12. 打开ps显示计算机内存不足怎么办,ps显示内存不足怎么办,教你ps显示内存不足怎么办...
  13. ES(ElasticSearch) 索引创建
  14. Sketch for Mac (矢量绘图软件) v81.1
  15. Adobe Acrobat Professional 7.0
  16. 研究领域、研究课题、研究方向三者的区别
  17. 电子实训与毕业设计开放式训练装置
  18. adb命令:WIFI连接设备
  19. 利用Python爬取爬取APP上面的数据
  20. 「全网最细」:MRP1视图所有字段详解及实战应用 - 合集

热门文章

  1. 谷歌语音对接-GoogleAssistant-smart-home
  2. BCG Application Management
  3. Android Studio设置HTTP代理地址
  4. Third season eighteenth episode,hypnotic recording(maybe you can remember 吕子乔)
  5. Java基础系列【导读】
  6. R语言进行线性回归的拟合度
  7. 使用强制推送,Luca——Jenkins的开发者抹掉了Github上1个月的提交
  8. 御龙在天以前服务器信息,细数御龙在天的名人以及其崛起的服务器
  9. 关于vue告警:Closing curly brace does not appear on the same line as the subsequent block
  10. 142、解密POE交换机供电秘密,8芯网线断芯不再害怕!