일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- python
- 함수
- function
- ML
- 파이썬
- import
- set
- 다트
- Flutter
- Android
- List
- map
- Class
- pushnamed
- textstyle
- text
- 크롤러
- 코틀린
- 콜렉션
- package
- 클래스
- animation
- crawler
- DART
- Yocto
- Collection
- 플러터
- 웹크롤러
- kotlin
- variable
- Today
- Total
조용한 담장
Flutter: device_apps package 본문
설치된 앱의 목록을 가져올 때 쓸 수 있는 package 이다.
앱의 정보를 얻을 수도 있고 앱의 실행도 가능하다.
Android 만 지원한다.
https://pub.dev/packages/device_apps
https://github.com/g123k/flutter_plugin_device_apps
예제 실행해 보기
예제 코드를 실행해 보자.
https://github.com/g123k/flutter_plugin_device_apps/tree/master/example
예제 실행 화면:
Platform-specific code 를 사용해서 설치된 정보를 얻어 화면에 뿌리는 동작을 하는데
어떻게 동작하는지 살펴보자...
코드로 동작 살펴보기
android/src/main/java/fr/g123k/deviceapps/DeviceAppsPlugin.java
public class DeviceAppsPlugin implements MethodCallHandler, PluginRegistry.ViewDestroyListener {
// ...
@Override
public void onMethodCall(MethodCall call, final Result result) {
switch (call.method) {
case "getInstalledApps":
// ...
fetchInstalledApps(systemApps, includeAppIcons, onlyAppsWithLaunchIntent, new InstalledAppsCallback() {
@Override
public void onInstalledAppsListAvailable(final List<Map<String, Object>> apps) {
if (!activity.isFinishing()) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
result.success(apps);
}
});
}
}
});
break;
}
}
private void fetchInstalledApps(final boolean includeSystemApps, final boolean includeAppIcons, final boolean onlyAppsWithLaunchIntent, final InstalledAppsCallback callback) {
asyncWork.run(new Runnable() {
@Override
public void run() {
List<Map<String, Object>> installedApps = getInstalledApps(includeSystemApps, includeAppIcons, onlyAppsWithLaunchIntent);
// ...
}
});
}
private List<Map<String, Object>> getInstalledApps(boolean includeSystemApps, boolean includeAppIcons, boolean onlyAppsWithLaunchIntent) {
PackageManager packageManager = activity.getPackageManager();
List<PackageInfo> apps = packageManager.getInstalledPackages(0);
List<Map<String, Object>> installedApps = new ArrayList<>(apps.size());
for (PackageInfo pInfo : apps) {
// ...
Map<String, Object> map = getAppData(packageManager, pInfo, includeAppIcons);
installedApps.add(map);
}
return installedApps;
}
private Map<String, Object> getAppData(PackageManager packageManager, PackageInfo pInfo, boolean includeAppIcon) {
Map<String, Object> map = new HashMap<>();
map.put("app_name", pInfo.applicationInfo.loadLabel(packageManager).toString());
map.put("apk_file_path", pInfo.applicationInfo.sourceDir);
map.put("package_name", pInfo.packageName);
map.put("version_code", pInfo.versionCode);
map.put("version_name", pInfo.versionName);
map.put("data_dir", pInfo.applicationInfo.dataDir);
map.put("system_app", isSystemApp(pInfo));
map.put("install_time", pInfo.firstInstallTime);
map.put("update_time", pInfo.lastUpdateTime);
// ...
return map;
}
}
getInstalledApps method call 이 호출되면 fetchInstalledApps() 이 호출되고 getInstalledApps() 를 호출하는데
여기서 packageManager.getInstalledPackages() 를 호출하여 설치된 패키지의 정보를 가진 PackageInfo 들을 얻는다.
PackageInfo 의 정보를 getAppData() 에서 Map 으로 필요한 데이터를 정리해서 List<Map<String, Object>> 의 형태로 최종 목록을 result.success(apps); 로 Flutter app 으로 전달한다.
class _ListAppsPagesContent extends StatelessWidget {
// ...
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: DeviceApps.getInstalledApplications(
includeAppIcons: true,
includeSystemApps: includeSystemApps,
onlyAppsWithLaunchIntent: onlyAppsWithLaunchIntent),
builder: (context, data) {
if (data.data == null) {
return Center(child: CircularProgressIndicator());
} else {
List<Application> apps = data.data;
print(apps);
return ListView.builder(
itemBuilder: (context, position) {
Application app = apps[position];
return Column(
children: <Widget>[
ListTile(
leading: app is ApplicationWithIcon
? CircleAvatar(
backgroundImage: MemoryImage(app.icon),
backgroundColor: Colors.white,
)
: null,
onTap: () => DeviceApps.openApp(app.packageName),
title: Text("${app.appName} (${app.packageName})"),
subtitle: Text('Version: ${app.versionName}\nSystem app: ${app.systemApp}\nAPK file path: ${app.apkFilePath}\nData dir : ${app.dataDir}\nInstalled: ${DateTime.fromMillisecondsSinceEpoch(app.installTimeMilis).toString()}\nUpdated: ${DateTime.fromMillisecondsSinceEpoch(app.updateTimeMilis).toString()}'),
),
Divider(
height: 1.0,
)
],
);
},
itemCount: apps.length);
}
});
}
}
lib/device_apps.dart 의 getInstalledApplications() 를 호출해 invokeMethod('getInstalledApps') 의 결과를 얻어 ListView.builder() 로 화면에 설치된 앱 들을 리스트로 표시한다.
class DeviceApps {
static const MethodChannel _channel =
const MethodChannel('g123k/device_apps');
static Future<List<Application>> getInstalledApplications(
{bool includeSystemApps: false,
bool includeAppIcons: false,
bool onlyAppsWithLaunchIntent: false}) async {
return _channel.invokeMethod('getInstalledApps', {
'system_apps': includeSystemApps,
'include_app_icons': includeAppIcons,
'only_apps_with_launch_intent': onlyAppsWithLaunchIntent
}).then((apps) {
if (apps != null && apps is List) {
List<Application> list = new List();
// ...
}
return list;
} else {
return List<Application>(0);
}
// ...
});
}
똑같이 만들어 보기
앱 목록을 가져오는 기능만 따라 만들어 보자...
android/app/src/main/kotlin/com.example.simplelauncher/MainActivity.kt
class MainActivity: FlutterActivity() {
private val _channel = "my.device_app.copy"
private val _systemAppMask = ApplicationInfo.FLAG_SYSTEM or ApplicationInfo.FLAG_UPDATED_SYSTEM_APP
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, _channel).setMethodCallHandler {
call, result ->
if (call.method == "getInstalledApps") {
val apps = packageManager.getInstalledPackages(0)
val installedApps = mutableListOf<Map<String, Any>>()
for (pInfo in apps) {
if (pInfo.applicationInfo.flags and _systemAppMask != 0) {
continue
}
val newMap = mapOf<String, Any>(
"app_name" to pInfo.applicationInfo.loadLabel(packageManager).toString(),
"apk_file_path" to pInfo.applicationInfo.sourceDir,
"package_name" to pInfo.packageName,
"version_name" to pInfo.versionName,
"data_dir" to pInfo.applicationInfo.dataDir,
"install_time" to pInfo.firstInstallTime,
"update_time" to pInfo.lastUpdateTime
)
//println("app_name: ${newMap["app_name"]}")
installedApps.add(newMap)
}
result.success(installedApps)
} else {
result.notImplemented()
}
}
}
}
getInstalledApps method 를 만들었고 packageManager.getInstalledPackages() 를 통해 List<PackageInfo> 를 얻어 mutableListOf<Map<String, Any>> 로 저장해 리턴한다.
lib/my_device_app_copy.dart
class _MyDeviceApps extends StatelessWidget {
List apps;
static const _platform = const MethodChannel('my.device_app.copy');
Future<void> _getInstalledApps() async {
try {
final result = await _platform.invokeMethod('getInstalledApps');
//print(result);
return result;
} on PlatformException catch (e) {
print('error ${e.message}');
return null;
}
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: _getInstalledApps(),
builder: (context, data) {
if (data == null) {
return Center(child: CircularProgressIndicator());
} else {
apps = data.data;
return ListView.builder(
itemBuilder: (context, position) {
return Column(
children: <Widget>[
ListTile(
title: Text(
"${apps[position]['app_name']}, ${apps[position]['package_name']}"),
subtitle: Text(
"Version: ${apps[position]['version_name']}\nAPK file path:${apps[position]['apk_file_path']}\nData dir:${apps[position]['data_dir']}\nInstall time:${DateTime.fromMillisecondsSinceEpoch(apps[position]['install_time']).toString()}\nUpdate time:${DateTime.fromMillisecondsSinceEpoch(apps[position]['update_time']).toString()}"),
)
],
);
},
itemCount: apps.length,
);
}
},
);
}
_getInstalledApps() 를 통해 invokeMethod('getInstalledApps') 를 호출하여 결과를 얻고 ListView.builder() 로 결과를 화면에 생성한다.
코드는 허접하지만 동작을 확인한 것에 의의를...
번외로
안드로이드 스튜디오의 Java 코드를 Kotlin 코드로 변경해주는 기능을 써보면
어떻게 바꿔주는지 해봤는데...
// ...
fun onMethodCall(call: MethodCall, result: Result) {
when (call.method) {
"getInstalledApps" -> {
val systemApps = call.hasArgument("system_apps") && (call.argument<Any>("system_apps") as Boolean?)!!
val includeAppIcons = call.hasArgument("include_app_icons") && (call.argument<Any>("include_app_icons") as Boolean?)!!
val onlyAppsWithLaunchIntent = call.hasArgument("only_apps_with_launch_intent") && (call.argument<Any>("only_apps_with_launch_intent") as Boolean?)!!
fetchInstalledApps(systemApps, includeAppIcons, onlyAppsWithLaunchIntent, InstalledAppsCallback { apps ->
if (!activity.isFinishing()) {
activity.runOnUiThread(Runnable { result.success(apps) })
}
})
}
// ...
private fun fetchInstalledApps(includeSystemApps: Boolean, includeAppIcons: Boolean, onlyAppsWithLaunchIntent: Boolean, callback: InstalledAppsCallback?) {
asyncWork.run(Runnable {
val installedApps = getInstalledApps(includeSystemApps, includeAppIcons, onlyAppsWithLaunchIntent)
callback?.onInstalledAppsListAvailable(installedApps)
})
}
private fun getInstalledApps(includeSystemApps: Boolean, includeAppIcons: Boolean, onlyAppsWithLaunchIntent: Boolean): List<Map<String, Any>> {
val packageManager: PackageManager = activity.getPackageManager()
val apps: List<PackageInfo> = packageManager.getInstalledPackages(0)
val installedApps: MutableList<Map<String, Any>> = ArrayList(apps.size)
// ...
val map = getAppData(packageManager, pInfo, includeAppIcons)
installedApps.add(map)
}
return installedApps
}
private fun getAppData(packageManager: PackageManager, pInfo: PackageInfo, includeAppIcon: Boolean): Map<String, Any> {
val map: MutableMap<String, Any> = HashMap()
map["app_name"] = pInfo.applicationInfo.loadLabel(packageManager).toString()
map["apk_file_path"] = pInfo.applicationInfo.sourceDir
map["package_name"] = pInfo.packageName
map["version_code"] = pInfo.versionCode
map["version_name"] = pInfo.versionName
map["data_dir"] = pInfo.applicationInfo.dataDir
map["system_app"] = isSystemApp(pInfo)
map["install_time"] = pInfo.firstInstallTime
map["update_time"] = pInfo.lastUpdateTime
// ...
return map
}
예쁘게 잘 바꿔준다...
'Flutter' 카테고리의 다른 글
Flutter Package: school_ui_toolkit (0) | 2020.07.30 |
---|---|
Flutter Gems (0) | 2020.07.28 |
Flutter: New Material Motion (0) | 2020.05.22 |
Flutter 1.17 (0) | 2020.05.07 |
Flutter Open Source App 1 : Time Cop (0) | 2020.04.02 |