第一次尝试 OkHttp 作为客户端时崩溃
Crashing when first time try OkHttp as a client
我有一些项目,实时发送蓝牙低功耗的 RSSI 和 MAC。我想尝试使用 http 协议,我找到了 OkHttp 库。但是当我 运行 使用 OkHttp 时,我的软件崩溃了。
我的错误
2022-04-02 10:22:56.681 20521-20521/com.example.android_http D/Logger: State Check
2022-04-02 10:22:57.146 20521-20521/com.example.android_http D/Logger: Recive data 6C:70:3C:0A:99:43
2022-04-02 10:22:57.217 20521-20521/com.example.android_http D/AndroidRuntime: Shutting down VM
2022-04-02 10:22:57.220 20521-20521/com.example.android_http E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android_http, PID: 20521
Theme: themes:{}
java.lang.RuntimeException: Error receiving broadcast Intent { act=android.bluetooth.device.action.FOUND flg=0x10 (has extras) } in com.example.android_http.MainActivity@6febfe0
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:892)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5456)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1273)
at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:110)
at libcore.io.IoBridge.connectErrno(IoBridge.java:154)
at libcore.io.IoBridge.connect(IoBridge.java:122)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:183)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:452)
at java.net.Socket.connect(Socket.java:884)
at okhttp3.internal.platform.AndroidPlatform.connectSocket(AndroidPlatform.kt:63)
at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.kt:295)
at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:207)
at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226)
at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)
at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)
at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
at okhttp3.internal.connection.RealCall.execute(RealCall.kt:154)
at com.example.android_http.postActivity.post(postActivity.java:22)
at com.example.android_http.MainActivity.onReceive(MainActivity.java:118)
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:882)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5456)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
我确定是 OkHttp 导致应用程序崩溃。因为在使用 OkHttp 之前应用程序很好。
这是我的mainActivity.java
package com.example.android_http;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
private Button btnTurn;
private boolean state = false;
private BluetoothAdapter bluetoothAdapter;
public static final int REQUEST_ACCESS_COARSE_LOCATION = 1;
public String data;
postActivity ClientHttp = new postActivity();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnTurn = findViewById(R.id.btnTurn);
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
stateCheck();
Log.d("Logger", "State Check");
handler.postDelayed(this, 1000);
}
}, 1000);
btnTurn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(!state){
btnTurn.setText("Turn Off");
state = true;
}else{
btnTurn.setText("Turn On");
state = false;
}
}
});
}
public void stateCheck(){
if (state){
if (bluetoothAdapter!=null & bluetoothAdapter.isEnabled()) {
if(checkCoarsePermission()){
Log.d("Logger", "Discover");
bluetoothAdapter.startDiscovery();
}
}
}
}
private boolean checkCoarsePermission(){
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_COARSE_LOCATION},
REQUEST_ACCESS_COARSE_LOCATION);
return false;
}else {
return true;
}
}
@Override
protected void onResume() {
super.onResume();
registerReceiver(devicesFoundReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
registerReceiver(devicesFoundReceiver, new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED));
registerReceiver(devicesFoundReceiver, new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED));
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(devicesFoundReceiver);
}
private final BroadcastReceiver devicesFoundReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action= intent.getAction();
if(BluetoothDevice.ACTION_FOUND.equals(action)){
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
int rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI,Short.MIN_VALUE);
String RSSI = String.valueOf(rssi);
Toast.makeText(context.getApplicationContext(),"rssi "+RSSI+" "+device.getAddress(),Toast.LENGTH_SHORT).show();
Log.d("Logger", "Recive data "+device.getAddress());
data = "RSSI: "+RSSI+" MAC: "+device.getAddress();
String data_json = "{'rssi':'"+RSSI+"','MAC':'"+device.getAddress()+"'";
try{
String response = ClientHttp.post("http://192.168.6.56:3000/clicked",data_json);
Log.d("Logger",response);
}catch (IOException e){
Log.e("Logger","Error Function to send");
}
// try{
// //GetText(mUrl,data);
// }catch (IOException e){
// Log.e("Logger","Error Function to send");
// }
}else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
}else if(BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)){
}
}
};
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case REQUEST_ACCESS_COARSE_LOCATION:
if(grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
Toast.makeText(this,"ALLOWED", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(this,"Forbidden",Toast.LENGTH_SHORT).show();
} break;
}
}
}
这是我的postActivity.java
package com.example.android_http;
import java.io.IOException;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class postActivity {
public static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
final OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(json, JSON);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
}
}
我的gradle
dependencies {
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation("com.squareup.okhttp3:okhttp:4.9.3")
implementation("com.squareup.okhttp3:okhttp")
}
为了更清楚的解释,我在 Android Studio 中使用 JAVA 和 Android 6.0 的 API 进行了编程。
我的问题很简单,如何解决这个问题?为什么会崩溃?请不要关闭我的问题!!!我只是个初学者!!!这个问题在其他 post 中不存在,我尝试用我的原始代码实现另一个 post。但仍然失败。
谢谢。
错误是在主线程(a.k.a.UI线程)上执行网络请求引起的。通常,主线程禁止线程阻塞操作(如文件读取、网络请求)。这样做是为了避免 App Not responding
错误。
在你的 mainActivity.java
中,因为 BroadcastReceiver#onReceive
是在主线程上执行的。 (参考:)。在这个 onReceive
函数中,您正在尝试发出网络请求。
只是,使用处理程序和 post 对后台线程(或任何其他线程)的网络调用,这将解决您的问题。
我有一些项目,实时发送蓝牙低功耗的 RSSI 和 MAC。我想尝试使用 http 协议,我找到了 OkHttp 库。但是当我 运行 使用 OkHttp 时,我的软件崩溃了。
我的错误
2022-04-02 10:22:56.681 20521-20521/com.example.android_http D/Logger: State Check
2022-04-02 10:22:57.146 20521-20521/com.example.android_http D/Logger: Recive data 6C:70:3C:0A:99:43
2022-04-02 10:22:57.217 20521-20521/com.example.android_http D/AndroidRuntime: Shutting down VM
2022-04-02 10:22:57.220 20521-20521/com.example.android_http E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android_http, PID: 20521
Theme: themes:{}
java.lang.RuntimeException: Error receiving broadcast Intent { act=android.bluetooth.device.action.FOUND flg=0x10 (has extras) } in com.example.android_http.MainActivity@6febfe0
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:892)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5456)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1273)
at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:110)
at libcore.io.IoBridge.connectErrno(IoBridge.java:154)
at libcore.io.IoBridge.connect(IoBridge.java:122)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:183)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:452)
at java.net.Socket.connect(Socket.java:884)
at okhttp3.internal.platform.AndroidPlatform.connectSocket(AndroidPlatform.kt:63)
at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.kt:295)
at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:207)
at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:226)
at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:106)
at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:74)
at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:255)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
at okhttp3.internal.connection.RealCall.execute(RealCall.kt:154)
at com.example.android_http.postActivity.post(postActivity.java:22)
at com.example.android_http.MainActivity.onReceive(MainActivity.java:118)
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:882)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5456)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
我确定是 OkHttp 导致应用程序崩溃。因为在使用 OkHttp 之前应用程序很好。
这是我的mainActivity.java
package com.example.android_http;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
private Button btnTurn;
private boolean state = false;
private BluetoothAdapter bluetoothAdapter;
public static final int REQUEST_ACCESS_COARSE_LOCATION = 1;
public String data;
postActivity ClientHttp = new postActivity();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnTurn = findViewById(R.id.btnTurn);
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
stateCheck();
Log.d("Logger", "State Check");
handler.postDelayed(this, 1000);
}
}, 1000);
btnTurn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(!state){
btnTurn.setText("Turn Off");
state = true;
}else{
btnTurn.setText("Turn On");
state = false;
}
}
});
}
public void stateCheck(){
if (state){
if (bluetoothAdapter!=null & bluetoothAdapter.isEnabled()) {
if(checkCoarsePermission()){
Log.d("Logger", "Discover");
bluetoothAdapter.startDiscovery();
}
}
}
}
private boolean checkCoarsePermission(){
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_COARSE_LOCATION},
REQUEST_ACCESS_COARSE_LOCATION);
return false;
}else {
return true;
}
}
@Override
protected void onResume() {
super.onResume();
registerReceiver(devicesFoundReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
registerReceiver(devicesFoundReceiver, new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED));
registerReceiver(devicesFoundReceiver, new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED));
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(devicesFoundReceiver);
}
private final BroadcastReceiver devicesFoundReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action= intent.getAction();
if(BluetoothDevice.ACTION_FOUND.equals(action)){
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
int rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI,Short.MIN_VALUE);
String RSSI = String.valueOf(rssi);
Toast.makeText(context.getApplicationContext(),"rssi "+RSSI+" "+device.getAddress(),Toast.LENGTH_SHORT).show();
Log.d("Logger", "Recive data "+device.getAddress());
data = "RSSI: "+RSSI+" MAC: "+device.getAddress();
String data_json = "{'rssi':'"+RSSI+"','MAC':'"+device.getAddress()+"'";
try{
String response = ClientHttp.post("http://192.168.6.56:3000/clicked",data_json);
Log.d("Logger",response);
}catch (IOException e){
Log.e("Logger","Error Function to send");
}
// try{
// //GetText(mUrl,data);
// }catch (IOException e){
// Log.e("Logger","Error Function to send");
// }
}else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
}else if(BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)){
}
}
};
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case REQUEST_ACCESS_COARSE_LOCATION:
if(grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
Toast.makeText(this,"ALLOWED", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(this,"Forbidden",Toast.LENGTH_SHORT).show();
} break;
}
}
}
这是我的postActivity.java
package com.example.android_http;
import java.io.IOException;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class postActivity {
public static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
final OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(json, JSON);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
}
}
我的gradle
dependencies {
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation("com.squareup.okhttp3:okhttp:4.9.3")
implementation("com.squareup.okhttp3:okhttp")
}
为了更清楚的解释,我在 Android Studio 中使用 JAVA 和 Android 6.0 的 API 进行了编程。
我的问题很简单,如何解决这个问题?为什么会崩溃?请不要关闭我的问题!!!我只是个初学者!!!这个问题在其他 post 中不存在,我尝试用我的原始代码实现另一个 post。但仍然失败。
谢谢。
错误是在主线程(a.k.a.UI线程)上执行网络请求引起的。通常,主线程禁止线程阻塞操作(如文件读取、网络请求)。这样做是为了避免 App Not responding
错误。
在你的 mainActivity.java
中,因为 BroadcastReceiver#onReceive
是在主线程上执行的。 (参考:)。在这个 onReceive
函数中,您正在尝试发出网络请求。
只是,使用处理程序和 post 对后台线程(或任何其他线程)的网络调用,这将解决您的问题。