Android入门笔记(通知与网络)
1 通知参考文章:《创建通知》当某个应用不在前台运行当又需要向用户发送一些信息,就可以使用 通知 来实现。通知可以在 活动、广播接收器和服务中创建,在活动中创建通知的场景比较少,因为一般的只有程序进入到后台的时候才需要使用通知。1.1 NotificationManagerNotificationManager 类用于对通知Notification 对象管理,Notificati...
1 通知
参考文章:《创建通知》
当某个应用不在前台运行当又需要向用户发送一些信息,就可以使用 通知 来实现。
通知可以在 活动、广播接收器和服务中创建,在活动中创建通知的场景比较少,因为一般的只有程序进入到后台的时候才需要使用通知。
1.1 NotificationManager
NotificationManager
类用于对通知 Notification
对象管理,NotificationManager
可以通过调用 Context
的 getSystemService()
方法获取,getSystemService()
方法可以接收一个字符串参数用于确定系统的哪个服务,此时传入 Context.NOTIFICATION_SERVICE
即可。
而获取 Notification
对象的问题在于 Android 系统的每个版本都对 通知 这个部分功能进行修改,导致 API 不稳定,解决方法就是使用 support
库中的兼容 API,support-v4
库中提供了 NotificationCompat
类,使用它可以保证兼容性地获取到空的 Notification
对象。
// channlId 是识别符,确定唯一性饥渴
Notification notification = new NotificationCompat.Builder(Context context, String channelId).build();
以上是一个空的 Notification
对象,可以在调用 build
方法之前 连缀 任意多的设置方法创建一个丰富的 Notification
对象,最后再通过 NotificationManager
类的 notify()
方法将通知显示出来,notify()
方法接受两个参数,第一个参数是 id
(需要保证每个通知的 id
都不同),第二个参数就是 Notification
实例,整体例子如下:
Button button = (Button) findViewById(R.id.notify);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new NotificationCompat.Builder(MainActivity.this, null)
.setContentTitle("这是标题")
.setContentText("这是内容")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher)
.build();
notificationManager.notify(1, notification);
}
});
1.2 PendingIntent
在上面代码中弹出的通知是不可点击的,想要编写通知的点击逻辑,就需要介绍一下 PendingIntent
对象了,如同名字的意思,PendingIntent
与 Intent
类似,都可以指明为“意图”,都可以启动活动、服务以及发送广播等。
二者不同在于,Intent
倾向立即执行某个动作,而 PendingIntent
更倾向于在某个合适的时间去执行某个动作。
PendingIntent
实例可以通过调用 PendingIntent
类的几个静态方法获取,分别是:getActivity()
、getBroadcast()
、getService()
。这几个方法接收的参数都是相同,其中的第三个参数就是 Intent
对象,用于构建出 PendingIntent
对象的“意图”。接着在 NotificationCompat.Builder
中调用 setContentIntent
方法,将PendingIntent
作为参数传入即可,例子代码如下:
Button button = (Button) findViewById(R.id.notify);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, NotificationActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivities(MainActivity.this, 0, new Intent[]{intent}, 0);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new NotificationCompat.Builder(MainActivity.this, null)
.setContentTitle("这是标题")
.setContentText("这是内容")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.build();
notificationManager.notify(2, notification);
}
});
其中点击了通知后,系统状态上的通知图标也不会消失,因为此时需要显式地调用消失的方法,一种是在 NotificationCompat.Builder
中调用 setAutoCancel()
方法,第二种是显式的调用 NotificationManager
中的 cancel()
方法将它取消,此时传入的就是此前调用 notify
方法时设置的唯一辨识值。
2 网络技术
2.1 HttpURLConnection
在过去,Android 上发送 HTTP 请求一般有两种方式:HttpURLConnection
和 HttpClient
,不过由于 HttpClient
的 api 过多,且扩展困难,所以不建议使用它。
在使用 HttpURLConnection
之前需要声明权限,在 AndroidManifest.xml
文件中添加以下声明:
<uses-permission android:name="android.permission.INTERNET"/>
同时为了用户数据和设备的安全,新的 Android 系统要求默认使用加密连接,这意味着将禁止 App 使用所有未加密的连接,因此直接使用 HttpURLConnection
进行非加密的明文流量的 http 网络请求会出现异常,而 https 请求则不会收到影响,此时的解决方法有三种(OkHttp
同理):
- APP改用 https 请求
targetSdkVersion
降到27
以下- 更改网络安全配置,直接在
AndroidManifest.xml
文件中的application
标签中添加android:usesCleartextTraffic="true"
属性
使用 HttpURLConnection
需要新建一个子线程,否则会报错,具体逻辑如下:
private void sendRequest() {
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
// 创建 uri
URL url = new URL("https://www.baidu.com");
connection = (HttpURLConnection) url.openConnection();
// 设置请求类型
connection.setRequestMethod("GET");
// 设置链接时长
connection.setConnectTimeout(8000);
// 设置读取时长
connection.setReadTimeout(8000);
// 获取返回数据
InputStream in = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(in));
StringBuilder reponse = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
reponse.append(line);
}
// Only the original thread that created a view hierarchy can touch its views.
// TextView textView = (TextView) findViewById(R.id.text);
// textView.setText(reponse);
Log.d("接受到数据", reponse.toString());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭资源
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (connection != null) {
connection.disconnect();
}
}
}
}).start();
}
其中由于请求需要在子线程进行,而 Android 并不允许在子线程中进行 UI 操作,所以如果想要在获取到数据后显示在界面上就需要使用到 runOnUiThread()
方法了,然后在里面编写更新 UI 元素的逻辑,最后再例子代码如下:
private void showResponse(final String response) {
runOnUiThread(new Runnable() {
@Override
public void run() {
TextView textView = (TextView) findViewById(R.id.text);
textView.setText(response);
}
});
}
如果请求方法使用 Post
,即只需在获取输入流之前将要提交的数据写出即可,注意每条数据都要以键值对的形式存在,数据与数据之间用 &
符号隔开,如:
// 设置请求类型
connection.setRequestMethod("POST");
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
out.writeBytes("username=admin&pw=123456");
2.2 OkHttp
OkHttp
是一个开源库,所以使用它之前需要先添加依赖,如下:
implementation 'com.squareup.okhttp3:okhttp:3.4.1'
OkHttp 的用法如同 HttpURLConnection
,首先需要创建一个 OkHttpClient
实例,然后创建一个 Request
对象用来封装一些请求信息,最后调用 OkHttpClient
对象的 newCall
方法创建一个 Call
对象,并调用它的 execute
方法来发送请求,同样的,以上逻辑都需要在子线程中进行,例子代码如下:
private void sendReuqestOfOkHttp() {
new Thread(new Runnable() {
@Override
public void run() {
// 创建 OkHttpClient
OkHttpClient client = new OkHttpClient();
// 想要发起一条 HTTP 请求,就需要创建一个 Request 对象
// 与通知 Notification 的用法类似,在使用 build 方法之前,可以连缀多个方法来丰富 reqeust 对象
Request request = new Request.Builder().url("https://www.baidu.com")
.build();
// 调用 OkHttpClient 对象的 newCall 方法创建一个 Call 对象,并调用它的 execute 方法来执行请求
// 从而获取 response 对象
try {
Response response = client.newCall(request).execute();
// 调用 response 对象的 body().string() 方法可以获取返回数据的字符串格式
showResponse(response.body().string());
Log.d("OkHttp 接收的数据", response.body().toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
而如果想要使用 Post
请求,则还需要创建 RequestBody
对象来存放待提交的参数,最后在 Request.Builder
中使用 post
方法,将其传入,例子代码如下:
// 创建 RequestBody 对象
RequestBody requestBody = new FormBody.Builder()
.add("userName", "admin")
.add("pw", "123")
.build();
// 创建 request
Request request = new Request.Builder().url("https://www.baidu.com")
.post(requestBody)
.build();
更多推荐
所有评论(0)