工程目录:



app-MainActivity

package com.example.app;import androidx.appcompat.app.AppCompatActivity;import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;public class MainActivity extends AppCompatActivity implements View.OnClickListener{@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);findViewById(R.id.btn1).setOnClickListener(this);findViewById(R.id.btn2).setOnClickListener(this);findViewById(R.id.btn3).setOnClickListener(this);findViewById(R.id.btn4).setOnClickListener(this);findViewById(R.id.btn5).setOnClickListener(this);}@Overridepublic void onClick(View v) {Intent intent = getPackageManager().getLaunchIntentForPackage("com.example.app1");switch(v.getId()){case R.id.btn1:intent = getPackageManager().getLaunchIntentForPackage("com.example.app1");break;case R.id.btn2:intent = getPackageManager().getLaunchIntentForPackage("com.example.app2");break;case R.id.btn3:intent = getPackageManager().getLaunchIntentForPackage("com.example.app3");break;case R.id.btn4:intent = getPackageManager().getLaunchIntentForPackage("com.example.app4");break;case R.id.btn5:intent = getPackageManager().getLaunchIntentForPackage("com.example.app5");break;}if (intent == null) {Toast.makeText(getApplicationContext(),"没有安装该app",Toast.LENGTH_SHORT).show();} else {startActivity(intent);}}
}

Layout

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><Buttonandroid:id="@+id/btn1"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="系统广播,接收短信放音乐(静态注册)" /><Buttonandroid:id="@+id/btn2"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="短信广播,接收短信显示内容(静态注册)" /><Buttonandroid:id="@+id/btn3"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="系统广播,按钮停止音乐服务(停止服务)" /><Buttonandroid:id="@+id/btn4"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="自定义广播(动态注册)" /><Buttonandroid:id="@+id/btn5"android:layout_width="match_parent"android:layout_height="wrap_content"android:textAllCaps="false"android:text="使用PendingIntent创建通知" /></LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

app1-MainActivity

package com.example.app1;import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;import android.Manifest;
import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.widget.Toast;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED){ActivityCompat.requestPermissions(this,new String[]{"android.permission.RECEIVE_SMS"},1);}}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);switch (requestCode){case 1:if(grantResults[0]!=PackageManager.PERMISSION_GRANTED){Toast.makeText(this, "未授权,无法实现预定的功能!", Toast.LENGTH_SHORT).show();finish();}}}@Overrideprotected void onDestroy() {  //按手机返回键时触发super.onDestroy();//创建组件对象ComponentName receiver = new ComponentName(this,SmsReceiver.class);//获取包管理器对象PackageManager pm = getPackageManager();//禁用一个静态注册的广播接收者pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);}
}

SmsReceiver

package com.example.app1;import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;public class SmsReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {MediaPlayer mediaPlayer = MediaPlayer.create(context,R.raw.cc);mediaPlayer.start();}
}

manifestes

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.app1"><uses-permission android:name="android.permission.RECEIVE_SMS"/><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"><receiverandroid:name=".SmsReceiver"android:enabled="true"android:exported="true"><intent-filter><action android:name="android.provider.Telephony.SMS_RECEIVED"/></intent-filter></receiver><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application></manifest>

app2-manifestes

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.app2"><uses-permission android:name="android.permission.RECEIVE_SMS"/><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"><receiverandroid:name=".SmsReceiver"android:enabled="true"android:exported="true"><intent-filter><action android:name="android.provider.Telephony.SMS_RECEIVED"/></intent-filter></receiver><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application></manifest>

MainActivity

package com.example.app2;import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;import android.Manifest;
import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.widget.Toast;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED){ActivityCompat.requestPermissions(this,new String[]{"android.permission.RECEIVE_SMS"},1);}}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);switch (requestCode){case 1:if(grantResults[0]!=PackageManager.PERMISSION_GRANTED){Toast.makeText(this, "未授权,无法实现预定的功能!", Toast.LENGTH_SHORT).show();finish();}}}@Overrideprotected void onDestroy() {  //按手机返回键时触发super.onDestroy();//创建组件对象ComponentName receiver = new ComponentName(this,SmsReceiver.class);//获取包管理器对象PackageManager pm = getPackageManager();//禁用一个静态注册的广播接收者pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);}
}

SmsReceiver

package com.example.app2;import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.widget.Toast;import java.text.SimpleDateFormat;
import java.util.Date;public class SmsReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {//获取发送短信意图对象携带的数据Bundle bundle = intent.getExtras();if(bundle != null){//可使用动态调试,查看短信数据结构Object[] pdus = (Object[]) bundle.get("pdus");//发送方的一条短信可能被分割、分多次发送SmsMessage[] msgs = new SmsMessage[pdus.length];for (int i = 0; i < msgs.length; i++) {byte[] pdu = (byte[]) pdus[i];//获取分段的短信msgs[i]= SmsMessage.createFromPdu(pdu);}//构建短信相关信息字符串StringBuilder strb=new StringBuilder();for(SmsMessage msg:msgs){strb.append("\n发短信人电话:\n").append(msg.getDisplayOriginatingAddress()).append("\n短信内容:\n").append(msg.getMessageBody());//接收时间Date date=new Date(msg.getTimestampMillis());SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");strb.append("\n短信接收时间:\n").append(sdf.format(date));}//在context指示的上下文(就是模块的MainActivity)里打Toast消息Toast.makeText(context, strb, Toast.LENGTH_LONG).show();}}
}

app3-manifestes

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.app3"><uses-permission android:name="android.permission.RECEIVE_SMS"/><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"><receiverandroid:name=".SmsReceiver"android:enabled="true"android:exported="true"><intent-filter><action android:name="android.provider.Telephony.SMS_RECEIVED"/></intent-filter></receiver><serviceandroid:name=".MyAudioService"android:enabled="true"android:exported="true" /><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application></manifest>

MainActivity

package com.example.app3;import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;public class MainActivity extends AppCompatActivity {private Button btnStop;private boolean isCast; //是否为广播激活@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED){ActivityCompat.requestPermissions(this,new String[]{"android.permission.RECEIVE_SMS"},1);}btnStop=findViewById(R.id.btnStop);Intent intent = getIntent(); //获取广播意图对象isCast = intent.getBooleanExtra("iscast", false);  //默认值为falsebtnStop.setEnabled(isCast);   //设置停止按钮可用和单击监听if(isCast) Toast.makeText(this, "正在播放音乐...", Toast.LENGTH_SHORT).show();btnStop.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v){//显式服务调用意图(非绑定式)Intent intent=new Intent(MainActivity.this,MyAudioService.class);//在Activity组件里,停止音乐播放服务stopService(intent);finish();  //销毁本活动}});}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);switch (requestCode){case 1:if(grantResults[0]!= PackageManager.PERMISSION_GRANTED){Toast.makeText(this, "未授权,无法实现预定的功能!", Toast.LENGTH_SHORT).show();finish();}else{Toast.makeText(this, "请发一条短信验证...", Toast.LENGTH_SHORT).show();}}}
}

MyAudioService

package com.example.app3;import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;public class MyAudioService extends Service {MediaPlayer mediaPlayer;@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {mediaPlayer  = MediaPlayer.create(this,R.raw.cc);mediaPlayer.start();}@Overridepublic void onDestroy() {mediaPlayer.stop();}
}

SmsReceiver

package com.example.app3;import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;public class SmsReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Intent serviceIntent = new Intent(context, MyAudioService.class);//在广播组件里,通过上下文对象启动音乐播放服务组件context.startService(serviceIntent);//新建调用Activity组件的意图Intent activityIntent = new Intent(context, MainActivity.class);activityIntent.putExtra("iscast", true);  //携带数据//新建栈用来存放被启动的Activity(当已经存在时,只做移动处理)activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//在广播组件里,通过上下文对象启动Activity组件context.startActivity(activityIntent);}
}

Layout

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><Buttonandroid:id="@+id/btnStop"android:layout_width="match_parent"android:layout_height="wrap_content"android:textAllCaps="false"android:text="Stop Music" /></LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

app4-MainActivity

package com.example.app4;import androidx.appcompat.app.AppCompatActivity;import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;public class MainActivity extends AppCompatActivity {private TextView tv;  //用于显示接收到的广播信息private BroadcastReceiver myReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {Bundle mybundle =  intent.getExtras();String str1 = mybundle.getString("data1");String str2 = mybundle.getString("data2");Toast.makeText(context, str1+" " +str2, Toast.LENGTH_LONG).show();tv.setText(str1+" " +str2);}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//使用意图过滤器类IntentFilter动态注册广播接收者IntentFilter myintentfliter = new IntentFilter();myintentfliter.addAction("com.example.broadcast.MY_BROADCAST");registerReceiver(myReceiver, myintentfliter);tv = findViewById(R.id.tv);findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View arg0) {Intent myintent = new Intent("com.example.broadcast.MY_BROADCAST");Bundle  bundle = new Bundle();bundle.putString("data1", "自定义广播与接收案例");bundle.putString("data2", "我是自定义的字符串!");myintent.putExtras(bundle);  //捆绑数据sendBroadcast(myintent);   //发送广播try {Thread.sleep(1000);  //休眠一下,模拟广播可能存在的延迟} catch (InterruptedException e) {e.printStackTrace();}}});}
}

Layout

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><Buttonandroid:id="@+id/btn"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="运行时快速发广播" /><TextViewandroid:id="@+id/tv"android:gravity="center"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="TextView" /></LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

app5-MainActivity

package com.example.app5;import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;public class MainActivity extends AppCompatActivity {NotificationManager notificationManager;  //通知管理器NotificationCompat.Builder builder;  //通知构造器(与Android版本相关)Button btn_notification;  //按钮boolean isCreate = false; //通知未创建@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);btn_notification = findViewById(R.id.btn_notification);//创建设置意图对象Intent intent = new Intent(Settings.ACTION_SETTINGS);//创建延期意图对象PendingIntent pendingIntent = PendingIntent.getActivity(this,0,intent,0);//获取通知管理器notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);//使用通知构造器builder = new NotificationCompat.Builder(this,getPackageName());//构建通知内容builder.setSmallIcon(R.drawable.ic_launcher_foreground)  //图标使用矢量图形.setContentTitle("进入设置界面").setContentText("点击进入设置界面").setWhen(System.currentTimeMillis()).setDefaults(Notification.DEFAULT_SOUND).setContentIntent(pendingIntent);  //关键方法if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { //Android 8.0NotificationChannel channel = new NotificationChannel( //Android 8.0需要创建通知频道getPackageName(),"MusicNotify",NotificationManager.IMPORTANCE_DEFAULT);notificationManager.createNotificationChannel(channel);}btn_notification.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {isCreate = !isCreate;  //在创建与取消之间切换TextView tv=findViewById(R.id.hide_tv);if(isCreate) {  //如果准备创建通知//发送通知至通知栏notificationManager.notify(1, builder.build());  //发通知tv.setVisibility(View.VISIBLE);  //设置可见btn_notification.setText("取消通知");}else {notificationManager.cancel(1);  //取消通知btn_notification.setText("创建通知");tv.setVisibility(View.INVISIBLE);  //设置不可见}}});}
}

Layout

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><Buttonandroid:id="@+id/btn_notification"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="发通知" /><TextViewandroid:id="@+id/hide_tv"android:layout_width="match_parent"android:layout_height="wrap_content"android:visibility="invisible"android:gravity="center"android:text="通知已创建,请下拉查看!" /></LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

app1:

app2:

app3:

app4:

app5:

Android的Broadcase的使用(读取短信和创建通知)相关推荐

  1. Android读取短信和联系人

    读取短信和联系人经常会用到,要了解的是这是内容提供者(contentProvider)的知识点,大家都知道数据库是在data-->data 对应的包目录下,其他应用是不可以访问到的,如果有些数据 ...

  2. Android 读取短信内容(模拟器)

    读取短信内容 读取短信的内容就要知道短信放在哪里,然后通过查询语句把结果封装到实体类的List中,再全部打印出来即可. 下面是具体的代码: activity_main.xml <?xml ver ...

  3. androidの读取短信内容

    androidの读取短信内容 1. 读取短信内容,很简单,直接上代码 <span style="font-size:14px;"> public Uri SMS_INB ...

  4. Android接收读取短信内容

    一.注册短信接收广播: public static final String SMS_BORADCAST = "android.provider.Telephony.SMS_RECEIVED ...

  5. 自动化软件测试 - 通过 Android Studio 开发 App 自动拦截读取短信验证码

        之前一期介绍了怎样通过 Python 的代码去获取短信验证码去进行软件测试,这一期将主要介绍 怎样 通过 Android Studio 开发 App 自动拦截读取短信验证码.     Andr ...

  6. Android开发学习之电话、短信、联系人

    作为一部手机,最重要的功能当属电话.短信.联系人了,所以今天想和大家分享的是关于Android电话.短信.联系人这块的API接口. 1.通话记录的获取 List<TelePhoneRecord& ...

  7. android studio内容提供者(查看短信的猫)点击查看短信,闪退,无法显示短信内容。(附程序源代码,以及解决办法)

    报错的问题: Permission Denial: readingcom.android.providers.telephony.SmsProvider uri content://sms/ 找到问题 ...

  8. 读取短信并复制验证码小工具

    获取短信有两种方式,第一种是通过广播接收器,第二种通过读取短信数据库. 第一种: 静态注册了一个广播,通过接收包含android.provider.Telephony.SMS_RECEIVED动作的广 ...

  9. 自动化软件测试 - 利用短信转发器结合Selenium读取短信验证码

        上一篇博客介绍了怎样通过 Android Studio 开发 App 自动拦截读取短信验证码,今天将介绍另外一种非开发App 的方法去实现,通过利用第三方工具短信转发器 结合 Selenium ...

最新文章

  1. 离散周期信号的傅里叶变换
  2. 五大板块(5)——字符串
  3. strong vs copy
  4. 随想录(qemu的学习)
  5. html怎么加漂浮物,全面开展水面漂浮物清理专项行动
  6. 《程序设计技术》第四章例程
  7. 快排序和堆排序,最小堆、最大堆
  8. 什么是网络安全网格?
  9. catia二次开发:检查文件类型 检查部件类型 产品名称 通过交互选择约束两个零件轴系重合 添加自定义属性,MasterShapeRepresentation
  10. 一个优秀程序员可抵五个普通程序员!
  11. 联想服务器装系统不能加载硬盘,联想电脑重装系统读不出硬盘怎么办
  12. BH1750光照传感器超详细攻略(从原理到代码讲解,看完你就懂了)
  13. 在uni-app的textarea中输入纯数字或者英文不换行的问题
  14. 万恶的ie8 hack问题
  15. 计算机钥匙英语,计算机加锁--把U盘变成打开电脑的钥匙 - 信息科学 - 小木虫 - 学术 科研 互动社区...
  16. 服务器主机型号,服务器的主机型号
  17. html界面等待状态,html页面Loading效果实现:加载新页面前的等待过渡画面
  18. 服务器开机显示器没反应,老司机教你开机显示器没反应怎么办
  19. GALIL运动控制卡维修控制器维修DMC-1840
  20. (十五)路过师大 - 5

热门文章

  1. 普通程序员想转人工智能,不知道它?别想了!
  2. 物联网火爆,开发者却遇到这个大难题!
  3. 程序员伪装 AI 编程,竟骗来 2 亿的投资!
  4. @开发者 想成为行业应用开发的实力派吗?TA 或者能帮到你
  5. 机器学习模型实战!如何从 900 万张图片中对 600 类照片进行分类? | 技术头条...
  6. 罗永浩望着 7 年前的罗永浩
  7. 从 C++98 到 C++17,元编程是如何演进的? | 技术头条
  8. 比特币蒸发 1 万亿;中兴入局无人驾驶;特斯拉 Model 3 在华降价 | 极客头条
  9. 微软智能云三驾马车 Azure、Office 365、Dynamics 365 齐聚中国
  10. 苹果说:没错,我就是故意让旧 iPhone 变慢的!