Android的Broadcase的使用(读取短信和创建通知)
工程目录:
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的使用(读取短信和创建通知)相关推荐
- Android读取短信和联系人
读取短信和联系人经常会用到,要了解的是这是内容提供者(contentProvider)的知识点,大家都知道数据库是在data-->data 对应的包目录下,其他应用是不可以访问到的,如果有些数据 ...
- Android 读取短信内容(模拟器)
读取短信内容 读取短信的内容就要知道短信放在哪里,然后通过查询语句把结果封装到实体类的List中,再全部打印出来即可. 下面是具体的代码: activity_main.xml <?xml ver ...
- androidの读取短信内容
androidの读取短信内容 1. 读取短信内容,很简单,直接上代码 <span style="font-size:14px;"> public Uri SMS_INB ...
- Android接收读取短信内容
一.注册短信接收广播: public static final String SMS_BORADCAST = "android.provider.Telephony.SMS_RECEIVED ...
- 自动化软件测试 - 通过 Android Studio 开发 App 自动拦截读取短信验证码
之前一期介绍了怎样通过 Python 的代码去获取短信验证码去进行软件测试,这一期将主要介绍 怎样 通过 Android Studio 开发 App 自动拦截读取短信验证码. Andr ...
- Android开发学习之电话、短信、联系人
作为一部手机,最重要的功能当属电话.短信.联系人了,所以今天想和大家分享的是关于Android电话.短信.联系人这块的API接口. 1.通话记录的获取 List<TelePhoneRecord& ...
- android studio内容提供者(查看短信的猫)点击查看短信,闪退,无法显示短信内容。(附程序源代码,以及解决办法)
报错的问题: Permission Denial: readingcom.android.providers.telephony.SmsProvider uri content://sms/ 找到问题 ...
- 读取短信并复制验证码小工具
获取短信有两种方式,第一种是通过广播接收器,第二种通过读取短信数据库. 第一种: 静态注册了一个广播,通过接收包含android.provider.Telephony.SMS_RECEIVED动作的广 ...
- 自动化软件测试 - 利用短信转发器结合Selenium读取短信验证码
上一篇博客介绍了怎样通过 Android Studio 开发 App 自动拦截读取短信验证码,今天将介绍另外一种非开发App 的方法去实现,通过利用第三方工具短信转发器 结合 Selenium ...
最新文章
- 离散周期信号的傅里叶变换
- 五大板块(5)——字符串
- strong vs copy
- 随想录(qemu的学习)
- html怎么加漂浮物,全面开展水面漂浮物清理专项行动
- 《程序设计技术》第四章例程
- 快排序和堆排序,最小堆、最大堆
- 什么是网络安全网格?
- catia二次开发:检查文件类型 检查部件类型 产品名称 通过交互选择约束两个零件轴系重合 添加自定义属性,MasterShapeRepresentation
- 一个优秀程序员可抵五个普通程序员!
- 联想服务器装系统不能加载硬盘,联想电脑重装系统读不出硬盘怎么办
- BH1750光照传感器超详细攻略(从原理到代码讲解,看完你就懂了)
- 在uni-app的textarea中输入纯数字或者英文不换行的问题
- 万恶的ie8 hack问题
- 计算机钥匙英语,计算机加锁--把U盘变成打开电脑的钥匙 - 信息科学 - 小木虫 - 学术 科研 互动社区...
- 服务器主机型号,服务器的主机型号
- html界面等待状态,html页面Loading效果实现:加载新页面前的等待过渡画面
- 服务器开机显示器没反应,老司机教你开机显示器没反应怎么办
- GALIL运动控制卡维修控制器维修DMC-1840
- (十五)路过师大 - 5
热门文章
- 普通程序员想转人工智能,不知道它?别想了!
- 物联网火爆,开发者却遇到这个大难题!
- 程序员伪装 AI 编程,竟骗来 2 亿的投资!
- @开发者 想成为行业应用开发的实力派吗?TA 或者能帮到你
- 机器学习模型实战!如何从 900 万张图片中对 600 类照片进行分类? | 技术头条...
- 罗永浩望着 7 年前的罗永浩
- 从 C++98 到 C++17,元编程是如何演进的? | 技术头条
- 比特币蒸发 1 万亿;中兴入局无人驾驶;特斯拉 Model 3 在华降价 | 极客头条
- 微软智能云三驾马车 Azure、Office 365、Dynamics 365 齐聚中国
- 苹果说:没错,我就是故意让旧 iPhone 变慢的!