Flutter로 Android 앱의 딥 링크 처리
딥링크란 무엇입니까?
딥 링크는 사용자를 웹사이트가 아닌 앱으로 직접 연결하는 링크 유형입니다.
왜 이것이 필요한가요?
웹과 모바일 모두에서 원활한 사용자 경험을 제공합니다. 또 다른 이유는 비즈니스에 웹 사이트와 모바일 앱이 있는 경우 딥 링크를 사용하여 "모바일 퍼스트"웹 디자인 패턴에서 벗어날 수 있기 때문입니다.
구현
AndroidManifest.xml
아래에서 android/app/src/main
파일 찾기
내부에 이 링크를 추가하십시오<activity>
.
<intent-filter android:label="InviteLink">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="only4.dev"
android:pathPrefix="/invite"
/>
</intent-filter>
Android 운영 체제는 일부 앱에 특정 작업을 등록하는 API를 제공합니다. 예를 들어 mp3
파일을 클릭하면 Android에서 지원되는 앱 목록에서 앱을 선택하라는 메시지를 사용자에게 표시합니다.
only4.dev/invite
에서 시작하는 링크를 클릭하면 항상 모바일 앱에서 이 링크를 열라는 메시지가 표시됩니다.
앱에서 링크를 처리할 수 있습니다.
2가지 유형의 이벤트가 있을 수 있습니다.
웹과 모바일 모두에서 원활한 사용자 경험을 제공합니다. 또 다른 이유는 비즈니스에 웹 사이트와 모바일 앱이 있는 경우 딥 링크를 사용하여 "모바일 퍼스트"웹 디자인 패턴에서 벗어날 수 있기 때문입니다.
구현
AndroidManifest.xml
아래에서 android/app/src/main
파일 찾기
내부에 이 링크를 추가하십시오<activity>
.
<intent-filter android:label="InviteLink">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="only4.dev"
android:pathPrefix="/invite"
/>
</intent-filter>
Android 운영 체제는 일부 앱에 특정 작업을 등록하는 API를 제공합니다. 예를 들어 mp3
파일을 클릭하면 Android에서 지원되는 앱 목록에서 앱을 선택하라는 메시지를 사용자에게 표시합니다.
only4.dev/invite
에서 시작하는 링크를 클릭하면 항상 모바일 앱에서 이 링크를 열라는 메시지가 표시됩니다.
앱에서 링크를 처리할 수 있습니다.
2가지 유형의 이벤트가 있을 수 있습니다.
<intent-filter android:label="InviteLink">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="only4.dev"
android:pathPrefix="/invite"
/>
</intent-filter>
이를 위해 2가지 유형의 메시지를 생성하고 브로드캐스트 수신기도 생성합니다.
브로드캐스트 수신기(수신기)는 시스템 또는 애플리케이션 이벤트에 등록할 수 있는 Android 구성요소입니다. 이벤트에 등록된 모든 수신자는 이 이벤트가 발생하면 Android 런타임에서 알림을 받습니다.
private static final String CHANNEL = "initial";
private static final String EVENTS = "eventWhileAppIsRunning";
private String startString;
private BroadcastReceiver linksReceiver;
사건을 처리합시다. 첫 번째 경우에 대해 새 항목
MethodChanenel
을 만들고 두 번째 경우에 대해 새 항목EventChannel
을 만듭니다.Android 측
MethodChannel
에서 Android(API) 및 iOS 측FlutterMessageChannel
(API)은 메서드 호출을 수신하고 결과를 다시 보내는 데 사용됩니다. 필요한 경우 Android/IOS 플랫폼이 클라이언트 역할을 하고 Dart에서 구현된 메서드를 사용하여 메서드 호출을 반대 방향으로 보낼 수도 있습니다.EventChannel
는 데이터를 스트리밍할 때 사용됩니다. 그 결과 Dart 측에 스트림이 있고 기본 측에서 해당 스트림을 공급할 수 있습니다. (즉, 앱이 이미 실행 중일 때).protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
Intent intent = getIntent();
Uri data = intent.getData();
new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
if (call.method.equals("initialLink")) {
if (startString != null) {
result.success(startString);
}
}
}
}
);
new EventChannel(getFlutterView(), EVENTS).setStreamHandler(
new EventChannel.StreamHandler() {
@Override
public void onListen(Object args, final EventChannel.EventSink events) {
linksReceiver = createChangeReceiver(events);
}
@Override
public void onCancel(Object args) {
linksReceiver = null;
}
}
);
if (data != null) {
startString = data.toString();
if(linksReceiver != null) {
linksReceiver.onReceive(this.getApplicationContext(), intent);
}
}
}
시간을 내어 이것을 읽고 이해하십시오.
딥 링크를 구현해야 하는 경우 시간을 내어 이것을 이해하십시오.
여기에 최종 MainActivity.java가 있습니다.
package my.app.com;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import io.flutter.app.FlutterActivity;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "initial";
private static final String EVENTS = "eventWhileAppIsRunning";
private String startString;
private BroadcastReceiver linksReceiver;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
Intent intent = getIntent();
Uri data = intent.getData();
new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(
new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
if (call.method.equals("initialLink")) {
if (startString != null) {
result.success(startString);
}
}
}
}
);
new EventChannel(getFlutterView(), EVENTS).setStreamHandler(
new EventChannel.StreamHandler() {
@Override
public void onListen(Object args, final EventChannel.EventSink events) {
linksReceiver = createChangeReceiver(events);
}
@Override
public void onCancel(Object args) {
linksReceiver = null;
}
}
);
if (data != null) {
startString = data.toString();
if(linksReceiver != null) {
linksReceiver.onReceive(this.getApplicationContext(), intent);
}
}
}
@Override
public void onNewIntent(Intent intent){
super.onNewIntent(intent);
if(intent.getAction() == android.content.Intent.ACTION_VIEW && linksReceiver != null) {
linksReceiver.onReceive(this.getApplicationContext(), intent);
}
}
private BroadcastReceiver createChangeReceiver(final EventChannel.EventSink events) {
return new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// NOTE: assuming intent.getAction() is Intent.ACTION_VIEW
String dataString = intent.getDataString();
if (dataString == null) {
events.error("UNAVAILABLE", "Link unavailable", null);
} else {
events.success(dataString);
}
}
};
}
}
다음 단계는 이러한 이벤트를 플러터 코드에 전달하는 것입니다.
StreamController()
클래스에 DeepLinkBloc
를 생성합니다.이 클래스의 생성자 생성
DeepLinkBloc() {
startUri().then(_onRedirected);
stream.receiveBroadcastStream().listen((d) => _onRedirected(d));
}
이벤트를 수신할 때마다
_onRedirected
메서드를 호출합니다. 이제 드디어 플러터 코드에 초기 링크가 생겼습니다.다음은 클래스의 전체 코드입니다.
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
abstract class Bloc {
void dispose();
}
class DeepLinkBloc extends Bloc {
DeepLinkBloc() {
startUri().then(_onRedirected);
stream.receiveBroadcastStream().listen((d) => _onRedirected(d));
}
// Initial event channel
static const platform = MethodChannel('initial');
// Runtime Event channel
static const stream = EventChannel('eventWhileAppIsRunning');
final StreamController<String> _stateController = StreamController();
Stream<String> get state => _stateController.stream;
Sink<String> get stateSink => _stateController.sink;
//Adding the listener into constructor
void _onRedirected(String uri) {
debugPrint(uri);
stateSink.add(uri);
}
@override
void dispose() {
_stateController.close();
}
Future<String> startUri() async {
try {
return platform.invokeMethod('initialLink');
} on PlatformException catch (e) {
return "Failed to Invoke: '${e.message}'.";
}
}
}
이제 링크를 사용하려는 위치
Provider<DeepLinkBloc>.value(value: _bloc)
에 위젯을 래핑하기만 하면 됩니다.이 공급자를 사용하는 새 위젯을 만들 수 있습니다.
class DeepLinkWrapper extends StatelessWidget {
@override
Widget build(BuildContext context) {
final _bloc = Provider.of<DeepLinkBloc>(context);
return StreamBuilder<String>(
stream: _bloc.state,
builder: (context, snapshot) {
// if app is started normally, no deep link is clicked show your old home page widget
if (!snapshot.hasData) {
return Container(
child: const HomePage(),
);
} else {
final splitInviteLink = snapshot.data.split('/');
final inviteToken = splitInviteLink[splitInviteLink.length - 1];
return RegisterStartPage(key: UniqueKey(),inviteToken: inviteToken,);
}
});
}
}
이 마지막 변경만 하면 됩니다.
main.dart
파일에서 이 수정 작업을 수행합니다. home: Scaffold(
body: Provider<DeepLinkBloc>(
builder: (context) => _bloc,
dispose: (context, bloc) => bloc.dispose(),
child: DeepLinkWrapper()
)
)
다음은 main.dart의 최종 MyApp 클래스에 대한 코드입니다.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final _bloc = DeepLinkBloc();
return MultiProvider(
providers: [
Provider<DeepLinkBloc>.value(value: _bloc),
// ...other providers
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
localizationsDelegates: const [
AppLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: const [
Locale('de'),
Locale('en'),
],
routes: {
HomePage.route: (context) => const HomePage(),
LoginPage.route: (context) => LoginPage(),
},
home: Scaffold(
body: Provider<DeepLinkBloc>(
create: (context) => _bloc,
dispose: (context, bloc) => bloc.dispose(),
child: DeepLinkWrapper()
)
)
),
);
}
}
Reference
이 문제에 관하여(Flutter로 Android 앱의 딥 링크 처리), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/mohitkyadav/handle-deep-links-in-the-android-apps-32mi텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)