Issue
I'm have some project, realtime sending RSSI and MAC of Bluetooth Low Energy. I want try using http protocol, and i found OkHttp library. But when i run with OkHttp, my software crash.
My error
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$3@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$3.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)
I'm sure it's OkHttp that crashes the app. Because before using OkHttp the app was fine.
This is my 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;
}
}
}
This is my 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();
}
}
}
My 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")
}
For a clearer explanation, I did programming using JAVA in Android Studio with API for Android 6.0.
My question is simple, how to fix this problem? and why it crashes? PLEASE DON'T CLOSED MY QUESTIONS!!! I AM JUST A BEGINNER!!! This problem does not exist in other posts and I have tried to implement another post with my origin code. But STILL FAIL.
Thanks.
Solution
The error is caused due to execution of network request on main thread (a.k.a. UI thread). In general, thread blocking operations (like file read, network requests) are prohibited on main thread. This is done to avoid App Not responding
error.
In your mainActivity.java
, since BroadcastReceiver#onReceive
is executed on main thread. (Ref: https://stackoverflow.com/a/5676888/5309486 ). And inside this onReceive
function, you are trying to make the network request.
Just, use handler and post the network call to background thread (or any other thread) and that will fix your issue.
Answered By - Ashok
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.