Flutter로 Android 런처 만들기

반응형

Flutter Project 생성하기

먼저 플러터 프로젝트를 생성합니다.

아래 명령어를 실행하면 코틀린 안드로이드(iOS는 스위프트)로 작성된 플러터 앱이 생성됩니다.

$ flutter create flutter_launcher

 

만약 오브젝트 C와 안드로이드 자바를 선호한다면 다음 명령어를 사용할 수 있습니다.

$ flutter create -i objc -a java flutter_launcher

 

아래와 비슷한 파일 구조를 가진 플러터 앱이 생성됩니다.

 

그 다음 AndroidManifest.xml 파일을 편집합니다.

매니페스트 파일 위치는 다음과 같습니다.

android/app/src/main/AndroidManifest.xml

<intent-filter> 에 아래 두 개의 카테고리 항목을 추가합니다.

<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.DEFAULT"/>

<intent-filter>는 아래와 같이 되어야 합니다.

여기까지 작성하고 플러터앱을 빌드한 다음, 실행하면 런처로 나타나게 됩니다.

 

_

설치되어 있는 어플리케이션 표시하기

안드로이드 앱에 설치되어 있는 어플리케이션을 가져오기 위해서는 device_apps 패키지가 필요합니다.

device_apps 패키지를 설치합니다.

$ flutter pub add device_apps

 

사용할수 있는 앱 목록을 가져오려면 다음과 같이 작성합니다.

import 'package:device_apps/device_apps.dart';

List<Application> apps = await DeviceApps.getInstalledApplications
(
    includeAppIcons: true,
    includeSystemApps: true,
    onlyAppsWithLaunchIntent: true,
)

_

 

이제 실행가능한 앱 목록을 Grid 위젯을 사용해서 화면에 출력해보겠습니다.

아래는 화면에 출력하는 전체 코드입니다.

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return MyHomePageState();
  }
}

class MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        color: Colors.black,
        child: FutureBuilder<List<Application>>(
          future: DeviceApps.getInstalledApplications(
            includeSystemApps: true,
            onlyAppsWithLaunchIntent: true,
            includeAppIcons: true,
          ),
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.done) {
              List<Application> allApps = snapshot.data!;

              return GridView.count(
                crossAxisCount: 3,
                children: List.generate(
                  allApps.length,
                  (index) {
                    final appInfo = allApps[index];

                    return Column(
                      children: [
                        if (appInfo is ApplicationWithIcon)
                          Image.memory(appInfo.icon, width: 64),
                        Text(
                          appInfo.appName,
                          style: const TextStyle(color: Colors.white),
                          textAlign: TextAlign.center,
                        )
                      ],
                    );
                  },
                ),
              );
            }

            return const Center(
              child: CircularProgressIndicator(),
            );
          },
        ),
      ),
    );
  }
}

_

 

그 다음 터치한 앱을 실행하기 위해서 GestureDetector 위젯을 사용합니다.

GestureDetector(
    onTap: () {
        DeviceApps.openApp(appInfo.packageName);
    },
    child: Column(),
)

_

 

다음은 완성된 전체 코드입니다.

class MyHomePageState extends State<MyHomePage> {
  final BouncingScrollPhysics _bouncingScrollPhysics =
      const BouncingScrollPhysics();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        color: Colors.black,
        child: FutureBuilder<List<Application>>(
          future: DeviceApps.getInstalledApplications(
            includeSystemApps: true,
            onlyAppsWithLaunchIntent: true,
            includeAppIcons: true,
          ),
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.done) {
              List<Application> allApps = snapshot.data!;

              return GridView.count(
                crossAxisCount: 3,
                padding: const EdgeInsets.only(top: 60.0),
                physics: _bouncingScrollPhysics,
                children: List.generate(
                  allApps.length,
                  (index) {
                    final appInfo = allApps[index];

                    return GestureDetector(
                      onTap: () {
                        DeviceApps.openApp(appInfo.packageName);
                      },
                      child: Column(
                        children: [
                          if (appInfo is ApplicationWithIcon)
                            Image.memory(appInfo.icon, width: 64),
                          Text(
                            appInfo.appName,
                            style: const TextStyle(color: Colors.white),
                            textAlign: TextAlign.center,
                          )
                        ],
                      ),
                    );
                  },
                ),
              );
            }

            return const Center(
              child: CircularProgressIndicator(),
            );
          },
        ),
      ),
    );
  }
}
 
반응형