From 02e8daef744805c60a116cd250c83dadcccc0cb6 Mon Sep 17 00:00:00 2001 From: Julius Kato Mutumba Date: Fri, 24 Nov 2023 16:38:17 +0200 Subject: [PATCH] android --- .../pspdfkit/FlutterInstantPdfActivity.kt | 39 ++++++++++- .../flutter/pspdfkit/PspdfkitPlugin.java | 7 ++ example/android/app/build.gradle | 1 + ...spdfkit_instant_collaboration_example.dart | 64 +++++++++++++++++++ lib/pspdfkit.dart | 8 ++- 5 files changed, 115 insertions(+), 4 deletions(-) diff --git a/android/src/main/java/com/pspdfkit/flutter/pspdfkit/FlutterInstantPdfActivity.kt b/android/src/main/java/com/pspdfkit/flutter/pspdfkit/FlutterInstantPdfActivity.kt index 419d7fa8..d228fe45 100644 --- a/android/src/main/java/com/pspdfkit/flutter/pspdfkit/FlutterInstantPdfActivity.kt +++ b/android/src/main/java/com/pspdfkit/flutter/pspdfkit/FlutterInstantPdfActivity.kt @@ -9,6 +9,11 @@ package com.pspdfkit.flutter.pspdfkit /// import android.os.Bundle +import android.view.View +import android.widget.AdapterView +import android.widget.ArrayAdapter +import android.widget.FrameLayout +import android.widget.Spinner import com.pspdfkit.document.PdfDocument import com.pspdfkit.instant.document.InstantPdfDocument import com.pspdfkit.instant.exceptions.InstantException @@ -16,16 +21,46 @@ import com.pspdfkit.instant.ui.InstantPdfActivity import io.flutter.plugin.common.MethodChannel import java.util.concurrent.atomic.AtomicReference + /** * For communication with the PSPDFKit plugin, we keep a static reference to the current * activity. */ class FlutterInstantPdfActivity : InstantPdfActivity() { + + override fun onCreate(bundle: Bundle?) { super.onCreate(bundle) bindActivity() + var tokens = intent.getStringArrayExtra("tokens")?.toList() + var layers = intent.getStringArrayExtra("layers")?.toList() + var serverUrl = intent.getStringExtra("serverUrl") + + //Add a dropdown for switching between layers + val layerSelector = Spinner(this) + val params = FrameLayout.LayoutParams( + FrameLayout.LayoutParams.WRAP_CONTENT, + FrameLayout.LayoutParams.WRAP_CONTENT + ) + params.setMargins(0, 0, 0, 0) + layerSelector.layoutParams = params + val spinnerArrayAdapter: ArrayAdapter = + ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, layers!!) + layerSelector.adapter = spinnerArrayAdapter + layerSelector.setSelection(0) + layerSelector.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) { + setDocument(serverUrl!!, tokens!![p2]) + } + + override fun onNothingSelected(p0: AdapterView<*>?) { + } + } + val layout = findViewById(R.id.pspdf__activity_content) + layout.addView(layerSelector) } + override fun onPause() { // Notify the Flutter PSPDFKit plugin that the activity is going to enter the onPause state. EventDispatcher.getInstance().notifyActivityOnPause() @@ -36,7 +71,7 @@ class FlutterInstantPdfActivity : InstantPdfActivity() { super.onDestroy() releaseActivity() } - + override fun onDocumentLoaded(pdfDocument: PdfDocument) { super.onDocumentLoaded(pdfDocument) val result = loadedDocumentResult.getAndSet(null) @@ -48,7 +83,7 @@ class FlutterInstantPdfActivity : InstantPdfActivity() { val result = loadedDocumentResult.getAndSet(null) result?.success(false) } - + override fun onSyncStarted(instantDocument: InstantPdfDocument) { super.onSyncStarted(instantDocument) EventDispatcher.getInstance() diff --git a/android/src/main/java/com/pspdfkit/flutter/pspdfkit/PspdfkitPlugin.java b/android/src/main/java/com/pspdfkit/flutter/pspdfkit/PspdfkitPlugin.java index 381b34a1..79572991 100644 --- a/android/src/main/java/com/pspdfkit/flutter/pspdfkit/PspdfkitPlugin.java +++ b/android/src/main/java/com/pspdfkit/flutter/pspdfkit/PspdfkitPlugin.java @@ -241,6 +241,9 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { String documentUrl = call.argument("serverUrl"); String jwt = call.argument("jwt"); + List tokens= call.argument("tokens"); + List layers= call.argument("layers"); + requireNotNullNotEmpty(documentUrl, "Document path"); requireNotNullNotEmpty(jwt, "JWT"); @@ -265,6 +268,10 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { .configuration(configurationAdapterInstant.build()) .build(); + intentInstant.putExtra("tokens", tokens.toArray(new String[tokens.size()])); + intentInstant.putExtra("layers", layers.toArray(new String[layers.size()])); + intentInstant.putExtra("serverUrl", documentUrl); + activity.startActivity(intentInstant); break; diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 7d8d337d..e6596e1b 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -51,6 +51,7 @@ dependencies { androidTestImplementation 'androidx.test:runner:1.5.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1' + implementation 'com.squareup.okhttp3:okhttp:4.2.1' constraints { implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0") { diff --git a/example/lib/pspdfkit_instant_collaboration_example.dart b/example/lib/pspdfkit_instant_collaboration_example.dart index b281ee14..2b6d8b4e 100644 --- a/example/lib/pspdfkit_instant_collaboration_example.dart +++ b/example/lib/pspdfkit_instant_collaboration_example.dart @@ -156,6 +156,16 @@ class _PspdfkitInstantCollaborationExampleState child: const Text('Enter Document URL'), ), ), + + const Padding( + padding: EdgeInsets.all(16.0), + ), + ElevatedButton( + onPressed: () { + _loadDocumentJson( + context, 'http://192.168.0.111:3000/api/documents'); + }, + child: const Text('Load Instant Layers')), // Delay for syncing local changes const Padding( padding: EdgeInsets.all(4.0), @@ -250,6 +260,45 @@ class _PspdfkitInstantCollaborationExampleState } } + void _loadDocumentJson(BuildContext context, String? url) { + if (url != null) { + showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return const Center( + child: CircularProgressIndicator(), + ); + }); + + _getDocumentJson(url).then((data) async { + var doc = data['documents'][0] as Map; + var tokes = doc['tokens'] as List; + var layers = doc['layers'] as List; + await Pspdfkit.presentInstant( + 'http://192.168.0.111:8080', + tokes[0], + { + enableInstantComments: enableComments, + }, + tokes.map((e) => e as String).toList(), + layers.map((e) => e as String).toList(), + ); + await Pspdfkit.setDelayForSyncingLocalChanges(delayTime); + await Pspdfkit.setListenToServerChanges(enableListenToServerChanges); + }).catchError((dynamic onError) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(onError.toString()), + )); + Navigator.of(context).pop(); + }); + } else { + if (kDebugMode) { + print('No URL'); + } + } + } + /// Fetches the document from the instant demo server. /// The server returns a JWT token that is used to authenticate the user. Future _getDocument(String url) async { @@ -260,6 +309,21 @@ class _PspdfkitInstantCollaborationExampleState final document = InstantDocumentDescriptor.fromJson(data); return document; } + + Future> _getDocumentJson(String url) async { + // The header is necessary to receive valid json response. + try { + http.Response response = await client.get(Uri.parse(url), headers: { + 'Authorization': 'Basic ${base64.encode(utf8.encode('cato:secret'))}' + }); + + final data = json.decode(response.body) as Map; + return data; + } catch (e) { + print(e); + rethrow; + } + } } class InstantBarcodeScanner extends StatefulWidget { diff --git a/lib/pspdfkit.dart b/lib/pspdfkit.dart index e434e2c7..7e57d111 100644 --- a/lib/pspdfkit.dart +++ b/lib/pspdfkit.dart @@ -92,11 +92,15 @@ class Pspdfkit { /// Returns false if the document could not be opened. /// static Future presentInstant(String serverUrl, String jwt, - [dynamic configuration]) async => + [dynamic configuration, + List? tokens, + List? layers]) async => await _channel.invokeMethod('presentInstant', { 'serverUrl': serverUrl, 'jwt': jwt, - 'configuration': configuration + 'configuration': configuration, + 'tokens': tokens, + 'layers': layers, }); /// Sets the value of a form field by specifying its fully qualified field name.