Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit f43804ab authored by David Luhmer's avatar David Luhmer Committed by GitHub
Browse files

Merge pull request #38 from nextcloud/fix-api-init-crash

make requests wait for api to initialize properly
parents 19d4c520 55d16810
Loading
Loading
Loading
Loading
+51 −18
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.Looper;
import android.os.NetworkOnMainThreadException;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.Log;
@@ -34,6 +35,7 @@ import com.nextcloud.android.sso.aidl.IInputStreamService;
import com.nextcloud.android.sso.aidl.IThreadListener;
import com.nextcloud.android.sso.aidl.NextcloudRequest;
import com.nextcloud.android.sso.aidl.ParcelFileDescriptorUtil;
import com.nextcloud.android.sso.exceptions.NextcloudApiNotRespondingException;
import com.nextcloud.android.sso.helper.ExponentialBackoff;
import com.nextcloud.android.sso.model.SingleSignOnAccount;

@@ -49,6 +51,7 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Reader;
import java.lang.reflect.Type;
import java.util.concurrent.atomic.AtomicBoolean;

import io.reactivex.Observable;
import io.reactivex.annotations.NonNull;
@@ -57,9 +60,20 @@ import static com.nextcloud.android.sso.exceptions.SSOException.parseNextcloudCu

public class NextcloudAPI {

    private static final String TAG = NextcloudAPI.class.getCanonicalName();

    private Gson gson;
    private IInputStreamService mService = null;
    private final AtomicBoolean mBound = new AtomicBoolean(false); // Flag indicating whether we have called bind on the service
    private boolean mDestroyed = false; // Flag indicating if API is destroyed
    private SingleSignOnAccount mAccount;
    private ApiConnectedListener mCallback;
    private Context mContext;



    public interface ApiConnectedListener {
        void onConnected();

        void onError(Exception ex);
    }

@@ -72,17 +86,6 @@ public class NextcloudAPI {
        connectApiWithBackoff();
    }

    private static final String TAG = NextcloudAPI.class.getCanonicalName();

    private Gson gson;
    private IInputStreamService mService = null;
    private boolean mBound = false; // Flag indicating whether we have called bind on the service
    private boolean mDestroyed = false; // Flag indicating if API is destroyed
    private SingleSignOnAccount mAccount;
    private ApiConnectedListener mCallback;
    private Context mContext;


    private String getAccountName() {
        return mAccount.name;
    }
@@ -106,7 +109,7 @@ public class NextcloudAPI {
        }

        // Disconnect if connected
        if (mBound) {
        if (mBound.get()) {
            stop();
        }

@@ -132,13 +135,13 @@ public class NextcloudAPI {
        mCallback = null;

        // Unbind from the service
        if (mBound) {
        if (mBound.get()) {
            if (mContext != null) {
                mContext.unbindService(mConnection);
            } else {
                Log.e(TAG, "Context was null, cannot unbind nextcloud single sign-on service connection!");
            }
            mBound = false;
            mBound.set(false);
            mContext = null;
        }
    }
@@ -152,7 +155,10 @@ public class NextcloudAPI {
            Log.i(TAG, "Nextcloud Single sign-on: onServiceConnected");

            mService = IInputStreamService.Stub.asInterface(service);
            mBound = true;
            mBound.set(true);
            synchronized (mBound) {
                mBound.notifyAll();
            }
            mCallback.onConnected();
        }

@@ -161,7 +167,7 @@ public class NextcloudAPI {
            // This is called when the connection with the service has been
            // unexpectedly disconnected -- that is, its process crashed.
            mService = null;
            mBound = false;
            mBound.set(false);

            if (!mDestroyed) {
                connectApiWithBackoff();
@@ -169,6 +175,24 @@ public class NextcloudAPI {
        }
    };

    private void waitForApi() throws NextcloudApiNotRespondingException {
        synchronized (mBound) {
            // If service is not bound yet.. wait
            if(!mBound.get()) {
                Log.v(TAG, "[waitForApi] - api not ready yet.. waiting [" + Thread.currentThread().getName() +  "]");
                try {
                    mBound.wait(10000); // wait up to 10 seconds

                    // If api is still not bound after 10 seconds.. throw an exception
                    if(!mBound.get()) {
                        throw new NextcloudApiNotRespondingException();
                    }
                } catch (InterruptedException ex) {
                    Log.e(TAG, "WaitForAPI failed", ex);
                }
            }
        }
    }

    public <T> Observable<T> performRequestObservable(final Type type, final NextcloudRequest request) {
        return Observable.fromPublisher(new Publisher<T>() {
@@ -249,7 +273,16 @@ public class NextcloudAPI {
     * @throws IOException
     */
    private ParcelFileDescriptor performAidlNetworkRequest(NextcloudRequest request)
            throws IOException, RemoteException {
            throws IOException, RemoteException, NextcloudApiNotRespondingException {

        // Check if we are on the main thread
        if(Looper.myLooper() == Looper.getMainLooper()) {
            throw new NetworkOnMainThreadException();
        }

        // Wait for api to be initialized
        waitForApi();

        // Log.d(TAG, request.url);
        request.setAccountName(getAccountName());
        request.setToken(getAccountToken());
+18 −0
Original line number Diff line number Diff line
package com.nextcloud.android.sso.exceptions;

import android.content.Context;

import com.nextcloud.android.sso.R;
import com.nextcloud.android.sso.model.ExceptionMessage;

public class NextcloudApiNotRespondingException extends SSOException {

    @Override
    public void loadExceptionMessage(Context context) {
        this.em = new ExceptionMessage(
                context.getString(R.string.nextcloud_files_api_not_responsing_title),
                context.getString(R.string.nextcloud_files_api_not_responsing_message)
        );
    }

}
+4 −0
Original line number Diff line number Diff line
@@ -30,6 +30,10 @@
    <string name="nextcloud_files_app_not_supported_title">Error</string>
    <string name="nextcloud_files_app_not_supported_message" formatted="true">Your nextcloud files app currently does not support the single sign on feature. Please update it: %1$s</string>


    <string name="nextcloud_files_api_not_responsing_title">Error</string>
    <string name="nextcloud_files_api_not_responsing_message">Nextcloud files app api is not responding. Please report this issue.</string>

    <string name="select_account_unknown_error_toast">Something went wrong.. please try again</string>

</resources>