Skip to content

Commit eb3627a

Browse files
Merge pull request #63 from nextcloud/allowDevApp
add support for dev app
2 parents 7e9c21a + 9ac1792 commit eb3627a

File tree

5 files changed

+77
-42
lines changed

5 files changed

+77
-42
lines changed

src/main/java/com/nextcloud/android/sso/AccountImporter.java

Lines changed: 53 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@
3434
import android.util.Log;
3535
import android.widget.Toast;
3636

37+
import androidx.core.app.ActivityCompat;
38+
import androidx.core.content.ContextCompat;
39+
import androidx.fragment.app.Fragment;
40+
3741
import com.nextcloud.android.sso.exceptions.AndroidGetAccountsPermissionNotGranted;
3842
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
3943
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountPermissionNotGrantedException;
@@ -45,12 +49,9 @@
4549

4650
import java.io.IOException;
4751
import java.util.ArrayList;
52+
import java.util.Arrays;
4853
import java.util.List;
4954

50-
import androidx.core.app.ActivityCompat;
51-
import androidx.core.content.ContextCompat;
52-
import androidx.fragment.app.Fragment;
53-
5455
import io.reactivex.annotations.NonNull;
5556

5657
import static android.app.Activity.RESULT_CANCELED;
@@ -71,42 +72,49 @@ public class AccountImporter {
7172

7273
private static SharedPreferences SHARED_PREFERENCES;
7374

75+
private static final List<String> APPS = Arrays.asList(Constants.PACKAGE_NAME_PROD, Constants.PACKAGE_NAME_DEV);
76+
private static final String[] ACCOUNT_TYPES = {Constants.ACCOUNT_TYPE_PROD, Constants.ACCOUNT_TYPE_DEV};
77+
7478
public static boolean accountsToImportAvailable(Context context) {
7579
return findAccounts(context).size() > 0;
7680
}
7781

78-
public static void pickNewAccount(Activity activity) throws NextcloudFilesAppNotInstalledException, AndroidGetAccountsPermissionNotGranted {
82+
public static void pickNewAccount(Activity activity) throws NextcloudFilesAppNotInstalledException,
83+
AndroidGetAccountsPermissionNotGranted {
7984
checkAndroidAccountPermissions(activity);
80-
81-
if (appInstalledOrNot(activity, "com.nextcloud.client")) {
82-
Intent intent = AccountManager.newChooseAccountIntent(null, null, new String[]{"nextcloud"},
83-
true, null, null, null, null);
85+
86+
if (appInstalledOrNot(activity)) {
87+
Intent intent = AccountManager.newChooseAccountIntent(null, null, ACCOUNT_TYPES,
88+
true, null, null, null, null);
8489
activity.startActivityForResult(intent, CHOOSE_ACCOUNT_SSO);
8590
} else {
8691
throw new NextcloudFilesAppNotInstalledException();
8792
}
8893
}
8994

90-
public static void pickNewAccount(Fragment fragment) throws NextcloudFilesAppNotInstalledException, AndroidGetAccountsPermissionNotGranted {
95+
public static void pickNewAccount(Fragment fragment) throws NextcloudFilesAppNotInstalledException,
96+
AndroidGetAccountsPermissionNotGranted {
9197
checkAndroidAccountPermissions(fragment.getContext());
92-
93-
if (appInstalledOrNot(fragment.getContext(), "com.nextcloud.client")) {
94-
Intent intent = AccountManager.newChooseAccountIntent(null, null, new String[]{"nextcloud"},
95-
true, null, null, null, null);
98+
99+
if (appInstalledOrNot(fragment.getContext())) {
100+
Intent intent = AccountManager.newChooseAccountIntent(null, null, ACCOUNT_TYPES,
101+
true, null, null, null, null);
96102
fragment.startActivityForResult(intent, CHOOSE_ACCOUNT_SSO);
97103
} else {
98104
throw new NextcloudFilesAppNotInstalledException();
99105
}
100106
}
101107

102108
public static void requestAndroidAccountPermissionsAndPickAccount(Activity activity) {
103-
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.GET_ACCOUNTS}, REQUEST_GET_ACCOUNTS_PERMISSION);
109+
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.GET_ACCOUNTS},
110+
REQUEST_GET_ACCOUNTS_PERMISSION);
104111
}
105112

106113
private static void checkAndroidAccountPermissions(Context context) throws AndroidGetAccountsPermissionNotGranted {
107114
// https://developer.android.com/reference/android/accounts/AccountManager#getAccountsByType(java.lang.String)
108-
// Caller targeting API level below Build.VERSION_CODES.O that have not been granted the Manifest.permission.GET_ACCOUNTS permission,
109-
// will only see those accounts managed by AbstractAccountAuthenticators whose signature matches the client.
115+
// Caller targeting API level below Build.VERSION_CODES.O that have not been granted the
116+
// Manifest.permission.GET_ACCOUNTS permission, will only see those accounts managed by
117+
// AbstractAccountAuthenticators whose signature matches the client.
110118
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
111119
// Do something for lollipop and above versions
112120
if (ContextCompat.checkSelfPermission(context, Manifest.permission.GET_ACCOUNTS) != PackageManager.PERMISSION_GRANTED) {
@@ -118,26 +126,32 @@ private static void checkAndroidAccountPermissions(Context context) throws Andro
118126
}
119127
}
120128

121-
private static boolean appInstalledOrNot(Context context, String uri) {
129+
private static boolean appInstalledOrNot(Context context) {
130+
boolean returnValue = false;
122131
PackageManager pm = context.getPackageManager();
123-
try {
124-
pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES);
125-
return true;
126-
} catch (PackageManager.NameNotFoundException e) {
127-
Log.v(TAG, e.getMessage());
132+
for (String app : APPS) {
133+
try {
134+
pm.getPackageInfo(app, PackageManager.GET_ACTIVITIES);
135+
returnValue = true;
136+
break;
137+
} catch (PackageManager.NameNotFoundException e) {
138+
Log.v(TAG, e.getMessage());
139+
}
128140
}
129-
return false;
141+
return returnValue;
130142
}
131143

132144
// Find all currently installed nextcloud accounts on the phone
133145
public static List<Account> findAccounts(final Context context) {
134146
final AccountManager accMgr = AccountManager.get(context);
135-
final Account[] accounts = accMgr.getAccountsByType("nextcloud");
147+
final Account[] accounts = accMgr.getAccounts();
136148

137149
List<Account> accountsAvailable = new ArrayList<>();
138150
for (final Account account : accounts) {
139-
if ("nextcloud".equals(account.type)) {
140-
accountsAvailable.add(account);
151+
for (String accountType : ACCOUNT_TYPES) {
152+
if (accountType.equals(account.type)) {
153+
accountsAvailable.add(account);
154+
}
141155
}
142156
}
143157
return accountsAvailable;
@@ -188,10 +202,11 @@ public static SingleSignOnAccount extractSingleSignOnAccountFromResponse(Intent
188202
}
189203
String token = future.getString(Constants.SSO_TOKEN);
190204
String serverUrl = future.getString(Constants.SSO_SERVER_URL);
205+
String type = future.getString("accountType");
191206

192207
SharedPreferences mPrefs = getSharedPreferences(context);
193208
String prefKey = getPrefKeyForAccount(accountName);
194-
SingleSignOnAccount ssoAccount = new SingleSignOnAccount(accountName, userId, token, serverUrl);
209+
SingleSignOnAccount ssoAccount = new SingleSignOnAccount(accountName, userId, token, serverUrl, type);
195210
try {
196211
mPrefs.edit().putString(prefKey, SingleSignOnAccount.toString(ssoAccount)).apply();
197212
} catch (IOException e) {
@@ -351,9 +366,17 @@ private static Intent buildRequestAuthTokenIntent(Context context, Intent intent
351366
if(account == null) {
352367
throw new NextcloudFilesAppAccountPermissionNotGrantedException();
353368
}
369+
370+
String componentName;
371+
if (account.type.equalsIgnoreCase(Constants.ACCOUNT_TYPE_DEV)) {
372+
componentName = Constants.PACKAGE_NAME_DEV;
373+
} else {
374+
componentName = Constants.PACKAGE_NAME_PROD;
375+
}
376+
354377
Intent authIntent = new Intent();
355-
authIntent.setComponent(new ComponentName("com.nextcloud.client",
356-
"com.owncloud.android.ui.activity.SsoGrantPermissionActivity"));
378+
authIntent.setComponent(new ComponentName(componentName,
379+
"com.owncloud.android.ui.activity.SsoGrantPermissionActivity"));
357380
authIntent.putExtra(NEXTCLOUD_FILES_ACCOUNT, account);
358381
return authIntent;
359382
}

src/main/java/com/nextcloud/android/sso/Constants.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,11 @@ public class Constants {
3838
public static final String EXCEPTION_INVALID_REQUEST_URL = "CE_4";
3939
public static final String EXCEPTION_HTTP_REQUEST_FAILED = "CE_5";
4040
public static final String EXCEPTION_ACCOUNT_ACCESS_DECLINED = "CE_6";
41+
42+
// package related constans
43+
public static final String PACKAGE_NAME_PROD = "com.nextcloud.client";
44+
public static final String PACKAGE_NAME_DEV = "com.nextcloud.android.beta";
45+
public static final String ACCOUNT_TYPE_PROD = "nextcloud";
46+
public static final String ACCOUNT_TYPE_DEV = "nextcloud.beta";
47+
4148
}

src/main/java/com/nextcloud/android/sso/api/AidlNetworkRequest.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import android.os.RemoteException;
1212
import android.util.Log;
1313

14+
import com.nextcloud.android.sso.Constants;
1415
import com.nextcloud.android.sso.aidl.IInputStreamService;
1516
import com.nextcloud.android.sso.aidl.IThreadListener;
1617
import com.nextcloud.android.sso.aidl.NextcloudRequest;
@@ -67,18 +68,23 @@ public void onServiceDisconnected(ComponentName className) {
6768
}
6869
};
6970

70-
public void connect() {
71-
super.connect();
71+
public void connect(String type) {
72+
super.connect(type);
7273

7374
// Disconnect if connected
7475
if (mBound.get()) {
7576
stop();
7677
}
7778

79+
String componentName = Constants.PACKAGE_NAME_PROD;
80+
if (type.equals(Constants.ACCOUNT_TYPE_DEV)) {
81+
componentName = Constants.PACKAGE_NAME_DEV;
82+
}
83+
7884
try {
7985
Intent intentService = new Intent();
80-
intentService.setComponent(new ComponentName("com.nextcloud.client",
81-
"com.owncloud.android.services.AccountManagerService"));
86+
intentService.setComponent(new ComponentName(componentName,
87+
"com.owncloud.android.services.AccountManagerService"));
8288
if (!mContext.bindService(intentService, mConnection, Context.BIND_AUTO_CREATE)) {
8389
Log.d(TAG, "Binding to AccountManagerService returned false");
8490
throw new IllegalStateException("Binding to AccountManagerService returned false");

src/main/java/com/nextcloud/android/sso/api/NetworkRequest.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ protected NetworkRequest(Context context, SingleSignOnAccount account, Nextcloud
2727
}
2828

2929

30-
protected void connect() {
31-
Log.v(TAG, "Nextcloud Single sign-on connect() called [" + Thread.currentThread().getName() + "]");
30+
protected void connect(String type) {
31+
Log.v(TAG, "Nextcloud Single sign-on connect() called [" + Thread.currentThread().getName() + "] Account-Type: [" + type + "]");
3232
if (mDestroyed) {
3333
throw new IllegalStateException("API already destroyed! You cannot reuse a stopped API instance");
3434
}
@@ -37,11 +37,8 @@ protected void connect() {
3737
protected abstract InputStream performNetworkRequest(NextcloudRequest request, InputStream requestBodyInputStream) throws Exception;
3838

3939
protected void connectApiWithBackoff() {
40-
new ExponentialBackoff(1000, 10000, 2, 5, Looper.getMainLooper(), new Runnable() {
41-
@Override
42-
public void run() {
43-
connect();
44-
}
40+
new ExponentialBackoff(1000, 10000, 2, 5, Looper.getMainLooper(), () -> {
41+
connect(mAccount.type);
4542
}).start();
4643
}
4744

src/main/java/com/nextcloud/android/sso/model/SingleSignOnAccount.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,14 @@ public class SingleSignOnAccount implements Serializable {
3737
public String userId;
3838
public String token;
3939
public String url;
40+
public String type;
4041

41-
public SingleSignOnAccount(String name, String userId, String token, String url) {
42+
public SingleSignOnAccount(String name, String userId, String token, String url, String type) {
4243
this.name = name;
4344
this.userId = userId;
4445
this.token = token;
4546
this.url = url;
47+
this.type = type;
4648
}
4749

4850
/** Read the object from Base64 string. */

0 commit comments

Comments
 (0)