Skip to content

Commit

Permalink
Merge pull request #520 from gini/PM-86-android-15
Browse files Browse the repository at this point in the history
Pm 86 android 15
  • Loading branch information
a-szotyori authored Aug 12, 2024
2 parents 60c3743 + aeae78c commit df2ec81
Show file tree
Hide file tree
Showing 21 changed files with 243 additions and 45 deletions.
5 changes: 3 additions & 2 deletions bank-api-library/library/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ android {
}
defaultConfig {
minSdk = libs.versions.android.minSdk.get().toInt()
targetSdk = libs.versions.android.targetSdk.get().toInt()
testOptions.targetSdk = libs.versions.android.targetSdk.get().toInt()
lint.targetSdk = libs.versions.android.targetSdk.get().toInt()

// Use the test runner with JUnit4 support
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
Expand Down Expand Up @@ -113,7 +114,7 @@ tasks.register<CreatePropertiesTask>("injectTestProperties") {

doFirst {
propertiesMap.clear()
propertiesMap.putAll(readLocalPropertiesToMap(project,
propertiesMap.putAll(readLocalPropertiesToMapSilent(project,
listOf("testClientId", "testClientSecret", "testApiUri", "testUserCenterUri", "testHealthApiUri")))
}

Expand Down
2 changes: 1 addition & 1 deletion bank-sdk/example-app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<application
android:name=".ExampleApp"
android:allowBackup="true"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:largeHeap="true"
Expand Down
8 changes: 5 additions & 3 deletions bank-sdk/sdk/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ android {
}
defaultConfig {
minSdk = libs.versions.android.minSdk.get().toInt()
targetSdk = libs.versions.android.targetSdk.get().toInt()
testOptions.targetSdk = libs.versions.android.targetSdk.get().toInt()
lint.targetSdk = libs.versions.android.targetSdk.get().toInt()

// Use the test runner with JUnit4 support
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
Expand Down Expand Up @@ -164,8 +165,9 @@ tasks.register<CreatePropertiesTask>("injectTestProperties") {

doFirst {
propertiesMap.clear()
propertiesMap.putAll(readLocalPropertiesToMap(project,
listOf("testClientId", "testClientSecret", "testApiUri", "testUserCenterUri")))
propertiesMap.putAll(readLocalPropertiesToMapSilent(project,
listOf("testClientId", "testClientSecret", "testApiUri", "testUserCenterUri"))
)
}

destinations.put(
Expand Down
5 changes: 3 additions & 2 deletions capture-sdk/default-network/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ android {
}
defaultConfig {
minSdk = libs.versions.android.minSdk.get().toInt()
targetSdk = libs.versions.android.targetSdk.get().toInt()
testOptions.targetSdk = libs.versions.android.targetSdk.get().toInt()
lint.targetSdk = libs.versions.android.targetSdk.get().toInt()

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
Expand Down Expand Up @@ -119,7 +120,7 @@ tasks.register<CreatePropertiesTask>("injectTestProperties") {

doFirst {
propertiesMap.clear()
propertiesMap.putAll(readLocalPropertiesToMap(project,
propertiesMap.putAll(readLocalPropertiesToMapSilent(project,
listOf("testClientId", "testClientSecret", "testApiUri", "testUserCenterUri")))
}

Expand Down
3 changes: 2 additions & 1 deletion capture-sdk/sdk/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ android {
}
defaultConfig {
minSdk = libs.versions.android.minSdk.get().toInt()
targetSdk = libs.versions.android.targetSdk.get().toInt()
testOptions.targetSdk = libs.versions.android.targetSdk.get().toInt()
lint.targetSdk = libs.versions.android.targetSdk.get().toInt()

// Use the test runner with JUnit4 support
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
Expand Down
11 changes: 11 additions & 0 deletions capture-sdk/sdk/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="net.gini.android.capture">

<uses-permission android:name="android.permission.VIBRATE" />
Expand All @@ -18,6 +19,16 @@
<meta-data
android:name="com.google.mlkit.vision.DEPENDENCIES"
android:value="barcode,ocr" />
<!-- Trigger Google Play services to install the backported photo picker module. -->
<service android:name="com.google.android.gms.metadata.ModuleDependencies"
android:enabled="false"
android:exported="false"
tools:ignore="MissingClass">
<intent-filter>
<action android:name="com.google.android.gms.metadata.MODULE_DEPENDENCIES" />
</intent-filter>
<meta-data android:name="photopicker_activity:0:required" android:value="" />
</service>

<!--Routing Mixpanel to EU Servers-->
<meta-data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,8 @@ private void setFileChooserFragmentResultListener() {
public void handleFileChooserResult(@NonNull FileChooserResult result) {
if (result instanceof FileChooserResult.FilesSelected) {
importDocumentFromIntent(((FileChooserResult.FilesSelected) result).getDataIntent());
} else if(result instanceof FileChooserResult.FilesSelectedUri) {
importDocumentFromUriList(((FileChooserResult.FilesSelectedUri) result).getList());
} else if (result instanceof FileChooserResult.Error) {
final GiniCaptureError error = ((FileChooserResult.Error) result).getError();
final String message = "Document import failed: " + error.getMessage();
Expand Down Expand Up @@ -1203,6 +1205,13 @@ private void importDocumentFromIntent(@NonNull final Intent data) {
}
}

private void importDocumentFromUriList(List<Uri> uriList) {
if (mFragment.getActivity() == null)
return;

handleMultiPageDocumentAndCallListener(mFragment.getActivity(), new Intent(Intent.ACTION_PICK), uriList);
}

private boolean isImage(@NonNull final Intent data, @NonNull final Activity activity) {
return IntentHelper.hasMimeTypeWithPrefix(data, activity, MimeType.IMAGE_PREFIX.asString());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ internal class CameraXController(val activity: Activity) : CameraInterface {

val imageAnalysis = ImageAnalysis.Builder()
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.setTargetResolution(targetResolution)
.setResolutionSelector(resolutionSelector)
.setTargetRotation(targetRotation)
.build()
imageAnalysisUseCase = imageAnalysis
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import android.app.Dialog
import android.content.Context
import android.content.Intent
import android.content.pm.ResolveInfo
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Parcelable
Expand All @@ -15,7 +16,9 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat
import androidx.fragment.app.setFragmentResult
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.GridLayoutManager
Expand All @@ -30,6 +33,7 @@ import net.gini.android.capture.R
import net.gini.android.capture.databinding.GcFragmentFileChooserBinding
import net.gini.android.capture.internal.fileimport.providerchooser.ProvidersAdapter
import net.gini.android.capture.internal.fileimport.providerchooser.ProvidersAppItem
import net.gini.android.capture.internal.fileimport.providerchooser.ProvidersAppWrapperItem
import net.gini.android.capture.internal.fileimport.providerchooser.ProvidersItem
import net.gini.android.capture.internal.fileimport.providerchooser.ProvidersSectionItem
import net.gini.android.capture.internal.fileimport.providerchooser.ProvidersSeparatorItem
Expand Down Expand Up @@ -57,6 +61,7 @@ class FileChooserFragment : BottomSheetDialogFragment() {
private var docImportEnabledFileTypes: DocumentImportEnabledFileTypes? = null
private var binding: GcFragmentFileChooserBinding by autoCleared()
private var chooseFileLauncher: ActivityResultLauncher<Intent>? = null
private var pickMedia: ActivityResultLauncher<PickVisualMediaRequest>? = null
private lateinit var mUserAnalyticsEventTracker: UserAnalyticsEventTracker
private val screenName: UserAnalyticsScreen = UserAnalyticsScreen.Camera

Expand Down Expand Up @@ -152,6 +157,46 @@ class FileChooserFragment : BottomSheetDialogFragment() {
})
}
}

val photoPickType =
if (FeatureConfiguration.isMultiPageEnabled()) {
ActivityResultContracts.PickMultipleVisualMedia(maxItems = 10)
} else {
ActivityResultContracts.PickVisualMedia()
}

pickMedia = registerForActivityResult(photoPickType) { activityResultUriList ->
findNavController().popBackStack()
val resultList = handleUriList(activityResultUriList)
setFragmentResult(REQUEST_KEY, Bundle().apply {
putParcelable(RESULT_KEY, resultList)
})
}
}

private fun handleUriList(activityResultUriList: Any?): FileChooserResult {
return if (activityResultUriList == null) {
FileChooserResult.Cancelled
} else {
try {
val uriList = when(activityResultUriList){
is Uri -> listOf(activityResultUriList)
is List<*> -> {
activityResultUriList.filterIsInstance<Uri>().takeIf {
it.size == activityResultUriList.size
} ?: throw IllegalArgumentException("List contains non-Uri elements")
}
else -> throw IllegalArgumentException("uri is neither Uri nor List<Uri>")
}
if (uriList.isNotEmpty()) {
FileChooserResult.FilesSelectedUri(uriList)
} else {
FileChooserResult.Cancelled
}
} catch (e: IllegalArgumentException) {
FileChooserResult.Error(GiniCaptureError(GiniCaptureError.ErrorCode.DOCUMENT_IMPORT, e.message))
}
}
}

private fun getGridSpanCount(): Int =
Expand All @@ -164,15 +209,20 @@ class FileChooserFragment : BottomSheetDialogFragment() {

private fun populateFileProviders() {
val providerItems: MutableList<ProvidersItem> = ArrayList()
var imageProviderItems: List<ProvidersItem> = ArrayList()
var imageProviderItems: List<ProvidersItem> = arrayListOf()
var pdfProviderItems: List<ProvidersItem> = ArrayList()
if (shouldShowImageProviders()) {
val imagePickerResolveInfos = queryImagePickers(requireContext())
val imageProviderResolveInfos = queryImageProviders(requireContext())
imageProviderItems = getImageProviderItems(
imagePickerResolveInfos,
imageProviderResolveInfos
)

imageProviderItems =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
ActivityResultContracts.PickVisualMedia.isPhotoPickerAvailable(requireContext())
) {
getPhotoPickerProvider()
} else {
getImageProviderItems(imagePickerResolveInfos, imageProviderResolveInfos)
}
}
if (shouldShowPdfProviders()) {
val pdfProviderResolveInfos = queryPdfProviders(requireContext())
Expand Down Expand Up @@ -204,12 +254,26 @@ class FileChooserFragment : BottomSheetDialogFragment() {
}
}

private fun launchApp(item: ProvidersAppItem) {
item.intent.setClassName(
item.resolveInfo.activityInfo.packageName,
item.resolveInfo.activityInfo.name
)
chooseFileLauncher?.launch(item.intent)
private fun launchApp(item: ProvidersItem) {
when (item) {
is ProvidersAppItem -> {
item.intent.setClassName(
item.resolveInfo.activityInfo.packageName,
item.resolveInfo.activityInfo.name
)
chooseFileLauncher?.launch(item.intent)
}

is ProvidersAppWrapperItem -> {
pickMedia?.launch(
PickVisualMediaRequest(
ActivityResultContracts.PickVisualMedia.SingleMimeType(
MimeType.IMAGE_WILDCARD.asString()
)
)
)
}
}
}

private fun getImageProviderItems(
Expand All @@ -233,6 +297,23 @@ class FileChooserFragment : BottomSheetDialogFragment() {
}
}

private fun getPhotoPickerProvider(): List<ProvidersItem> {
val providerList =
ContextCompat.getDrawable(requireContext(), (R.drawable.gc_photo_picker_app_icon))
?.let { image ->
listOf(
ProvidersSectionItem(getString(R.string.gc_file_chooser_fotos_section_header)),
ProvidersAppWrapperItem(
image,
getString(R.string.gc_file_chooser_fotos_section_header)
)
)
} ?: run {
emptyList()
}
return providerList
}

private fun getPdfProviderItems(pdfProviderResolveInfos: List<ResolveInfo>): List<ProvidersItem> =
mutableListOf<ProvidersItem>().apply {
if (pdfProviderResolveInfos.isNotEmpty()) {
Expand Down Expand Up @@ -340,6 +421,7 @@ class FileChooserFragment : BottomSheetDialogFragment() {
@Parcelize
sealed class FileChooserResult : Parcelable {
data class FilesSelected(val dataIntent: Intent) : FileChooserResult()
data class FilesSelectedUri(val list: List<Uri>) : FileChooserResult()
data class Error(val error: GiniCaptureError) : FileChooserResult()
object Cancelled : FileChooserResult()
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,14 @@ public int getItemViewType(final int position) {

@Override
public ProvidersItemViewHolder onCreateViewHolder(final ViewGroup parent,
final int viewType) {
final int viewType) {
switch (ProvidersItem.FileProviderItemType.fromOrdinal(viewType)) {
case SECTION:
return createSectionItemViewHolder(parent);
case APP:
return createAppItemViewHolder(parent);
return createAppItemViewHolder(parent, ProvidersItem.FileProviderItemType.APP);
case APP_WRAPPER_PHOTO_PICKER:
return createAppItemViewHolder(parent, ProvidersItem.FileProviderItemType.APP_WRAPPER_PHOTO_PICKER);
case SEPARATOR:
return createSeparatorItemViewHolder(parent);
default:
Expand All @@ -62,10 +64,12 @@ private ProvidersItemViewHolder createSectionItemViewHolder(
}

@NonNull
private ProvidersItemViewHolder createAppItemViewHolder(@NonNull final ViewGroup parent) {
private ProvidersItemViewHolder createAppItemViewHolder(
@NonNull final ViewGroup parent,
@NonNull ProvidersItem.FileProviderItemType providerItemType) {
final View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.gc_item_file_provider_app, parent, false);
return new ProvidersAppItemViewHolder(itemView);
return new ProvidersAppItemViewHolder(itemView, providerItemType);
}

private ProvidersItemViewHolder createSeparatorItemViewHolder(@NonNull final ViewGroup parent) {
Expand All @@ -83,6 +87,9 @@ public void onBindViewHolder(final ProvidersItemViewHolder holder, final int pos
case APP:
bindAppItemViewHolder((ProvidersAppItemViewHolder) holder, position);
break;
case APP_WRAPPER_PHOTO_PICKER:
bindAppWrapperItemViewHolder((ProvidersAppItemViewHolder) holder, position);
break;
case SEPARATOR:
break;
default:
Expand All @@ -101,13 +108,22 @@ private void bindAppItemViewHolder(@NonNull final ProvidersAppItemViewHolder hol
final ProvidersAppItem item = (ProvidersAppItem) mItems.get(position);
holder.icon.setImageDrawable(item.getResolveInfo().loadIcon(mContext.getPackageManager()));
holder.label.setText(item.getResolveInfo().loadLabel(mContext.getPackageManager()));
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
final ProvidersAppItem item =
(ProvidersAppItem) mItems.get(holder.getAdapterPosition());
mItemSelectedListener.onItemSelected(item);
}
holder.itemView.setOnClickListener(view -> {
final ProvidersAppItem selectedItem =
(ProvidersAppItem) mItems.get(holder.getAdapterPosition());
mItemSelectedListener.onItemSelected(selectedItem);
});
}

private void bindAppWrapperItemViewHolder(@NonNull final ProvidersAppItemViewHolder holder,
final int position) {
final ProvidersAppWrapperItem item = (ProvidersAppWrapperItem) mItems.get(position);
holder.icon.setImageDrawable(item.getDrawableIcon());
holder.label.setText(item.getText());
holder.itemView.setOnClickListener(view -> {
final ProvidersAppWrapperItem selectedItem =
(ProvidersAppWrapperItem) mItems.get(holder.getAdapterPosition());
mItemSelectedListener.onItemSelected(selectedItem);
});
}

Expand All @@ -123,8 +139,8 @@ private static class ProvidersAppItemViewHolder extends ProvidersItemViewHolder
@NonNull
final TextView label;

ProvidersAppItemViewHolder(@NonNull final View itemView) {
super(itemView, ProvidersItem.FileProviderItemType.APP);
ProvidersAppItemViewHolder(@NonNull final View itemView, @NonNull ProvidersItem.FileProviderItemType providerItemType) {
super(itemView, providerItemType);
icon = itemView.findViewById(R.id.gc_app_icon);
label = itemView.findViewById(R.id.gc_app_label);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
*/
public interface ProvidersAppItemSelectedListener {

void onItemSelected(@NonNull final ProvidersAppItem item);
void onItemSelected(@NonNull final ProvidersItem item);
}
Loading

0 comments on commit df2ec81

Please sign in to comment.