fixed starting new intents when activity already exists

This commit is contained in:
Thibault Deckers 2020-09-23 15:05:54 +09:00
parent f78b466229
commit 0547c3bbf1
8 changed files with 74 additions and 24 deletions

View file

@ -6,6 +6,7 @@ import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.core.content.pm.ShortcutInfoCompat;
import androidx.core.content.pm.ShortcutManagerCompat;
@ -25,19 +26,23 @@ import deckers.thibault.aves.channel.calls.MetadataHandler;
import deckers.thibault.aves.channel.calls.StorageHandler;
import deckers.thibault.aves.channel.streams.ImageByteStreamHandler;
import deckers.thibault.aves.channel.streams.ImageOpStreamHandler;
import deckers.thibault.aves.channel.streams.IntentStreamHandler;
import deckers.thibault.aves.channel.streams.MediaStoreStreamHandler;
import deckers.thibault.aves.channel.streams.StorageAccessStreamHandler;
import deckers.thibault.aves.utils.PermissionManager;
import deckers.thibault.aves.utils.Utils;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodChannel;
public class MainActivity extends FlutterActivity {
private static final String LOG_TAG = Utils.createLogTag(MainActivity.class);
public static final String INTENT_CHANNEL = "deckers.thibault/aves/intent";
public static final String VIEWER_CHANNEL = "deckers.thibault/aves/viewer";
private IntentStreamHandler intentStreamHandler;
private Map<String, Object> intentDataMap;
@Override
@ -79,6 +84,8 @@ public class MainActivity extends FlutterActivity {
finish();
}
});
intentStreamHandler = new IntentStreamHandler();
new EventChannel(messenger, INTENT_CHANNEL).setStreamHandler(intentStreamHandler);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
setupShortcuts();
@ -107,6 +114,13 @@ public class MainActivity extends FlutterActivity {
ShortcutManagerCompat.setDynamicShortcuts(this, Arrays.asList(videos, search));
}
@Override
protected void onNewIntent(@NonNull Intent intent) {
super.onNewIntent(intent);
handleIntent(intent);
intentStreamHandler.notifyNewIntent();
}
private void handleIntent(Intent intent) {
Log.i(LOG_TAG, "handleIntent intent=" + intent);
if (intent == null) return;

View file

@ -44,7 +44,7 @@ public class ImageByteStreamHandler implements EventChannel.StreamHandler {
}
@Override
public void onListen(Object o, final EventChannel.EventSink eventSink) {
public void onListen(Object args, EventChannel.EventSink eventSink) {
this.eventSink = eventSink;
this.handler = new Handler(Looper.getMainLooper());
new Thread(this::getImage).start();

View file

@ -47,7 +47,7 @@ public class ImageOpStreamHandler implements EventChannel.StreamHandler {
}
@Override
public void onListen(Object o, final EventChannel.EventSink eventSink) {
public void onListen(Object args, EventChannel.EventSink eventSink) {
this.eventSink = eventSink;
this.handler = new Handler(Looper.getMainLooper());
if ("delete".equals(op)) {

View file

@ -0,0 +1,20 @@
package deckers.thibault.aves.channel.streams;
import io.flutter.plugin.common.EventChannel;
public class IntentStreamHandler implements EventChannel.StreamHandler {
private EventChannel.EventSink eventSink;
@Override
public void onListen(Object args, EventChannel.EventSink eventSink) {
this.eventSink = eventSink;
}
@Override
public void onCancel(Object arguments) {
}
public void notifyNewIntent() {
eventSink.success(true);
}
}

View file

@ -27,7 +27,7 @@ public class MediaStoreStreamHandler implements EventChannel.StreamHandler {
}
@Override
public void onListen(Object args, final EventChannel.EventSink eventSink) {
public void onListen(Object args, EventChannel.EventSink eventSink) {
this.eventSink = eventSink;
this.handler = new Handler(Looper.getMainLooper());
new Thread(this::fetchAll).start();

View file

@ -29,7 +29,7 @@ public class StorageAccessStreamHandler implements EventChannel.StreamHandler {
}
@Override
public void onListen(Object o, final EventChannel.EventSink eventSink) {
public void onListen(Object args, EventChannel.EventSink eventSink) {
this.eventSink = eventSink;
this.handler = new Handler(Looper.getMainLooper());
Runnable onGranted = () -> success(true); // user gave access to a directory, with no guarantee that it matches the specified `path`

View file

@ -5,6 +5,7 @@ import 'package:aves/model/settings/settings.dart';
import 'package:aves/utils/route_tracker.dart';
import 'package:aves/widgets/common/data_providers/settings_provider.dart';
import 'package:aves/widgets/common/icons.dart';
import 'package:aves/widgets/common/routes.dart';
import 'package:aves/widgets/home_page.dart';
import 'package:aves/widgets/welcome_page.dart';
import 'package:firebase_core/firebase_core.dart';
@ -32,7 +33,7 @@ void main() {
enum AppMode { main, pick, view }
class AvesApp extends StatefulWidget {
static AppMode mode = AppMode.main;
static AppMode mode;
@override
_AvesAppState createState() => _AvesAppState();
@ -41,6 +42,8 @@ class AvesApp extends StatefulWidget {
class _AvesAppState extends State<AvesApp> {
Future<void> _appSetup;
final NavigatorObserver _routeTracker = CrashlyticsRouteTracker();
final _newIntentChannel = EventChannel('deckers.thibault/aves/intent');
final _navigatorKey = GlobalKey<NavigatorState>();
static const accentColor = Colors.indigoAccent;
@ -64,10 +67,13 @@ class _AvesAppState extends State<AvesApp> {
),
);
Widget get firstPage => settings.hasAcceptedTerms ? HomePage() : WelcomePage();
@override
void initState() {
super.initState();
_appSetup = _setup();
_newIntentChannel.receiveBroadcastStream().listen((_) => _onNewIntent());
}
Future<void> _setup() async {
@ -87,6 +93,14 @@ class _AvesAppState extends State<AvesApp> {
await settings.init();
}
void _onNewIntent() {
FirebaseCrashlytics.instance.log('New intent');
_navigatorKey.currentState.pushReplacement(DirectMaterialPageRoute(
settings: RouteSettings(name: HomePage.routeName),
builder: (_) => firstPage,
));
}
@override
Widget build(BuildContext context) {
// place the settings provider above `MaterialApp`
@ -95,23 +109,10 @@ class _AvesAppState extends State<AvesApp> {
future: _appSetup,
builder: (context, snapshot) {
if (!snapshot.hasError && snapshot.connectionState == ConnectionState.done) {
return settings.hasAcceptedTerms ? HomePage() : WelcomePage();
return firstPage;
}
return Scaffold(
body: snapshot.hasError
? Container(
alignment: Alignment.center,
padding: EdgeInsets.all(16),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(AIcons.error),
SizedBox(height: 16),
Text(snapshot.error.toString()),
],
),
)
: SizedBox.shrink(),
body: snapshot.hasError ? _buildError(snapshot.error) : SizedBox.shrink(),
);
},
);
@ -121,6 +122,7 @@ class _AvesAppState extends State<AvesApp> {
future: _appSetup,
builder: (context, snapshot) {
return MaterialApp(
navigatorKey: _navigatorKey,
home: home,
navigatorObservers: [
if (!snapshot.hasError && snapshot.connectionState == ConnectionState.done) _routeTracker,
@ -134,4 +136,19 @@ class _AvesAppState extends State<AvesApp> {
),
);
}
Widget _buildError(Object error) {
return Container(
alignment: Alignment.center,
padding: EdgeInsets.all(16),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(AIcons.error),
SizedBox(height: 16),
Text(error.toString()),
],
),
);
}
}

View file

@ -63,19 +63,18 @@ class _HomePageState extends State<HomePage> {
await androidFileUtils.init();
unawaited(androidFileUtils.initAppNames());
AvesApp.mode = AppMode.main;
final intentData = await ViewerService.getIntentData();
if (intentData != null) {
final action = intentData['action'];
switch (action) {
case 'view':
AvesApp.mode = AppMode.view;
_viewerEntry = await _initViewerEntry(
uri: intentData['uri'],
mimeType: intentData['mimeType'],
);
if (_viewerEntry == null) {
// fallback to default mode when we fail to retrieve the entry
AvesApp.mode = AppMode.main;
if (_viewerEntry != null) {
AvesApp.mode = AppMode.view;
}
break;
case 'pick':