diff --git a/packages/package_info_plus/package_info_plus/CHANGELOG.md b/packages/package_info_plus/package_info_plus/CHANGELOG.md index 1c6e213a5d..bdfbaba2e0 100644 --- a/packages/package_info_plus/package_info_plus/CHANGELOG.md +++ b/packages/package_info_plus/package_info_plus/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.4.0 + +- Android: Migrate to Kotlin +- Android: Update dependencies, build config updates +- Android: Fix project title + ## 1.3.1 - Fix embedding issue in example diff --git a/packages/package_info_plus/package_info_plus/README.md b/packages/package_info_plus/package_info_plus/README.md index 2469310404..d1d0c2d6c1 100644 --- a/packages/package_info_plus/package_info_plus/README.md +++ b/packages/package_info_plus/package_info_plus/README.md @@ -2,11 +2,13 @@ [![Flutter Community: package_info_plus](https://fluttercommunity.dev/_github/header/package_info_plus)](https://github.com/fluttercommunity/community) +[![package_info_plus](https://github.com/fluttercommunity/plus_plugins/actions/workflows/package_info_plus.yaml/badge.svg)](https://github.com/fluttercommunity/plus_plugins/actions/workflows/package_info_plus.yaml) [![pub package](https://img.shields.io/pub/v/package_info_plus.svg)](https://pub.dev/packages/package_info_plus)

-

build
+
build

+ This Flutter plugin provides an API for querying information about an application package. @@ -24,7 +26,7 @@ application package. This works both on iOS and Android. ```dart import 'package:package_info_plus/package_info_plus.dart'; -... +... // Be sure to add this line if `PackageInfo.fromPlatform()` is called before runApp() WidgetsFlutterBinding.ensureInitialized(); @@ -54,5 +56,3 @@ Check out our documentation website to learn more. [Plus plugins documentation]( Calling to `PackageInfo.fromPlatform()` before the `runApp()` call will cause an exception. See https://github.com/fluttercommunity/plus_plugins/issues/309 - -**Important:** As of January 2021, the Flutter team is no longer accepting non-critical PRs for the original set of plugins in `flutter/plugins`, and instead they should be submitted in this project. [You can read more about this announcement here.](https://github.com/flutter/plugins/blob/master/CONTRIBUTING.md#important-note) as well as [in the Flutter 2 announcement blog post.](https://medium.com/flutter/whats-new-in-flutter-2-0-fe8e95ecc65) diff --git a/packages/package_info_plus/package_info_plus/android/build.gradle b/packages/package_info_plus/package_info_plus/android/build.gradle index 632f51b5c0..64cbb1e4ae 100644 --- a/packages/package_info_plus/package_info_plus/android/build.gradle +++ b/packages/package_info_plus/package_info_plus/android/build.gradle @@ -2,13 +2,16 @@ group 'io.flutter.plugins.packageinfo' version '1.0-SNAPSHOT' buildscript { + ext.kotlin_version = '1.6.10' + repositories { google() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.0.2' + classpath 'com.android.tools.build:gradle:7.1.1' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } @@ -20,6 +23,7 @@ rootProject.allprojects { } apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' android { compileSdkVersion 31 @@ -31,4 +35,8 @@ android { lintOptions { disable 'InvalidPackage' } + + dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + } } diff --git a/packages/package_info_plus/package_info_plus/android/settings.gradle b/packages/package_info_plus/package_info_plus/android/settings.gradle index a5683f94fc..50f50a6b45 100644 --- a/packages/package_info_plus/package_info_plus/android/settings.gradle +++ b/packages/package_info_plus/package_info_plus/android/settings.gradle @@ -1 +1 @@ -rootProject.name = 'package_info' +rootProject.name = 'package_info_plus' diff --git a/packages/package_info_plus/package_info_plus/android/src/main/java/dev/fluttercommunity/plus/packageinfo/PackageInfoPlugin.java b/packages/package_info_plus/package_info_plus/android/src/main/java/dev/fluttercommunity/plus/packageinfo/PackageInfoPlugin.java deleted file mode 100644 index 317f363340..0000000000 --- a/packages/package_info_plus/package_info_plus/android/src/main/java/dev/fluttercommunity/plus/packageinfo/PackageInfoPlugin.java +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package dev.fluttercommunity.plus.packageinfo; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.os.Build; -import androidx.annotation.NonNull; -import io.flutter.embedding.engine.plugins.FlutterPlugin; -import io.flutter.plugin.common.MethodCall; -import io.flutter.plugin.common.MethodChannel; -import io.flutter.plugin.common.MethodChannel.MethodCallHandler; -import io.flutter.plugin.common.MethodChannel.Result; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.HashMap; -import java.util.Map; - -/** PackageInfoPlugin */ -public class PackageInfoPlugin implements MethodCallHandler, FlutterPlugin { - private Context applicationContext; - private MethodChannel methodChannel; - - @SuppressWarnings("deprecation") - private static long getLongVersionCode(PackageInfo info) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - return info.getLongVersionCode(); - } - return info.versionCode; - } - - /** Plugin registration. */ - @Override - public void onAttachedToEngine(FlutterPluginBinding binding) { - this.applicationContext = binding.getApplicationContext(); - methodChannel = - new MethodChannel(binding.getBinaryMessenger(), "dev.fluttercommunity.plus/package_info"); - methodChannel.setMethodCallHandler(this); - } - - @Override - public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { - applicationContext = null; - methodChannel.setMethodCallHandler(null); - methodChannel = null; - } - - @Override - public void onMethodCall(MethodCall call, @NonNull Result result) { - try { - if (call.method.equals("getAll")) { - PackageManager pm = applicationContext.getPackageManager(); - PackageInfo info = pm.getPackageInfo(applicationContext.getPackageName(), 0); - - String buildSignature = getBuildSignature(pm); - - Map map = new HashMap<>(); - map.put("appName", info.applicationInfo.loadLabel(pm).toString()); - map.put("packageName", applicationContext.getPackageName()); - map.put("version", info.versionName); - map.put("buildNumber", String.valueOf(getLongVersionCode(info))); - if (buildSignature != null) map.put("buildSignature", buildSignature); - - result.success(map); - } else { - result.notImplemented(); - } - } catch (PackageManager.NameNotFoundException ex) { - result.error("Name not found", ex.getMessage(), null); - } - } - - @SuppressWarnings("deprecation") - private String getBuildSignature(PackageManager pm) { - try { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - PackageInfo packageInfo = - pm.getPackageInfo( - applicationContext.getPackageName(), PackageManager.GET_SIGNING_CERTIFICATES); - if (packageInfo == null || packageInfo.signingInfo == null) { - return null; - } - if (packageInfo.signingInfo.hasMultipleSigners()) { - return signatureToSha1(packageInfo.signingInfo.getApkContentsSigners()[0].toByteArray()); - } else { - return signatureToSha1( - packageInfo.signingInfo.getSigningCertificateHistory()[0].toByteArray()); - } - } else { - @SuppressLint("PackageManagerGetSignatures") - PackageInfo packageInfo = - pm.getPackageInfo(applicationContext.getPackageName(), PackageManager.GET_SIGNATURES); - if (packageInfo == null - || packageInfo.signatures == null - || packageInfo.signatures.length == 0 - || packageInfo.signatures[0] == null) { - return null; - } - return signatureToSha1(packageInfo.signatures[0].toByteArray()); - } - } catch (PackageManager.NameNotFoundException | NoSuchAlgorithmException e) { - return null; - } - } - - // Credits https://gist.github.com/scottyab/b849701972d57cf9562e - private String bytesToHex(byte[] bytes) { - final char[] hexArray = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' - }; - char[] hexChars = new char[bytes.length * 2]; - int v; - for (int j = 0; j < bytes.length; j++) { - v = bytes[j] & 0xFF; - hexChars[j * 2] = hexArray[v >>> 4]; - hexChars[j * 2 + 1] = hexArray[v & 0x0F]; - } - return new String(hexChars); - } - - // Credits https://gist.github.com/scottyab/b849701972d57cf9562e - private String signatureToSha1(byte[] sig) throws NoSuchAlgorithmException { - MessageDigest digest = MessageDigest.getInstance("SHA1"); - digest.update(sig); - byte[] hashtext = digest.digest(); - return bytesToHex(hashtext); - } -} diff --git a/packages/package_info_plus/package_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/packageinfo/PackageInfoPlugin.kt b/packages/package_info_plus/package_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/packageinfo/PackageInfoPlugin.kt new file mode 100644 index 0000000000..34080ffd53 --- /dev/null +++ b/packages/package_info_plus/package_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/packageinfo/PackageInfoPlugin.kt @@ -0,0 +1,130 @@ +package dev.fluttercommunity.plus.packageinfo + +import android.content.Context +import android.content.pm.PackageInfo +import android.content.pm.PackageManager +import android.os.Build +import io.flutter.embedding.engine.plugins.FlutterPlugin +import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding +import io.flutter.plugin.common.MethodCall +import io.flutter.plugin.common.MethodChannel +import io.flutter.plugin.common.MethodChannel.MethodCallHandler +import java.security.MessageDigest +import java.security.NoSuchAlgorithmException + +/** PackageInfoPlugin */ +class PackageInfoPlugin : MethodCallHandler, FlutterPlugin { + private var applicationContext: Context? = null + private var methodChannel: MethodChannel? = null + + /** Plugin registration. */ + override fun onAttachedToEngine(binding: FlutterPluginBinding) { + applicationContext = binding.applicationContext + methodChannel = MethodChannel(binding.binaryMessenger, CHANNEL_NAME) + methodChannel!!.setMethodCallHandler(this) + } + + override fun onDetachedFromEngine(binding: FlutterPluginBinding) { + applicationContext = null + methodChannel!!.setMethodCallHandler(null) + methodChannel = null + } + + override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { + try { + if (call.method == "getAll") { + val packageManager = applicationContext!!.packageManager + val info = packageManager.getPackageInfo(applicationContext!!.packageName, 0) + + val buildSignature = getBuildSignature(packageManager) + + val infoMap = HashMap() + infoMap.apply { + put("appName", info.applicationInfo.loadLabel(packageManager).toString()) + put("packageName", applicationContext!!.packageName) + put("version", info.versionName) + put("buildNumber", getLongVersionCode(info).toString()) + if (buildSignature != null) put("buildSignature", buildSignature) + }.also { resultingMap -> + result.success(resultingMap) + } + } else { + result.notImplemented() + } + } catch (ex: PackageManager.NameNotFoundException) { + result.error("Name not found", ex.message, null) + } + } + + @Suppress("deprecation") + private fun getLongVersionCode(info: PackageInfo): Long { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + info.longVersionCode + } else { + info.versionCode.toLong() + } + } + + @Suppress("deprecation", "PackageManagerGetSignatures") + private fun getBuildSignature(pm: PackageManager): String? { + return try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + val packageInfo = pm.getPackageInfo( + applicationContext!!.packageName, + PackageManager.GET_SIGNING_CERTIFICATES + ) + val signingInfo = packageInfo.signingInfo ?: return null + + if (signingInfo.hasMultipleSigners()) { + signatureToSha1(signingInfo.apkContentsSigners.first().toByteArray()) + } else { + signatureToSha1(signingInfo.signingCertificateHistory.first().toByteArray()) + } + } else { + val packageInfo = pm.getPackageInfo( + applicationContext!!.packageName, + PackageManager.GET_SIGNATURES + ) + val signatures = packageInfo.signatures + + if (signatures.isNullOrEmpty() || packageInfo.signatures.first() == null) { + null + } else { + signatureToSha1(signatures.first().toByteArray()) + } + } + } catch (e: PackageManager.NameNotFoundException) { + null + } catch (e: NoSuchAlgorithmException) { + null + } + } + + // Credits https://gist.github.com/scottyab/b849701972d57cf9562e + @Throws(NoSuchAlgorithmException::class) + private fun signatureToSha1(sig: ByteArray): String { + val digest = MessageDigest.getInstance("SHA1") + digest.update(sig) + val hashText = digest.digest() + return bytesToHex(hashText) + } + + // Credits https://gist.github.com/scottyab/b849701972d57cf9562e + private fun bytesToHex(bytes: ByteArray): String { + val hexArray = charArrayOf( + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' + ) + val hexChars = CharArray(bytes.size * 2) + var v: Int + for (j in bytes.indices) { + v = bytes[j].toInt() and 0xFF + hexChars[j * 2] = hexArray[v ushr 4] + hexChars[j * 2 + 1] = hexArray[v and 0x0F] + } + return String(hexChars) + } + + companion object { + private const val CHANNEL_NAME = "dev.fluttercommunity.plus/package_info" + } +} diff --git a/packages/package_info_plus/package_info_plus/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/package_info_plus/package_info_plus/example/android/gradle/wrapper/gradle-wrapper.properties index cb24abda10..7645e290ee 100644 --- a/packages/package_info_plus/package_info_plus/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/package_info_plus/package_info_plus/example/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip diff --git a/packages/package_info_plus/package_info_plus/pubspec.yaml b/packages/package_info_plus/package_info_plus/pubspec.yaml index 1058fc6ac7..ec05afcfa0 100644 --- a/packages/package_info_plus/package_info_plus/pubspec.yaml +++ b/packages/package_info_plus/package_info_plus/pubspec.yaml @@ -1,6 +1,6 @@ name: package_info_plus description: Flutter plugin for querying information about the application package, such as CFBundleVersion on iOS or versionCode on Android. -version: 1.3.1 +version: 1.4.0 homepage: https://plus.fluttercommunity.dev/ repository: https://github.com/fluttercommunity/plus_plugins/tree/main/packages/