Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SyncAdapter- onPerformSync has no internet access

I have a SyncAdapter class that connects to an MQTT broker and publish payload for the server to receive the payload. However, it seems that even though the onPerformSync() method is invoked, the internet access is not there. I thought using SyncAdapter guarantees internet access?

Here is the SyncAdapter Class

public class SyncAdapter extends AbstractThreadedSyncAdapter {
    private static final String TAG = SyncAdapter.class.getSimpleName();
    private MqttHelper mqttHelper;

    public SyncAdapter(Context context, boolean autoInitialize) {
        super(context, autoInitialize);
        mqttHelper = new MqttHelper(getContext());
    }

    public SyncAdapter(Context context, boolean autoInitialize, boolean allowParallelSyncs) {
        super(context, autoInitialize, allowParallelSyncs);
    }
    private boolean isNetworkAvailable() {
        ConnectivityManager connectivityManager
            = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetworkInfo != null && activeNetworkInfo.isConnected();
    }

    @Override
    public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
        Log.wtf(TAG, "onPerformSync: ");
        Log.wtf(TAG, "SYNC_EXTRAS_MANUAL: " + extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL));
        Log.wtf(TAG, "SYNC_EXTRAS_EXPEDITED: " + extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED));

        Log.wtf(TAG, "internte: " + isNetworkAvailable());


        mqttHelper.connect(new IMqttActionListener() {
            @Override
            public void onSuccess(IMqttToken asyncActionToken) {
                Log.wtf(TAG, "onSuccess: ");
                mqttHelper.pub("hello/android", "Finally working via sync adapter praise the lord!!!!");
                // TODO: Get Checkpoints from Realm
                // TODO: publish at once
                // TODO: Disconnect
                mqttHelper.disconnect(new IMqttActionListener() {
                    @Override
                    public void onSuccess(IMqttToken asyncActionToken) {
                        Log.wtf(TAG, "onSuccess: disconnect");
                    }

                    @Override
                    public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                        Log.wtf(TAG, "onFailure: disocnnect");
                    }
                });
            }

            @Override
            public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                Log.wtf(TAG, "onFailure: ", exception);
            }
        });

    }

    @Override
    public void onSyncCanceled() {
        super.onSyncCanceled();
        Log.wtf(TAG, "sync canceled");
    }
}

And also a snippet of my Android Manifest pertaining to the MqttService and SyncAdapter:

<application
    ...
    <receiver android:name=".LocationPollingReceiver" />
    <service android:name="org.eclipse.paho.android.service.MqttService"
        android:process=":sync"/>
    <service
        android:name=".LocationPollingService"
        android:exported="false"/>
    <service
        android:name=".sync.AuthenticatorService">
        <intent-filter>
            <action android:name="android.accounts.AccountAuthenticator"/>
        </intent-filter>
        <meta-data
            android:name="android.accounts.AccountAuthenticator"
            android:resource="@xml/authenticator" />
    </service>
    <provider
        android:name=".sync.StubProvider"
        android:authorities="proj.com.fyp.provider"
        android:exported="false"
        android:syncable="true"/>
    <service
        android:name=".sync.SyncService"
        android:exported="true"
        android:process=":sync">
        <intent-filter>
            <action android:name="android.content.SyncAdapter"/>
        </intent-filter>
        <meta-data android:name="android.content.SyncAdapter"
            android:resource="@xml/syncadapter" />
    </service>
</application>

Does this have anything to do with invoking the sync manually? like what I did below?

Account mAccount = MainActivity.CreateSyncAccount(context);
Bundle settingsBundle = new Bundle();
settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
//settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_FORCE, true);
ContentResolver.requestSync(mAccount, AUTHORITY, settingsBundle);

Even syncing via the Settings->Account->Sync now produced the same result.

like image 211
Andy Aldo Avatar asked May 20 '17 14:05

Andy Aldo


1 Answers

Let me explain something.

onPerformSync() is a callback, which is not up to your control on how/when it gets called? These types of callbacks are generally Async Tasks, which can be triggered from external (can be remote) objects anytime. That's why we generally put these types of callbacks in our MainThread (UI thread) because, MainThread can't be killed throughout the app. [Note: If you have executed a service in the different process then you can run onPerformSync() from that Service as well]. My intention of saying this is to make sure that throughout the app keeps running, there is a change of these callbacks can be executed anytime.

I really don't see any use of onNetworkAvailable() method here. You use this onNetworkAvailable() if you want to do some network operations from your side.

like image 153
Uddhav P. Gautam Avatar answered Oct 19 '22 23:10

Uddhav P. Gautam