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

Commit 592195bb authored by Stefan Niedermann's avatar Stefan Niedermann
Browse files

Merge branch 'master' into 26-current-account-livedata

parents fa8b9b0a 80842e0e
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
name: "Validate Gradle Wrapper"

on:
  pull_request:
    branches: [ master ]

jobs:
  validation:
    name: "Validation"
    runs-on: ubuntu-latest
    steps:
      -   uses: actions/checkout@v2
      -   uses: gradle/wrapper-validation-action@v1
+4 −3
Original line number Diff line number Diff line
[main]
host = https://www.transifex.com

[nextcloud.android-singlesignon]
[o:nextcloud:p:nextcloud:r:android-singlesignon]
file_filter = lib/src/main/res/values-<lang>/strings.xml
source_file = lib/src/main/res/values/strings.xml
type = ANDROID
source_lang = en
lang_map = af_ZA: af-rZA, am_ET: am-rET, ar_AE: ar-rAE, ar_BH: ar-rBH, ar_DZ: ar-rDZ, ar_EG: ar-rEG, ar_IQ: ar-rIQ, ar_JO: ar-rJO, ar_KW: ar-rKW, ar_LB: ar-rLB, ar_LY: ar-rLY, ar_MA: ar-rMA, ar_OM: ar-rOM, ar_QA: ar-rQA, ar_SA: ar-rSA, ar_SY: ar-rSY, ar_TN: ar-rTN, ar_YE: ar-rYE, arn_CL: arn-rCL, as_IN: as-rIN, az_AZ: az-rAZ, ba_RU: ba-rRU, be_BY: be-rBY, bg_BG: bg-rBG, bn_BD: bn-rBD, bn_IN: bn-rIN, bo_CN: bo-rCN, br_FR: br-rFR, bs_BA: bs-rBA, ca_ES: ca-rES, co_FR: co-rFR, cs_CZ: cs-rCZ, cy_GB: cy-rGB, da_DK: da-rDK, de_AT: de-rAT, de_CH: de-rCH, de_DE: de-rDE, de_LI: de-rLI, de_LU: de-rLU, dsb_DE: dsb-rDE, dv_MV: dv-rMV, el_GR: el-rGR, en_AU: en-rAU, en_BZ: en-rBZ, en_CA: en-rCA, en_GB: b+en+001, en_IE: en-rIE, en_IN: en-rIN, en_JM: en-rJM, en_MY: en-rMY, en_NZ: en-rNZ, en_PH: en-rPH, en_SG: en-rSG, en_TT: en-rTT, en_US: en-rUS, en_ZA: en-rZA, en_ZW: en-rZW, en@pirate: en-rpirate, es_AR: es-rAR, es_BO: es-rBO, es_CL: es-rCL, es_CO: es-rCO, es_CR: es-rCR, es_DO: es-rDO, es_EC: es-rEC, es_ES: es-rES, es_GT: es-rGT, es_HN: es-rHN, es_MX: es-rMX, es_NI: es-rNI, es_PA: es-rPA, es_PE: es-rPE, es_PR: es-rPR, es_PY: es-rPY, es_SV: es-rSV, es_419: b+es+419, es_UY: es-rUY, es_VE: es-rVE, et_EE: et-rEE, eu_ES: eu-rES, fa_IR: fa-rIR, fi_FI: fi-rFI, fil_PH: fil-rPH, fo_FO: fo-rFO, fr_BE: fr-rBE, fr_CA: fr-rCA, fr_CH: fr-rCH, fr_FR: fr-rFR, fr_LU: fr-rLU, fr_MC: fr-rMC, fy_NL: fy-rNL, ga_IE: ga-rIE, gd_GB: gd-rGB, gl_ES: gl-rES, gsw_FR: gsw-rFR, gu_IN: gu-rIN, ha_NG: ha-rNG, he: iw, he_IL: he-rIL, hi_IN: hi-rIN, hr_BA: hr-rBA, hr_HR: hr-rHR, hsb_DE: hsb-rDE, hu_HU: hu-rHU, hy_AM: hy-rAM, id: in, id_ID: id-rID, ig_NG: ig-rNG, ii_CN: ii-rCN, is_IS: is-rIS, it_CH: it-rCH, it_IT: it-rIT, iu_CA: iu-rCA, ja_JP: ja-rJP, ka_GE: ka-rGE, kk_KZ: kk-rKZ, kl_GL: kl-rGL, km_KH: km-rKH, kn_IN: kn-rIN, ko_KR: ko-rKR, kok_IN: kok-rIN, ku_IQ: ku-rIQ, ky_KG: ky-rKG, lb_LU: lb-rLU, lo_LA: lo-rLA, lt_LT: lt-rLT, lv_LV: lv-rLV, mi_NZ: mi-rNZ, mk_MK: mk-rMK, ml_IN: ml-rIN, mn_CN: mn-rCN, mn_MN: mn-rMN, moh_CA: moh-rCA, mr_IN: mr-rIN, ms_BN: ms-rBN, ms_MY: ms-rMY, my_MM: my, mt_MT: mt-rMT, nb_NO: nb-rNO, ne_NP: ne-rNP, nl_BE: nl-rBE, nl_NL: nl-rNL, nn_NO: nn-rNO, nso_ZA: nso-rZA, oc_FR: oc-rFR, or_IN: or-rIN, pa_IN: pa-rIN, pl_PL: pl-rPL, prs_AF: prs-rAF, ps_AF: ps-rAF, pt_BR: pt-rBR, pt_PT: pt-rPT, qut_GT: qut-rGT, quz_BO: quz-rBO, quz_EC: quz-rEC, quz_PE: quz-rPE, rm_CH: rm-rCH, ro_RO: ro-rRO, ru_RU: ru-rRU, rw_RW: rw-rRW, sa_IN: sa-rIN, sah_RU: sah-rRU, se_FI: se-rFI, se_NO: se-rNO, se_SE: se-rSE, si_LK: si-rLK, sk_SK: sk-rSK, sl_SI: sl-rSI, sma_NO: sma-rNO, sma_SE: sma-rSE, smj_NO: smj-rNO, smj_SE: smj-rSE, smn_FI: smn-rFI, sms_FI: sms-rFI, sq_AL: sq-rAL, sr_BA: sr-rBA, sr_CS: sr-rCS, sr_ME: sr-rME, sr_RS: sr-rRS, sr@latin: sr-rSP, sv_FI: sv-rFI, sv_SE: sv-rSE, sw_KE: sw-rKE, syr_SY: syr-rSY, ta_IN: ta-rIN, ta_LK: ta-rLK, te_IN: te-rIN, tg_TJ: tg-rTJ, th_TH: th-rTH, tk_TM: tk-rTM, tn_ZA: tn-rZA, tr_TR: tr-rTR, tt_RU: tt-rRU, tzm_DZ: tzm-rDZ, ug_CN: ug-rCN, uk_UA: uk-rUA, ur_PK: ur-rPK, uz_UZ: uz-rUZ, vi_VN: vi-rVN, wo_SN: wo-rSN, xh_ZA: xh-rZA, yo_NG: yo-rNG, zh_CN: zh-rCN, zh_CN.GB2312:zh-rBG, zh_HK: zh-rHK, zh_MO: zh-rMO, zh_SG: zh-rSG, zh_TW: zh-rTW, zu_ZA: zu-rZA
type        = ANDROID
lang_map    = en_NZ: en-rNZ, qut_GT: qut-rGT, fo_FO: fo-rFO, ky_KG: ky-rKG, pl_PL: pl-rPL, ar_SA: ar-rSA, sa_IN: sa-rIN, ar_OM: ar-rOM, sr_RS: sr-rRS, bn_BD: bn-rBD, en_BZ: en-rBZ, ga_IE: ga-rIE, gsw_FR: gsw-rFR, rm_CH: rm-rCH, es_AR: es-rAR, ja_JP: ja-rJP, kok_IN: kok-rIN, zh_CN.GB2312: zh-rBG, it_CH: it-rCH, bo_CN: bo-rCN, ta_LK: ta-rLK, de_LU: de-rLU, fr_CH: fr-rCH, ug_CN: ug-rCN, az_AZ: az-rAZ, hu_HU: hu-rHU, lb_LU: lb-rLU, quz_EC: quz-rEC, tr_TR: tr-rTR, es_GT: es-rGT, tg_TJ: tg-rTJ, tk_TM: tk-rTM, ar_EG: ar-rEG, en_ZA: en-rZA, mn_MN: mn-rMN, sms_FI: sms-rFI, ar_LY: ar-rLY, ba_RU: ba-rRU, kk_KZ: kk-rKZ, nl_BE: nl-rBE, tzm_DZ: tzm-rDZ, de_AT: de-rAT, es_NI: es-rNI, or_IN: or-rIN, da_DK: da-rDK, dsb_DE: dsb-rDE, en@pirate: en-rpirate, lt_LT: lt-rLT, es_PY: es-rPY, bs_BA: bs-rBA, es_CO: es-rCO, pt_BR: pt-rBR, smj_NO: smj-rNO, ar_YE: ar-rYE, es_DO: es-rDO, fr_FR: fr-rFR, si_LK: si-rLK, sv_FI: sv-rFI, en_JM: en-rJM, sma_NO: sma-rNO, sma_SE: sma-rSE, zu_ZA: zu-rZA, ii_CN: ii-rCN, arn_CL: arn-rCL, be_BY: be-rBY, en_IN: en-rIN, es_EC: es-rEC, sq_AL: sq-rAL, ar_TN: ar-rTN, fr_LU: fr-rLU, xh_ZA: xh-rZA, am_ET: am-rET, ca_ES: ca-rES, fy_NL: fy-rNL, sr_ME: sr-rME, ar_KW: ar-rKW, hy_AM: hy-rAM, prs_AF: prs-rAF, en_AU: en-rAU, syr_SY: syr-rSY, uz_UZ: uz-rUZ, yo_NG: yo-rNG, es_HN: es-rHN, de_DE: de-rDE, es_CR: es-rCR, eu_ES: eu-rES, quz_BO: quz-rBO, sr_CS: sr-rCS, bn_IN: bn-rIN, dv_MV: dv-rMV, en_IE: en-rIE, mr_IN: mr-rIN, ne_NP: ne-rNP, co_FR: co-rFR, en_GB: b+en+001, ar_LB: ar-rLB, sw_KE: sw-rKE, hr_HR: hr-rHR, en_TT: en-rTT, smj_SE: smj-rSE, as_IN: as-rIN, id_ID: id-rID, mk_MK: mk-rMK, de_CH: de-rCH, oc_FR: oc-rFR, zh_CN: zh-rCN, zh_HK: zh-rHK, zh_SG: zh-rSG, ar_MA: ar-rMA, es_VE: es-rVE, ko_KR: ko-rKR, sr@latin: sr-rSP, ar_IQ: ar-rIQ, ig_NG: ig-rNG, mt_MT: mt-rMT, se_NO: se-rNO, bg_BG: bg-rBG, en_SG: en-rSG, ku_IQ: ku-rIQ, lo_LA: lo-rLA, ml_IN: ml-rIN, smn_FI: smn-rFI, uk_UA: uk-rUA, sr_BA: sr-rBA, mi_NZ: mi-rNZ, ar_DZ: ar-rDZ, hi_IN: hi-rIN, se_FI: se-rFI, fi_FI: fi-rFI, en_PH: en-rPH, ms_BN: ms-rBN, nn_NO: nn-rNO, pt_PT: pt-rPT, af_ZA: af-rZA, km_KH: km-rKH, es_SV: es-rSV, sah_RU: sah-rRU, en_US: en-rUS, id: in, pa_IN: pa-rIN, tt_RU: tt-rRU, ar_SY: ar-rSY, gu_IN: gu-rIN, my_MM: my, es_ES: es-rES, hr_BA: hr-rBA, br_FR: br-rFR, fr_MC: fr-rMC, ms_MY: ms-rMY, vi_VN: vi-rVN, ar_JO: ar-rJO, es_CL: es-rCL, fa_IR: fa-rIR, gl_ES: gl-rES, ps_AF: ps-rAF, ar_QA: ar-rQA, rw_RW: rw-rRW, ro_RO: ro-rRO, de_LI: de-rLI, cs_CZ: cs-rCZ, kl_GL: kl-rGL, es_PE: es-rPE, zh_TW: zh-rTW, fr_BE: fr-rBE, kn_IN: kn-rIN, tn_ZA: tn-rZA, hsb_DE: hsb-rDE, ar_BH: ar-rBH, ar_AE: ar-rAE, en_CA: en-rCA, he_IL: he-rIL, sv_SE: sv-rSE, ta_IN: ta-rIN, es_419: b+es+419, is_IS: is-rIS, iu_CA: iu-rCA, fil_PH: fil-rPH, mn_CN: mn-rCN, nso_ZA: nso-rZA, es_PA: es-rPA, nl_NL: nl-rNL, sk_SK: sk-rSK, en_MY: en-rMY, moh_CA: moh-rCA, cy_GB: cy-rGB, en_ZW: en-rZW, es_BO: es-rBO, es_MX: es-rMX, fr_CA: fr-rCA, it_IT: it-rIT, zh_MO: zh-rMO, sl_SI: sl-rSI, et_EE: et-rEE, gd_GB: gd-rGB, ka_GE: ka-rGE, nb_NO: nb-rNO, se_SE: se-rSE, ur_PK: ur-rPK, wo_SN: wo-rSN, el_GR: el-rGR, es_UY: es-rUY, quz_PE: quz-rPE, he: iw, ru_RU: ru-rRU, es_PR: es-rPR, lv_LV: lv-rLV, te_IN: te-rIN, th_TH: th-rTH, ha_NG: ha-rNG
+30 −119
Original line number Diff line number Diff line
@@ -43,42 +43,17 @@ repositories {
}

dependencies {
    // Note: Starting with Version 0.5.7 Android Gradle Plugin (AGP) Version 7.0.0 or higher is
    // required.
    implementation "com.github.nextcloud:Android-SingleSignOn:0.5.7"
    // Note: Android Gradle Plugin (AGP) version ≥ 7.0.0 is required.
    implementation "com.github.nextcloud:Android-SingleSignOn:0.6.0"
}
```

For Android 11 and later [you need to add queries](https://github.com/nextcloud/Android-SingleSignOn/issues/277) to your app's manifest file. It will not find the Nextcloud app otherwise.

```xml
<queries>
    <package android:name="com.nextcloud.client" />
    <package android:name="com.nextcloud.android.qa" />
    <package android:name="com.nextcloud.android.beta" />
</queries>
```

### 2) To choose an account, include the following code in your login dialog

From an Activity

```java
private void openAccountChooser() {
    try {
        AccountImporter.pickNewAccount(this);
    } catch (NextcloudFilesAppNotInstalledException | AndroidGetAccountsPermissionNotGranted e) {
        UiExceptionManager.showDialogForException(this, e);
    }
}
```

From a Fragment

```java
private void openAccountChooser() {
    try {
        AccountImporter.pickNewAccount(currentFragment);
        AccountImporter.pickNewAccount(activityOrFragment);
    } catch (NextcloudFilesAppNotInstalledException | AndroidGetAccountsPermissionNotGranted e) {
        UiExceptionManager.showDialogForException(this, e);
    }
@@ -87,109 +62,53 @@ private void openAccountChooser() {

### 3) To handle the result of the Account Chooser, include the following

From an Activity

```java
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    AccountImporter.onActivityResult(requestCode, resultCode, data, this, new AccountImporter.IAccountAccessGranted() {

        NextcloudAPI.ApiConnectedListener callback = new NextcloudAPI.ApiConnectedListener() {
            @Override
            public void onConnected() {
                // ignore this one… see 5)
            }

            @Override
            public void onError(Exception ex) {
                // TODO handle errors
            }
        };

        @Override
        public void accountAccessGranted(SingleSignOnAccount account) {
            Context l_context = getApplicationContext();
            final var context = getApplicationContext();

            // As this library supports multiple accounts we created some helper methods if you only want to use one.
            // The following line stores the selected account as the "default" account which can be queried by using
            // the SingleAccountHelper.getCurrentSingleSignOnAccount(context) method
            SingleAccountHelper.setCurrentAccount(l_context, account.name);
            SingleAccountHelper.setCurrentAccount(context, account.name);

            // Get the "default" account
            SingleSignOnAccount ssoAccount = null;
            try {
                ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(l_context);
                ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(context);
            } catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) {
                UiExceptionManager.showDialogForException(l_context, e);
            }

            NextcloudAPI nextcloudAPI = new NextcloudAPI(l_context, ssoAccount, new GsonBuilder().create(), callback);

            // TODO … (see code in section 4 and below)
        }
    });
}
```

From a Fragment

```java
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    AccountImporter.onActivityResult(requestCode, resultCode, data, LoginDialogFragment.this, new AccountImporter.IAccountAccessGranted() {

        NextcloudAPI.ApiConnectedListener callback = new NextcloudAPI.ApiConnectedListener() {
            @Override
            public void onConnected() {
                // ignore this one… see 5)
            }

            @Override
            public void onError(Exception ex) {
                // TODO handle errors
                UiExceptionManager.showDialogForException(context, e);
            }
        };

        @Override
        public void accountAccessGranted(SingleSignOnAccount account) {
            // As this library supports multiple accounts we created some helper methods if you only want to use one.
            // The following line stores the selected account as the "default" account which can be queried by using
            // the SingleAccountHelper.getCurrentSingleSignOnAccount(context) method
            SingleAccountHelper.setCurrentAccount(getActivity(), account.name);

            // Get the "default" account
            SingleSignOnAccount ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(context);
            NextcloudAPI nextcloudAPI = new NextcloudAPI(context, ssoAccount, new GsonBuilder().create(), callback);
            final var nextcloudAPI = new NextcloudAPI(context, ssoAccount, new GsonBuilder().create());

            // TODO … (see code in section 4 and below)
        }
    });
}
```

From both an Activity and Fragment

```java
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    AccountImporter.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}

// Complete example: https://github.com/nextcloud/news-android/blob/890828441ba0c8a9b90afe56f3e08ed63366ece5/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/LoginDialogActivity.java#L470-L475

```

### 4) How to get account information?

```java
// If you stored the "default" account using setCurrentAccount(…) you can get the account by using the following line:
final SingleSignOnAccount ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(context);
final var ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(context);

// Otherwise (for multi-account support): (you'll have to keep track of the account names yourself. Note: this has to be the name of SingleSignOnAccount.name)
// Otherwise (for multi-account support you'll have to keep track of the account names yourself. Note: this has to be the name of SingleSignOnAccount.name)
AccountImporter.getSingleSignOnAccount(context, accountName);

ssoAccount.name; // Name of the account used in the android account manager
@@ -200,13 +119,15 @@ ssoAccount.url;

### 5) How to make a network request?

You'll notice that there is an callback parameter in the constructor of the `NextcloudAPI`.

```java
public NextcloudAPI(Context context, SingleSignOnAccount account, Gson gson, ApiConnectedListener callback) {
public NextcloudAPI(Context context, SingleSignOnAccount account, Gson gson) {
```

You can use this callback to subscribe to errors that might occur during the initialization of the API. You can start making requests to the API as soon as you instantiated the `NextcloudAPI` object. For a minimal example to get started (without retrofit) take a look at section 5.2. The callback method `onConnected` will be called once the connection to the files app is established. You can start making calls to the api before that callback is fired as the library will queue your calls until the connection is established[¹](https://github.com/nextcloud/Android-SingleSignOn/issues/400).
You'll notice that there is an optional `ApiConnectedListener` callback parameter in the constructor of the `NextcloudAPI`.
You can use this callback to subscribe to errors that might occur during the initialization of the API.
You can start making requests to the API as soon as you instantiated the `NextcloudAPI` object.
The callback method `onConnected` will be called once the connection to the files app is established.
You can start making calls to the api before that callback is fired as the library will queue your calls until the connection is established[¹](https://github.com/nextcloud/Android-SingleSignOn/issues/400).

#### 5.1) **Using Retrofit**

@@ -255,8 +176,8 @@ public class ApiProvider {
    private final API mApi;

    public ApiProvider(@NonNull NextcloudAPI.ApiConnectedListener callback) {
       final SingleSignOnAccount ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(context);
       final NextcloudAPI nextcloudAPI = new NextcloudAPI(context, ssoAccount, new GsonBuilder().create(), callback);
       final var ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(context);
       final var nextcloudAPI = new NextcloudAPI(context, ssoAccount, new GsonBuilder().create(), callback);
       mApi = new NextcloudRetrofitApiBuilder(nextcloudAPI, API.mApiEndpoint).create(API.class);
   }
}
@@ -271,8 +192,6 @@ Note: If you need a different mapping between your json-structure and your java-
`NextcloudAPI` provides a method called `performNetworkRequest(NextcloudRequest request)` that allows you to handle the server response yourself.

```java
import java.util.LinkedList;

public class MyActivity extends AppCompatActivity {

    private NextcloudAPI mNextcloudAPI;
@@ -281,8 +200,8 @@ public class MyActivity extends AppCompatActivity {
    protected void onStart() {
        super.onStart();
        try {
            final SingleSignOnAccount ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(this);
            mNextcloudAPI = new NextcloudAPI(this, ssoAccount, new GsonBuilder().create(), apiCallback);
            final var ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(this);
            mNextcloudAPI = new NextcloudAPI(this, ssoAccount, new GsonBuilder().create());

            // Start download of file in background thread (otherwise you'll get a NetworkOnMainThreadException)
            new Thread(this::downloadFile).start();
@@ -299,30 +218,18 @@ public class MyActivity extends AppCompatActivity {
        mNextcloudAPI.stop();
    }

    private NextcloudAPI.ApiConnectedListener apiCallback = new NextcloudAPI.ApiConnectedListener() {
        @Override
        public void onConnected() {
            // ignore this one… see 5)
        }

        @Override
        public void onError(Exception ex) {
            // TODO handle error in your app
        }
    };

    private void downloadFile() {
        final List<Pair<String, String>> parameters = new ArrayList<>();
        parameters.add(new QueryPair("quality", "1024p"));
        parameters.add(new Pair<>("someOtherParameter", "parameterValue"));
        
        final NextcloudRequest nextcloudRequest = new NextcloudRequest.Builder()
        final var nextcloudRequest = new NextcloudRequest.Builder()
                .setMethod("GET")
                .setParameter(parameters)
                .setUrl(Uri.encode("/remote.php/webdav/sample movie.mp4","/"))
                .build();

        try (InputStream inputStream = mNextcloudAPI.performNetworkRequest(nextcloudRequest)) {
        try (final var inputStream = mNextcloudAPI.performNetworkRequest(nextcloudRequest)) {
            while(inputStream.available() > 0) {
                inputStream.read();
                // TODO do something useful with the data here..
@@ -346,7 +253,7 @@ final List<String> depth = new ArrayList<>();
depth.add("0");
header.put("Depth", depth);

final NextcloudRequest nextcloudRequest = new NextcloudRequest.Builder()
final var nextcloudRequest = new NextcloudRequest.Builder()
        .setMethod("PROPFIND")
        .setHeader(header)
        .setUrl(Uri.encode("/remote.php/webdav/" + remotePath, "/"))
@@ -360,7 +267,7 @@ In case that you require some sso features that were introduced in a specific ne
```java
final int MIN_NEXTCLOUD_FILES_APP_VERSION_CODE = 30030052;

if (VersionCheckHelper.verifyMinVersion(context, MIN_NEXTCLOUD_FILES_APP_VERSION_CODE)) {
if (VersionCheckHelper.verifyMinVersion(context, MIN_NEXTCLOUD_FILES_APP_VERSION_CODE, FilesAppType.PROD)) {
   // Version requirement is satisfied!
}
```
@@ -397,6 +304,10 @@ Once the user clicks on "Allow" in the login dialog, the Nextcloud Files App wil
- [Nextcloud Deck app](https://github.com/stefan-niedermann/nextcloud-deck/)
  - [API](https://github.com/stefan-niedermann/nextcloud-deck/blob/master/app/src/main/java/it/niedermann/nextcloud/deck/api/DeckAPI.java)
  - [Login](https://github.com/stefan-niedermann/nextcloud-deck/blob/master/app/src/main/java/it/niedermann/nextcloud/deck/ui/ImportAccountActivity.java#L77)
- [Nextcloud Bookmarks app](https://gitlab.com/bisada/OCBookmarks)
  - [API](https://gitlab.com/bisada/OCBookmarks/-/blob/master/app/src/main/java/org/schabi/ocbookmarks/REST/OCBookmarksRestConnector.java#L42)
  - [Login](https://gitlab.com/bisada/OCBookmarks/-/blob/master/app/src/main/java/org/schabi/ocbookmarks/MainActivity.java#L261)


## Troubleshooting

@@ -413,4 +324,4 @@ Note that the "Make network request" section in the diagram only shows the workf

# Translations

We manage translations via [Transifex](https://www.transifex.com/nextcloud/nextcloud/android-singlesignon/). So just request joining the translation team for Android on the site and start translating. All translations will then be automatically pushed to this repository, there is no need for any pull request for translations.
We manage translations via [Transifex](https://app.transifex.com/nextcloud/nextcloud/android-singlesignon/). So just request joining the translation team for Android on the site and start translating. All translations will then be automatically pushed to this repository, there is no need for any pull request for translations.
+3 −7
Original line number Diff line number Diff line
buildscript {
    ext {
        kotlin_version = '1.5.31'
        kotlin_version = '1.8.20'
    }
    repositories {
        google()
        maven {
            url 'https://oss.sonatype.org/content/repositories/snapshots/'
        }
        maven {
            url 'https://plugins.gradle.org/m2/'
        }
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:7.0.3'
        classpath 'com.android.tools.build:gradle:7.4.2'
        classpath 'gradle.plugin.com.github.spotbugs.snom:spotbugs-gradle-plugin:4.7.5'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.18.1"
        classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.22.0"
    }
}

allprojects {
    repositories {
        google()
        maven { url "https://jitpack.io" }
        mavenCentral()
        maven {
            url 'https://plugins.gradle.org/m2/'
+4.71 KiB (58.1 KiB)

File changed.

No diff preview for this file type.

Loading