diff --git a/app/build.gradle b/app/build.gradle index 7e875abf5f..f4ea8d9fd0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -261,7 +261,11 @@ dependencies { implementation "com.github.cotechde.hwsecurity:hwsecurity-fido:$fidoVersion" implementation "com.github.cotechde.hwsecurity:hwsecurity-fido2:$fidoVersion" - implementation 'com.github.zynkware:Document-Scanning-Android-SDK:1.0.1' + // document scanner not available on FDroid (generic) due to OpenCV binaries + gplayImplementation "com.github.zynkware:Document-Scanning-Android-SDK:$documentScannerVersion" + huaweiImplementation "com.github.zynkware:Document-Scanning-Android-SDK:$documentScannerVersion" + qaImplementation "com.github.zynkware:Document-Scanning-Android-SDK:$documentScannerVersion" + versionDevImplementation "com.github.zynkware:Document-Scanning-Android-SDK:$documentScannerVersion" spotbugsPlugins 'com.h3xstream.findsecbugs:findsecbugs-plugin:1.12.0' spotbugsPlugins 'com.mebigfatguy.fb-contrib:fb-contrib:7.4.7' diff --git a/app/src/generic/AndroidManifest.xml b/app/src/generic/AndroidManifest.xml new file mode 100644 index 0000000000..660a75a34e --- /dev/null +++ b/app/src/generic/AndroidManifest.xml @@ -0,0 +1,30 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/generic/java/com/owncloud/android/ui/activity/AppScanActivity.kt b/app/src/generic/java/com/owncloud/android/ui/activity/AppScanActivity.kt new file mode 100644 index 0000000000..632a8db524 --- /dev/null +++ b/app/src/generic/java/com/owncloud/android/ui/activity/AppScanActivity.kt @@ -0,0 +1,42 @@ +/* + * + * Nextcloud Android client application + * + * @author Tobias Kaminsky + * Copyright (C) 2022 Tobias Kaminsky + * Copyright (C) 2022 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.ui.activity + +import android.app.Activity +import com.owncloud.android.lib.common.utils.Log_OC + +class AppScanActivity { + // stub + companion object { + private val TAG = AppScanActivity::class.simpleName + + @JvmStatic + val enabled: Boolean = false + + @JvmStatic + fun scanFromCamera(activity: Activity, requestcode: Int) { + // stub + Log_OC.w(TAG, "scanFromCamera called in stub implementation") + } + } +} diff --git a/app/src/gplay/java/com/owncloud/android/ui/activity/AppScanActivity.kt b/app/src/gplay/java/com/owncloud/android/ui/activity/AppScanActivity.kt new file mode 100644 index 0000000000..cc229efde9 --- /dev/null +++ b/app/src/gplay/java/com/owncloud/android/ui/activity/AppScanActivity.kt @@ -0,0 +1,81 @@ +/* + * Nextcloud Android client application + * + * @author Álvaro Brey Vilas + * Copyright (C) 2022 Álvaro Brey Vilas + * Copyright (C) 2022 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.ui.activity + +import android.Manifest +import android.app.Activity +import android.content.Intent +import android.graphics.Bitmap +import android.os.Bundle +import com.owncloud.android.R +import com.owncloud.android.utils.DisplayUtils +import com.owncloud.android.utils.PermissionUtil +import com.zynksoftware.documentscanner.ScanActivity +import com.zynksoftware.documentscanner.model.DocumentScannerErrorModel +import com.zynksoftware.documentscanner.model.ScannerResults +import com.zynksoftware.documentscanner.ui.DocumentScanner + +@Suppress("unused") +class AppScanActivity : ScanActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + addFragmentContentLayout() + } + + override fun onError(error: DocumentScannerErrorModel) { + DisplayUtils.showSnackMessage(this, R.string.error_starting_scan_doc) + } + + override fun onSuccess(scannerResults: ScannerResults) { + val intent = Intent() + + intent.putExtra( + "file", + scannerResults.transformedImageFile?.absolutePath ?: scannerResults.croppedImageFile?.absolutePath + ) + + setResult(Activity.RESULT_OK, intent) + finish() + } + + override fun onClose() { + finish() + } + + companion object { + @JvmStatic + val enabled: Boolean = true + + @JvmStatic + fun scanFromCamera(activity: Activity, requestCode: Int) { + val configuration = DocumentScanner.Configuration() + configuration.imageType = Bitmap.CompressFormat.PNG + DocumentScanner.init(activity, configuration) + val scanIntent = Intent(activity, AppScanActivity::class.java) + if (PermissionUtil.checkSelfPermission(activity, Manifest.permission.CAMERA)) { + activity.startActivityForResult(scanIntent, requestCode) + } else { + PermissionUtil.requestCameraPermission(activity, PermissionUtil.PERMISSIONS_SCAN_DOCUMENT) + } + } + } +} diff --git a/app/src/huawei/java/com/owncloud/android/ui.activity/HuaweiCommunityActivity.kt b/app/src/huawei/java/com/owncloud/android/ui.activity/HuaweiCommunityActivity.kt deleted file mode 100644 index 46ce50b819..0000000000 --- a/app/src/huawei/java/com/owncloud/android/ui.activity/HuaweiCommunityActivity.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Nextcloud Android client application - * - * @author Tobias Kaminsky - * Copyright (C) 2021 Nextcloud - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU AFFERO GENERAL PUBLIC LICENSE for more details. - * - * You should have received a copy of the GNU Affero General Public - * License along with this program. If not, see . - */ -package com.owncloud.android.ui.activity - -import android.view.View - -/** - * Activity providing information about ways to participate in the app's development. - */ -class HuaweiCommunityActivity : CommunityActivity() { - override fun setupContent() { - super.setupContent() - binding.communityReleaseCandidatePlaystore.visibility = View.GONE - } -} diff --git a/app/src/main/java/com/owncloud/android/ui/activity/AppScanActivity.kt b/app/src/huawei/java/com/owncloud/android/ui/activity/AppScanActivity.kt similarity index 58% rename from app/src/main/java/com/owncloud/android/ui/activity/AppScanActivity.kt rename to app/src/huawei/java/com/owncloud/android/ui/activity/AppScanActivity.kt index 6d80172b13..a1c17b8999 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/AppScanActivity.kt +++ b/app/src/huawei/java/com/owncloud/android/ui/activity/AppScanActivity.kt @@ -1,35 +1,38 @@ /* - * * Nextcloud Android client application * - * @author Tobias Kaminsky - * Copyright (C) 2022 Tobias Kaminsky + * @author Álvaro Brey Vilas + * Copyright (C) 2022 Álvaro Brey Vilas * Copyright (C) 2022 Nextcloud GmbH * * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by + * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. + * GNU General Public License for more details. * - * You should have received a copy of the GNU Affero General Public License + * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package com.owncloud.android.ui.activity +import android.Manifest import android.app.Activity import android.content.Intent +import android.graphics.Bitmap import android.os.Bundle import com.owncloud.android.R import com.owncloud.android.utils.DisplayUtils +import com.owncloud.android.utils.PermissionUtil import com.zynksoftware.documentscanner.ScanActivity import com.zynksoftware.documentscanner.model.DocumentScannerErrorModel import com.zynksoftware.documentscanner.model.ScannerResults +import com.zynksoftware.documentscanner.ui.DocumentScanner class AppScanActivity : ScanActivity() { override fun onCreate(savedInstanceState: Bundle?) { @@ -56,4 +59,22 @@ class AppScanActivity : ScanActivity() { override fun onClose() { finish() } + + companion object { + @JvmStatic + val enabled: Boolean = true + + @JvmStatic + fun scanFromCamera(activity: Activity, requestCode: Int) { + val configuration = DocumentScanner.Configuration() + configuration.imageType = Bitmap.CompressFormat.PNG + DocumentScanner.init(activity, configuration) + val scanIntent = Intent(activity, AppScanActivity::class.java) + if (PermissionUtil.checkSelfPermission(activity, Manifest.permission.CAMERA)) { + activity.startActivityForResult(scanIntent, requestCode) + } else { + PermissionUtil.requestCameraPermission(activity, PermissionUtil.PERMISSIONS_SCAN_DOCUMENT) + } + } + } } diff --git a/app/src/huawei/java/com/owncloud/android/ui/activity/HuaweiCommunityActivity.kt b/app/src/huawei/java/com/owncloud/android/ui/activity/HuaweiCommunityActivity.kt new file mode 100644 index 0000000000..bc3bf0e17f --- /dev/null +++ b/app/src/huawei/java/com/owncloud/android/ui/activity/HuaweiCommunityActivity.kt @@ -0,0 +1,33 @@ +/* + * Nextcloud Android client application + * + * @author Álvaro Brey Vilas + * Copyright (C) 2022 Álvaro Brey Vilas + * Copyright (C) 2022 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.owncloud.android.ui.activity + +import android.view.View + +/** + * Activity providing information about ways to participate in the app's development. + */ +class HuaweiCommunityActivity : CommunityActivity() { + override fun setupContent() { + super.setupContent() + binding.communityReleaseCandidatePlaystore.visibility = View.GONE + } +} diff --git a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java index a83bfb4b0a..be8d922e90 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java +++ b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java @@ -399,7 +399,7 @@ public class FileDisplayActivity extends FileActivity // If request is cancelled, result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // permission was granted - getFileOperationsHelper().scanFromCamera( + AppScanActivity.scanFromCamera( this, FileDisplayActivity.REQUEST_CODE__UPLOAD_SCAN_DOC_FROM_CAMERA); } diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListBottomSheetDialog.java b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListBottomSheetDialog.java index 84be01db91..f5a83957fc 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListBottomSheetDialog.java +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListBottomSheetDialog.java @@ -38,6 +38,7 @@ import com.owncloud.android.files.FileMenuFilter; import com.owncloud.android.lib.common.Creator; import com.owncloud.android.lib.common.DirectEditing; import com.owncloud.android.lib.resources.status.OCCapability; +import com.owncloud.android.ui.activity.AppScanActivity; import com.owncloud.android.ui.activity.FileActivity; import com.owncloud.android.utils.MimeTypeUtil; import com.owncloud.android.utils.theme.ThemeColorUtils; @@ -183,10 +184,14 @@ public class OCFileListBottomSheetDialog extends BottomSheetDialog { dismiss(); }); - binding.menuScanDocUpload.setOnClickListener(v -> { - actions.scanDocUpload(); - dismiss(); - }); + if(AppScanActivity.getEnabled()) { + binding.menuScanDocUpload.setOnClickListener(v -> { + actions.scanDocUpload(); + dismiss(); + }); + }else { + binding.menuScanDocUpload.setVisibility(View.GONE); + } binding.menuUploadFiles.setOnClickListener(v -> { actions.uploadFiles(); diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java index 8c509146e5..60c07b8b3f 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java @@ -72,6 +72,7 @@ import com.owncloud.android.lib.resources.e2ee.ToggleEncryptionRemoteOperation; import com.owncloud.android.lib.resources.files.SearchRemoteOperation; import com.owncloud.android.lib.resources.files.ToggleFavoriteRemoteOperation; import com.owncloud.android.lib.resources.status.OCCapability; +import com.owncloud.android.ui.activity.AppScanActivity; import com.owncloud.android.ui.activity.FileActivity; import com.owncloud.android.ui.activity.FileDisplayActivity; import com.owncloud.android.ui.activity.FolderPickerActivity; @@ -486,7 +487,7 @@ public class OCFileListFragment extends ExtendedListFragment implements FileDisplayActivity fileDisplayActivity = (FileDisplayActivity) getActivity(); if (fileDisplayActivity != null) { - fileDisplayActivity.getFileOperationsHelper() + AppScanActivity .scanFromCamera(fileDisplayActivity, FileDisplayActivity.REQUEST_CODE__UPLOAD_SCAN_DOC_FROM_CAMERA); } else { Toast.makeText(getContext(), diff --git a/app/src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java b/app/src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java index e207221654..2f42f28956 100755 --- a/app/src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java +++ b/app/src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java @@ -37,7 +37,6 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; -import android.graphics.Bitmap; import android.net.Uri; import android.os.Build; import android.os.Environment; @@ -69,7 +68,6 @@ import com.owncloud.android.lib.resources.shares.ShareType; import com.owncloud.android.lib.resources.status.OCCapability; import com.owncloud.android.operations.SynchronizeFileOperation; import com.owncloud.android.services.OperationsService; -import com.owncloud.android.ui.activity.AppScanActivity; import com.owncloud.android.ui.activity.ConflictsResolveActivity; import com.owncloud.android.ui.activity.ExternalSiteWebView; import com.owncloud.android.ui.activity.FileActivity; @@ -86,7 +84,6 @@ import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.FileStorageUtils; import com.owncloud.android.utils.PermissionUtil; import com.owncloud.android.utils.UriUtils; -import com.zynksoftware.documentscanner.ui.DocumentScanner; import org.greenrobot.eventbus.EventBus; @@ -1075,19 +1072,6 @@ public class FileOperationsHelper { } } - public void scanFromCamera(Activity activity, int requestCode) { - DocumentScanner.Configuration configuration = new DocumentScanner.Configuration(); - configuration.setImageType(Bitmap.CompressFormat.PNG); - DocumentScanner.INSTANCE.init(activity, configuration); - - Intent scanIntent = new Intent(activity, AppScanActivity.class); - if (PermissionUtil.checkSelfPermission(activity, Manifest.permission.CAMERA)) { - activity.startActivityForResult(scanIntent, requestCode); - } else { - PermissionUtil.requestCameraPermission(activity, PermissionUtil.PERMISSIONS_SCAN_DOCUMENT); - } - } - public static File createImageFile(Activity activity) { File storageDir = activity.getExternalFilesDir(Environment.DIRECTORY_PICTURES); diff --git a/app/src/qa/java/com/owncloud/android/ui/activity/AppScanActivity.kt b/app/src/qa/java/com/owncloud/android/ui/activity/AppScanActivity.kt new file mode 100644 index 0000000000..a1c17b8999 --- /dev/null +++ b/app/src/qa/java/com/owncloud/android/ui/activity/AppScanActivity.kt @@ -0,0 +1,80 @@ +/* + * Nextcloud Android client application + * + * @author Álvaro Brey Vilas + * Copyright (C) 2022 Álvaro Brey Vilas + * Copyright (C) 2022 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.ui.activity + +import android.Manifest +import android.app.Activity +import android.content.Intent +import android.graphics.Bitmap +import android.os.Bundle +import com.owncloud.android.R +import com.owncloud.android.utils.DisplayUtils +import com.owncloud.android.utils.PermissionUtil +import com.zynksoftware.documentscanner.ScanActivity +import com.zynksoftware.documentscanner.model.DocumentScannerErrorModel +import com.zynksoftware.documentscanner.model.ScannerResults +import com.zynksoftware.documentscanner.ui.DocumentScanner + +class AppScanActivity : ScanActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + addFragmentContentLayout() + } + + override fun onError(error: DocumentScannerErrorModel) { + DisplayUtils.showSnackMessage(this, R.string.error_starting_scan_doc) + } + + override fun onSuccess(scannerResults: ScannerResults) { + val intent = Intent() + + intent.putExtra( + "file", + scannerResults.transformedImageFile?.absolutePath ?: scannerResults.croppedImageFile?.absolutePath + ) + + setResult(Activity.RESULT_OK, intent) + finish() + } + + override fun onClose() { + finish() + } + + companion object { + @JvmStatic + val enabled: Boolean = true + + @JvmStatic + fun scanFromCamera(activity: Activity, requestCode: Int) { + val configuration = DocumentScanner.Configuration() + configuration.imageType = Bitmap.CompressFormat.PNG + DocumentScanner.init(activity, configuration) + val scanIntent = Intent(activity, AppScanActivity::class.java) + if (PermissionUtil.checkSelfPermission(activity, Manifest.permission.CAMERA)) { + activity.startActivityForResult(scanIntent, requestCode) + } else { + PermissionUtil.requestCameraPermission(activity, PermissionUtil.PERMISSIONS_SCAN_DOCUMENT) + } + } + } +} diff --git a/app/src/versionDev/java/com/owncloud/android/ui/activity/AppScanActivity.kt b/app/src/versionDev/java/com/owncloud/android/ui/activity/AppScanActivity.kt new file mode 100644 index 0000000000..a1c17b8999 --- /dev/null +++ b/app/src/versionDev/java/com/owncloud/android/ui/activity/AppScanActivity.kt @@ -0,0 +1,80 @@ +/* + * Nextcloud Android client application + * + * @author Álvaro Brey Vilas + * Copyright (C) 2022 Álvaro Brey Vilas + * Copyright (C) 2022 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.ui.activity + +import android.Manifest +import android.app.Activity +import android.content.Intent +import android.graphics.Bitmap +import android.os.Bundle +import com.owncloud.android.R +import com.owncloud.android.utils.DisplayUtils +import com.owncloud.android.utils.PermissionUtil +import com.zynksoftware.documentscanner.ScanActivity +import com.zynksoftware.documentscanner.model.DocumentScannerErrorModel +import com.zynksoftware.documentscanner.model.ScannerResults +import com.zynksoftware.documentscanner.ui.DocumentScanner + +class AppScanActivity : ScanActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + addFragmentContentLayout() + } + + override fun onError(error: DocumentScannerErrorModel) { + DisplayUtils.showSnackMessage(this, R.string.error_starting_scan_doc) + } + + override fun onSuccess(scannerResults: ScannerResults) { + val intent = Intent() + + intent.putExtra( + "file", + scannerResults.transformedImageFile?.absolutePath ?: scannerResults.croppedImageFile?.absolutePath + ) + + setResult(Activity.RESULT_OK, intent) + finish() + } + + override fun onClose() { + finish() + } + + companion object { + @JvmStatic + val enabled: Boolean = true + + @JvmStatic + fun scanFromCamera(activity: Activity, requestCode: Int) { + val configuration = DocumentScanner.Configuration() + configuration.imageType = Bitmap.CompressFormat.PNG + DocumentScanner.init(activity, configuration) + val scanIntent = Intent(activity, AppScanActivity::class.java) + if (PermissionUtil.checkSelfPermission(activity, Manifest.permission.CAMERA)) { + activity.startActivityForResult(scanIntent, requestCode) + } else { + PermissionUtil.requestCameraPermission(activity, PermissionUtil.PERMISSIONS_SCAN_DOCUMENT) + } + } + } +} diff --git a/build.gradle b/build.gradle index f66cb13427..bf511c90e1 100644 --- a/build.gradle +++ b/build.gradle @@ -17,6 +17,7 @@ buildscript { fidoVersion = "4.1.0" checkerVersion = "3.21.2" exoplayerVersion = "2.17.1" + documentScannerVersion = "1.0.1" ciBuild = System.getenv("CI") == "true" }