Flutter

외부 앱에서 데이터 전달 받기 : receive_sharing_intent(2)_안드로이드 성공

전기Man 2022. 7. 24. 20:57

1. main.dart(시작점)

import 'dart:async';
import 'package:receive_intent/home_screen.dart';
import 'package:receive_intent/init_data.dart';
import 'package:receive_intent/show_data_argument.dart';
import 'package:receive_intent/show_data_screen.dart';
import 'package:flutter/material.dart';
import 'package:receive_sharing_intent/receive_sharing_intent.dart';

const String homeRoute = "home";
const String showDataRoute = "showData";

Future<InitData> init() async {  //1. 화면 초기화 InitData(this.sharedText, this.routeName)
  String sharedText = "";
  String routeName = homeRoute;
  //This shared intent work when application is closed
  String? sharedValue = await ReceiveSharingIntent.getInitialText(); //2. receive_sharing_intent.dart 여기에서 받는 정보
  if (sharedValue != null) {
    sharedText = sharedValue;
    routeName = showDataRoute;
  }
  return InitData(sharedText, routeName); //3. null이면 homeRoute, 아니면 showDataRoute
}

void main() async {
  WidgetsFlutterBinding.ensureInitialized(); //4. 서버나 SharedPreferences 등 비동기로 데이터를 다룬 다음 runApp을 실행해야하는 경우 아래 한줄을 반드시 추가해야합니다.
  InitData initData = await init(); //5. 호출..
  runApp(MyApp(initData: initData)); //6. 호출된 값을 전달해준다. 네임드 아규먼트로...
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key, required this.initData}) : super(key: key); //7. 네임드 아규먼트 생성자..

  final InitData initData;  //8. 네임드 아규먼트 생성자 변수 선언

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _navKey = GlobalKey<NavigatorState>(); //9. 글로벌키 생성...네비게이터 스테이트를 위해서..

  late StreamSubscription _intentDataStreamSubscription; //10. 일종의 스트림 변수 선언

  @override
  void initState() {
    super.initState();

    //This shared intent work when application is in memory
    _intentDataStreamSubscription = //11. 스티림이란, receive_sharing_intent.dart를 통해서 텍스트를 받는다는 의미 같음.
        ReceiveSharingIntent.getTextStream().listen((String value) {
          _navKey.currentState!.pushNamed(
            showDataRoute, //_navKey는 네비게이션 추적을 위한 키이고, pushNamed를 통해 값을 입력받는다고 이해하자.
            arguments: ShowDataArgument(value), //13. ShowDataArgument는 변수 하나를 받는 자료형 정도로 이해하자.
          );
        });
  }

  @override
  void dispose() {
    super.dispose();
    _intentDataStreamSubscription.cancel();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: _navKey, //15. MaterialApp에 있는 네임드아규먼트로, key가 navigation을 추적하게 된다. without context
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.red,
      ),
      onGenerateRoute: (RouteSettings settings) { //name router를 설정하기 위한 프로퍼티
        switch (settings.name) { //여기에 name 이란 것은, 아마도 위에서 pushNamed에서 밀어넣어준, showDataRoute가 되는 것이겠지...
          case homeRoute:
            return MaterialPageRoute(builder: (_) => HomeScreen());
          case showDataRoute:
            {
              if (settings.arguments != null) { //여기의 RouteSettings 와 위의 StreamSubscription 은 서로 바인딩 돼 있는듯
                final args = settings.arguments as ShowDataArgument; //변수 하나에 값을 넣어준다.
                return MaterialPageRoute(
                    builder: (BuildContext context) => ShowDataScreen(
                      sharedText: args.sharedText,)
                );// 값을 전달한다.
                // builder: (_)  와   builder: (BuildContext context)    같은 의미다.
              } else {
                return MaterialPageRoute(
                    builder: (_) => ShowDataScreen(
                      sharedText: widget.initData.sharedText,
                    ));
              }
            }
        }
      },
      initialRoute: widget.initData.routeName,
    );
  }
}

 

2. init_data.dart

//일종의 자료형이다...
class InitData {
  final String sharedText;
  final String routeName;
  InitData(this.sharedText, this.routeName);
}

3. show_data_argument.dart

class ShowDataArgument {
  String sharedText;
  ShowDataArgument(this.sharedText);
}

 

4. 인텐트 전달받을때 화면.dart

import 'package:flutter/material.dart';

class OptionValue { //키 밸류의 자료형을 생성한다.
  final int _key;
  final String _value;
  OptionValue(this._key, this._value); //키 밸류 생성자..
}

class ShowDataScreen extends StatefulWidget {
  ShowDataScreen({Key? key, this.sharedText}); //생성될때 sharedText를 넘겨 받는다.

  String? sharedText = "";

  @override
  State<ShowDataScreen> createState() => _ShowDataScreenState();
}

class _ShowDataScreenState extends State<ShowDataScreen> {
  int _currentValue = 1; //라디오버튼 초기 값..

  final _buttonOptions = [  //맵 자료형 하나 만든다.
    OptionValue(1, '아이폰최신정보'),
    OptionValue(2, '사고싶은거'),
    OptionValue(3, '코딩공부'),
    OptionValue(4, '재밌는거'),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          centerTitle: true,
          title: const Text("Show Data Screen"),
        ),
        body: Column(
          children: [
            Expanded(
              child: ListView(
                padding: EdgeInsets.all(8.0),
                children: _buttonOptions
                    .map((optionValue) => RadioListTile<int>(
                          groupValue: _currentValue,
                          title: Text(optionValue._value),
                          value: optionValue._key,
                          onChanged: (val) {
                            setState(() {
                              _currentValue = val!;
                            });
                          },
                        ))
                    .toList(),
              ),
            ),
            SizedBox(height: 20),
            Text(widget.sharedText ?? '', //sharedText가 null이면 ''을 출력
                style: const TextStyle(fontSize: 20)),
            SizedBox(height: 150),
          ],
        ));
  }
}