Home > Mobile >  Crashing when first time try OkHttp as a client
Crashing when first time try OkHttp as a client

Time:04-04

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.

CodePudding user response:

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.

  • Related