본 실험은 HttpURLConnection 및 Handler 메커니즘 등을 조사하기 위한 것으로, 입력된 URL을 통해 URL의 html 파일을 획득하여 인터페이스에 표시하는 것으로 렌더링은 다음과 같다.
첫 번째 XML 코드:
activity_main66.xml
<?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">
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="5dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="5dp"
android:layout_marginBottom="5dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="9"
android:gravity="center"
android:orientation="horizontal">
<EditText
android:id="@+id/et_url"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="9"
android:ems="10"
android:layout_marginRight="5dp"
android:inputType="textPersonName"
android:hint="请输入网址"
android:text="" />
<Button
android:id="@+id/btn_search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="查看" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="@+id/txt_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="" />
</LinearLayout>
</ScrollView>
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
논리적 자바 코드:
MainActivity66
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.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class MainActivity66 extends AppCompatActivity {
TextView txt_content;
EditText et_url;
Button btn_search;
final int REQUEST_CODE = 1;
Handler handler = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main66);
txt_content = findViewById(R.id.txt_content);
et_url = findViewById(R.id.et_url);
btn_search = findViewById(R.id.btn_search);
//动态权限处理
if (ContextCompat.checkSelfPermission(this, Manifest.permission.INTERNET)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.INTERNET}, REQUEST_CODE);
}
//Handler处理
handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message message) {
String str = (String) message.obj;
txt_content.setText(str);
return true;
}
});
btn_search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String urlStr = et_url.getText().toString().trim();
if(urlStr.equals("")){
Toast.makeText(MainActivity66.this, "请输入网址",Toast.LENGTH_LONG).show();
}else{
new Thread(){ //网络访问必须放在线程中进行,创建一个无名线程对象
@Override
public void run() {
URL url = null;
try {
url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
InputStream is = conn.getInputStream();
byte a = (byte) is.read(); //先读取1个字节
byte[] buffer = new byte[is.available()]; //再定义剩余的字节数组
is.read(buffer); //读取剩余的字节到buffer中
//定义字节数组输出流类对象,目的是将开始的1个字节和后面的字节组合到一起
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(a);
out.write(buffer);
String str = out.toString();
Message msg = new Message(); //定义消息对象
msg.obj = str;
handler.sendMessage(msg); //将消息发送到消息队伍中
conn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}.start(); //启动线程
}
}
});
}
//动态权限请求回调方法
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CODE) {
if (grantResults.length != 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "权限开启成功", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "权限开启失败", Toast.LENGTH_LONG).show();
}
}
}
}
또한 일부 네트워크 구성도 수행해야 합니다.
AndroidManifest.xml 파일에 명령문 추가: 네트워크 권한 선언
<uses-permission android:name="android.permission.INTERNET" />
또한 상위 버전의 Android도 네트워크 보안 액세스 구성을 완료해야 합니다.
res 폴더 아래에 xml 폴더를 만들고 새 파일 network_config.xml을 만듭니다.
내용은 다음과 같습니다.
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true"/>
</network-security-config>
또한 AndroidManifest.xml로 돌아가서 문장을 추가해야 합니다.
android:networkSecurityConfig="@xml/network_config"