1

I'm trying to debugging a service in Android. I've already put the line Debug.waitForDebugger(); in this method:

@Override
protected void onHandleIntent(Intent intent)
{
    Debug.waitForDebugger();
    Utilities.displayAlertDialog("on handle intent", this);

    SharedPreferences sp = getSharedPreferences(getString(clyky.cartracker.R.string.sharedPreferencesName), Context.MODE_PRIVATE);
    int userID = sp.getInt("id_user", SplashActivity.DEFAULT_USER_ID);

    if (userID != SplashActivity.DEFAULT_USER_ID)
    {
        sendRequest(userID);
    }
    else
    {
        stopSelf();
    }
}

I've put a breakpoint on line 2 (Utilities.displayAlertDialog("on handle intent", this);, but this breakpoint is never reached. I'm debugging my app on my device and I'm using Android Studio.

EDIT

This is my entire service class. It retrieves some information from the database and puts all into an ArrayList:

public class RetrieveVehicleListService extends IntentService
{
    private static final int NOTIFICATION_ID = 1;
    private NotificationManager mNotificationManager;
    private NotificationCompat.Builder builder;
    private ArrayList<Vehicle> vehicles;

    private void parseVehiclesFromMap(ArrayList vehicles)
    {
        for (int i = 0; i < vehicles.size(); i++)
        {
            final Vehicle v = new Vehicle();
            HashMap vehicleMap = (HashMap) vehicles.get(i);

            v.setPlate(vehicleMap.get("plate").toString());
            v.setKm(vehicleMap.get("km") == null ? null : Integer.parseInt(vehicleMap.get("km").toString()));
            v.setFuelQuantity(Double.parseDouble(vehicleMap.get("fuel_quantity").toString()));
            v.setEffectiveFuelEconomy(Double.parseDouble(vehicleMap.get("fuel_economy").toString()));
            v.setInsuranceDate(vehicleMap.get("insurance_date") == null ? null : new LocalDate(vehicleMap.get("insurance_date").toString()));
            v.setMatriculationDate(new LocalDate(vehicleMap.get("matriculation_date").toString()));
            v.setLatitude(vehicleMap.get("latitude") == null ? null : Double.parseDouble(vehicleMap.get("latitude").toString()));
            v.setLongitude(vehicleMap.get("longitude") == null ? null : Double.parseDouble(vehicleMap.get("longitude").toString()));
            v.setFuelType(FuelType.fromInt(Integer.parseInt(vehicleMap.get("id_fuel").toString())));

            this.vehicles.add(v);
        }
    }

    private void sendRequest(int userID)
    {
        Response.Listener<String> listener = new Response.Listener<String>()
        {
            @Override
            public void onResponse(String response)
            {
                try
                {
                    HashMap json = new ObjectMapper().readValue(response, HashMap.class);
                    String errorCode = json.get("error_code").toString();

                    switch (errorCode)
                    {
                        case "0":
                            parseVehiclesFromMap((ArrayList) json.get("vehicles"));
                            break;
                        default:
                            // TODO gestire
                            break;
                    }
                }
                catch (IOException e)
                {
                    // TODO gestire
                    e.printStackTrace();
                }
            }
        };

        VehicleListRequest request = new VehicleListRequest(String.valueOf(userID), listener, null);
        RequestQueue queue = Volley.newRequestQueue(this);
        queue.add(request);
    }

    @Override
    protected void onHandleIntent(Intent intent)
    {
        Debug.waitForDebugger();
        Utilities.displayAlertDialog("on handle intent", this);

        SharedPreferences sp = getSharedPreferences(getString(clyky.cartracker.R.string.sharedPreferencesName), Context.MODE_PRIVATE);
        int userID = sp.getInt("id_user", SplashActivity.DEFAULT_USER_ID);

        if (userID != SplashActivity.DEFAULT_USER_ID)
        {
            sendRequest(userID);
        }
        else
        {
            stopSelf();
        }
    }

    public RetrieveVehicleListService()
    {
        super("RetrieveVehicleList");
        vehicles = new ArrayList<>();
    }
}

This is my BroadcastReceiver, which runs my RetrieveVehiclesListService when the internet connection is available:

public class NetworkWatcher extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = cm.getActiveNetworkInfo();
        Intent retrieveVehicleList = new Intent(context, RetrieveVehicleListService.class);

        if (info != null)
        {
            if (info.isConnected())
            {
                if (!Utilities.vehicleFileExists(context))
                {
                    context.startService(retrieveVehicleList);
                }
            }
            else
            {
                context.stopService(retrieveVehicleList);
            }
        }
    }
}

this is my manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="clyky.cartracker">

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

    <!--
         TODO crediti per le icone:
        <div>Icons made by <a href="http://www.flaticon.com/authors/dave-gandy" title="Dave Gandy">Dave Gandy</a> from <a href="http://www.flaticon.com" title="Flaticon">www.flaticon.com</a> is licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a></div>
        per la freccia in giù che espande il layout nella LoginActivity
        <div>Icons made by <a href="http://www.flaticon.com/authors/dave-gandy" title="Dave Gandy">Dave Gandy</a> from <a href="http://www.flaticon.com" title="Flaticon">www.flaticon.com</a> is licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a></div>
        per la freccia in su
        <div>Icons made by <a href="http://www.flaticon.com/authors/madebyoliver" title="Madebyoliver">Madebyoliver</a> from <a href="http://www.flaticon.com" title="Flaticon">www.flaticon.com</a> is licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a></div>
        per il lucchetto
        <a href="https://icons8.com/icon/17577/Car-Rental">Car rental icon credits</a>
        per l'icona della macchina
    -->
    <application
        android:name=".AppGlobal"
        android:allowBackup="true"
        android:icon="@mipmap/ic_app_icon"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".activities.RegistrationActivity">
        </activity>
        <activity android:name=".activities.LoginActivity">
        </activity>
        <activity android:name=".activities.VehicleListActivity">
        </activity>
        <activity android:name=".activities.VehicleDetailsActivity">
        </activity>
        <activity android:name=".activities.AddVehicleActivity">
        </activity>
        <!--
             The API key for Google Maps-based APIs is defined as a string resource
             Note that the API key is linked to the encryption key used to sign the APK.
             You need a different API key for each encryption key, including the release key that is used to
             sign the APK for publishing.
             You can define the keys for the debug and release targets in src/debug/ and src/release/. 
        -->
        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="@string/google_maps_key"/>

        <activity
            android:name=".activities.SplashActivity"
            android:theme="@style/SplashTheme">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity android:name=".activities.MainActivity">
        </activity>
        <activity android:name=".activities.DrivingLicenseActivity">
        </activity>
        <receiver
            android:name=".services.NetworkWatcher"
            android:enabled="true"
            android:exported="false">
        </receiver>
        <service
            android:name=".services.RetrieveVehicleListService"
            android:exported="false">
        </service>
    </application>
</manifest>
  • If the breakpoint is never reached this means the method is never called. Probably you should add all the Service class code to your answer and how you are using it – MatPag May 24 '17 at 19:29
  • don't forget to declare this `Service` in the manifest – Veneet Reddy May 24 '17 at 19:31
  • Maybe it's just that the intended associated to your event is never fired. You can also put some log messages and see what happens – Maurizio Ricci May 24 '17 at 19:31
  • As @VeneetReddy said, have you registered the service in the AndroidManifest.xml? – MatPag May 24 '17 at 19:34
  • @MatPag thanks for your comment, I've edited my post. –  May 24 '17 at 19:34
  • @VeneetReddy thank you, but I've already declared that :) –  May 24 '17 at 19:34
  • @MaurizioRicci could it be a problem with my implementation of `BroadcastReceiver`? –  May 24 '17 at 19:35
  • Have you put a breakpoint in the first line of onReceive method of NetworkWatcher to see if at least the execution arrives there? (and obviously you registered this receiver in the manifest too :D) – MatPag May 24 '17 at 19:38
  • @Clyky can u post manifest file? And by the way which android device you are testing this? because Apps targeting Android N do not receive CONNECTIVITY_ACTION broadcasts even if they have manifest entries to request notification of these events. – Dhaval Patel May 24 '17 at 19:39
  • @MatPag I've tried both breakpoint at the start of `onReceive` method and a log message inside my if-statement (which checks if file exists): none of them is reached –  May 24 '17 at 19:43
  • @DhavalPatel I've posted the manifest. I'm debugging my app on my Nexus 5 which runs a custom rom based on Android 6.0.1. –  May 24 '17 at 19:47
  • @Clyky you have not defined network receiver properly. wait i will write the answer. – Dhaval Patel May 24 '17 at 19:48

2 Answers2

0

Connectivity Change Action:

  1. If you want to detect change network connection use:

    <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />

  2. If you want to detect WiFi state Change use:

    <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />

Change you receive as per below:

<receiver  android:name=".services.NetworkWatcher">
           <intent-filter>
              <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
           </intent-filter>
</receiver>
Community
  • 1
  • 1
Dhaval Patel
  • 10,119
  • 5
  • 43
  • 46
  • 1
    thank you, it works, but I think I will change my code to work even on Android N :) –  May 25 '17 at 12:00
0

You should completely remove the <receiver> tag from your AndroidManifest.xml because starting with Nougat (Android 7 API 24) you will not be able to receive connectivity change events in a receiver as stated here, because of new limitations to background services

You could be able to listen to CONNECTIVITY_ACTION only on your Main UI thread while the app is running and in foreground with a programmatically registered BroadCastReceiver, and this could be a good or a bad solution based on your use case.

What i suggest you, it's to read this answer: https://stackoverflow.com/a/39880860/2910520 and choose between one or a combination of the provided solutions:

  1. JobScheduler (API 21 onwards)
  2. GcmNetworkManager (for this to work users need Google Play Services installed)

Evernote has released a library which already switch to the best implementation available for the device, i would suggest you to use this without doing everything from scratch: https://github.com/evernote/android-job

MatPag
  • 41,742
  • 14
  • 105
  • 114