Flutter [local_auth] 不适用于 Android <28
Posted
技术标签:
【中文标题】Flutter [local_auth] 不适用于 Android <28【英文标题】:Flutter [local_auth] Doesn't work on Android <28 【发布时间】:2020-09-24 08:52:45 【问题描述】:我正在尝试使用 local_auth,从 0.4.0 更新到 0.6.2
我按照说明在我的 MainActivity.java 中将 FlutterActivity 更改为 FlutterFragmentActivity
(根据本指南https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-android-projects 和此线程https://github.com/flutter/flutter/issues/57678)
这样
import io.flutter.embedding.android.FlutterFragmentActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.embedding.engine.FlutterEngine;
public class MainActivity extends FlutterFragmentActivity
@Override
public void configureFlutterEngine(FlutterEngine flutterEngine)
GeneratedPluginRegistrant.registerWith(flutterEngine);
我也改变了我的 style.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="LaunchTheme" parent="Theme.AppCompat.NoActionBar">
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
</resources>
还有我的 AndroidManifest.xml
<application
android:icon="@mipmap/ic_launcher"
android:allowBackup="false"
android:fullBackupContent="false"
android:label="XXX">
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
android:hardwareAccelerated="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:windowSoftInputMode="adjustResize">
<!-- This keeps the window background of the activity showing
until Flutter renders its first frame. It can be removed if
there is no splash screen (such as the default splash screen
defined in @style/LaunchTheme). -->
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background" />
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<activity android:name="com.apptreesoftware.barcodescan.BarcodeScannerActivity"/>
<provider
android:name="vn.hunghd.flutterdownloader.DownloadedFileProvider"
android:authorities="$applicationId.flutter_downloader.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
它适用于 Android 28 及更高版本,但不适用于旧版本。
当我在 android 27 上运行时出现此错误
I/zygote (10611):拒绝重新初始化先前失败的类 java.lang.Class:java.lang.NoClassDefFoundError:解析失败:Landroidx/core/widget/TintableCompoundDrawablesView; I/zygote (10611): (Throwable without stack trace) I/zygote (10611): Caused by: java.lang.ClassNotFoundException: 在路径上找不到类“androidx.core.widget.TintableCompoundDrawablesView”:DexPathList [[ zip 文件 "/data/app/it.xxx.flutter.xxx-bwyNjP_RiFiWr_SW3gO7MQ==/base.apk"],nativeLibraryDirectories=[/data/app/it.xxx.flutter.xxx-bwyNjP_RiFiWr_SW3gO7MQ==/lib/x86, /data/app/it.xxx.flutter.xxx-bwyNjP_RiFiWr_SW3gO7MQ==/base.apk!/lib/x86, /system/lib, /vendor/lib]] I/zygote (10611): (无堆栈跟踪可抛出) I/zygote (10611): E/MethodChannel#plugins.flutter.io/local_auth(10611): 处理方法调用失败 E/MethodChannel#plugins.flutter.io/local_auth(10611): android.view.InflateException: Binary XML 文件第 26 行:二进制 XML 文件第 45 行:错误膨胀类 androidx.appcompat.widget.DialogTitle E/MethodChannel#plugins.flutter.io/local_auth(10611):原因:android.view.InflateException:二进制 XML 文件第 45 行:膨胀类 androidx.appcompat.widget.DialogTitle 时出错E/MethodChannel#plugins.flutter.io/local_auth(10611):引起:java.lang.ClassNotFoundException:androidx.appcompat.widget.DialogTitle E/MethodChannel#plugins.flutter.io/local_auth(10611):在 java.lang .VMClassLoader.findLoadedClass(Native Method) E/MethodChannel#plugins.flutter.io/local_auth(10611): at java.lang.ClassLoader.findLoadedClass(ClassLoader.java:738) E/MethodChannel#plugins.flutter.io/local_auth( 10611): 在 java.lang.ClassLoader.loadClass(ClassLoader.java:363) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在 java.lang.ClassLoader.loadClass(ClassLoader.java:312) E/ MethodChannel#plugins.flutter.io/local_auth(10611):在 android.view.LayoutInflater.createView(LayoutInflater.java:606) E/MethodChannel#plugins.flutter.io/local_auth(10611):在 android.view.LayoutInflater。 createViewFromTag(LayoutInflater.java:790) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在 android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730) E/MethodChannel#plugins.flutter.io/ local_auth(10611):在 android.view.LayoutInflater.rInflate(LayoutInflater.java:863) E/MethodChannel#plugins.flutter.io/local_auth(10611):在 android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824) E/MethodChannel#plugins.flutter.io/local_auth(10611):在 android.view.LayoutInflater.rInflate(LayoutInflater.java:866) E/MethodChannel#plugins.flutter.io/local_auth(10611):在 android.view。 LayoutInflater.rInflateChildren(LayoutInflater.java:824) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在 android.view.LayoutInflater.parseInclude(LayoutInflater.java:995) E/MethodChannel#plugins.flutter.io/ local_auth(10611):在 android.view.LayoutInflater.rInflate(LayoutInflater.java:859) E/MethodChannel#plugins.flutter.io/local_auth(10611):在 android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:824) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在 android.view.LayoutInflater.inflate(LayoutInflater.java:515) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在android.view.LayoutInflater.inflate(LayoutInflater.java:423) E/MethodChannel#plugins.flutter.io/local_auth(10611):在 android.view.LayoutInflater.inflate(LayoutInflater.java:374) E/MethodChannel#plugins。 flutter.io/local_auth(10611):在 androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:555) E/MethodChannel#plugins.flutter.io/local_auth(10611):在 androidx.appcompat.app.AppCompatDialog。 setContentView(AppCompatDialog.java:95) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在 androidx.appcompat.app.AlertController.installContent(AlertController.java:232) E/MethodChannel#plugins.flutter.io/ local_auth(10611): 在 androidx.appcompat.app.AlertDialog.onCreate(AlertDialog.java:279) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在 android.app.Dialog.dispatchOnCreate(Dialog.java: 403) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在 android.app.Dialog.show(Dialog.java:302) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在 androidx。 F ragment.app.DialogFragment.onStart(DialogFragment.java:486) E/MethodChannel#plugins.flutter.io/local_auth(10611):在 androidx.fragment.app.Fragment.performStart(Fragment.java:2632) E/MethodChannel# plugins.flutter.io/local_auth(10611):在 androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:915) E/MethodChannel#plugins.flutter.io/local_auth(10611):在 androidx.fragment.app。 FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1238) E/MethodChannel#plugins.flutter.io/local_auth(10611):在 androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1303) E/MethodChannel#plugins.flutter。 io/local_auth(10611): 在 androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:439) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在 androidx.fragment.app.FragmentManagerImpl.executeOps( FragmentManagerImpl.java:2079) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在 androidx.fragment.app.FragmentManagerImpl.execut eOpsTogether(FragmentManagerImpl.java:1869) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在 androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1824) E/MethodChannel#plugins.flutter.io/ local_auth(10611):在 androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1727) E/MethodChannel#plugins.flutter.io/local_auth(10611):在 androidx.fragment.app.FragmentManagerImpl.executePendingTransactions(FragmentManagerImpl. java:183) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在 androidx.biometric.BiometricPrompt.authenticateInternal(BiometricPrompt.java:749) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在androidx.biometric.BiometricPrompt.authenticate(BiometricPrompt.java:658) E/MethodChannel#plugins.flutter.io/local_auth(10611): at io.flutter.plugins.localauth.AuthenticationHelper.authenticate(AuthenticationHelper.java:103) E/ MethodChannel#plugins.flutter.io/local_auth(10611):在 io.flut ter.plugins.localauth.LocalAuthPlugin.onMethodCall(LocalAuthPlugin.java:120) E/MethodChannel#plugins.flutter.io/local_auth(10611): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java: 226) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在 io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:85) E/MethodChannel#plugins.flutter.io/local_auth( 10611): 在 io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:631) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在 android.os.MessageQueue.nativePollOnce(Native Method) E /MethodChannel#plugins.flutter.io/local_auth(10611):在 android.os.MessageQueue.next(MessageQueue.java:325) E/MethodChannel#plugins.flutter.io/local_auth(10611):在 android.os.Looper .loop(Looper.java:142) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在 android.app.ActivityThread.main(ActivityThread.java:6494) E/MethodChannel#plugins.flutter.io/local_auth (1 0611): 在 java.lang.reflect.Method.invoke(Native Method) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java :438) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807) E/MethodChannel#plugins.flutter.io/local_auth(10611 ):引起:java.lang.NoClassDefFoundError:解析失败:Landroidx/core/widget/TintableCompoundDrawablesView; E/MethodChannel#plugins.flutter.io/local_auth(10611):在 androidx.appcompat.app.AppCompatDelegateImpl.createView(AppCompatDelegateImpl.java:1383) E/MethodChannel#plugins.flutter.io/local_auth(10611):在 androidx。 appcompat.app.AppCompatDelegateImpl.onCreateView(AppCompatDelegateImpl.java:1457) E/MethodChannel#plugins.flutter.io/local_auth(10611):在 android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:772) E/MethodChannel#plugins。 flutter.io/local_auth(10611): 在 android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在 android.view.LayoutInflater.inflate(LayoutInflater. java:492) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在 android.view.LayoutInflater.inflate(LayoutInflater.java:423) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在android.view.LayoutInflater.inflate(LayoutInflater.java:374) E/MethodChannel#plugins.flutter.io/local_auth(10611):在 com.android.internal.policy.DecorView.o nResourcesLoaded(DecorView.java:1933) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在 com.android.internal.policy.PhoneWindow.generateLayout(PhoneWindow.java:2586) E/MethodChannel#plugins.flutter。 io/local_auth(10611):在 com.android.internal.policy.PhoneWindow.installDecor(PhoneWindow.java:2659) E/MethodChannel#plugins.flutter.io/local_auth(10611):在 com.android.internal.policy。 PhoneWindow.getDecorView(PhoneWindow.java:2067) E/MethodChannel#plugins.flutter.io/local_auth(10611):在 androidx.appcompat.app.AppCompatDelegateImpl.createSubDecor(AppCompatDelegateImpl.java:717) E/MethodChannel#plugins.flutter。 io/local_auth(10611): 在 androidx.appcompat.app.AppCompatDelegateImpl.ensureSubDecor(AppCompatDelegateImpl.java:659) E/MethodChannel#plugins.flutter.io/local_auth(10611): 在 androidx.appcompat.app.AppCompatDelegateImpl.setContentView( AppCompatDelegateImpl.java:552) E/MethodChannel#plugins.flutter.io/local_auth(10611): ... 30 更多 E/MethodChannel#plugins.flutter.io/local_auth(10 611):原因:java.lang.ClassNotFoundException:在路径上找不到类“androidx.core.widget.TintableCompoundDrawablesView”:DexPathList [[zip file“/data/app/it.xxx.flutter.xxx-bwyNjP_RiFiWr_SW3gO7MQ= =/base.apk"],nativeLibraryDirectories=[/data/app/it.xxx.flutter.xxx-bwyNjP_RiFiWr_SW3gO7MQ==/lib/x86, /data/app/it.xxx.flutter.xxx-bwyNjP_RiFiWr_SW3gO7MQ==/base .apk!/lib/x86, /system/lib, /vendor/lib]] E/MethodChannel#plugins.flutter.io/local_auth(10611): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:125) E /MethodChannel#plugins.flutter.io/local_auth(10611):在 java.lang.ClassLoader.loadClass(ClassLoader.java:379) E/MethodChannel#plugins.flutter.io/local_auth(10611):在 java.lang.ClassLoader .loadClass(ClassLoader.java:312)
E/MethodChannel#plugins.flutter.io/local_auth(10611): ... 44 更多
这是我的约定
[✓] Flutter: is fully installed. (Channel stable, v1.17.3, on Mac OS X 10.15.5 19F101, locale en-IT)
[✓] Android toolchain - develop for Android devices: is fully installed. (Android SDK version 29.0.3)
[✓] Xcode - develop for ios and macOS: is fully installed. (Xcode 11.5)
[✓] Android Studio: is fully installed. (version 3.6)
[✓] VS Code: is fully installed. (version 1.45.1)
[✓] Connected device: is fully installed. (1 available)
任何建议将不胜感激
【问题讨论】:
【参考方案1】:对我有帮助:
活动
导入 io.flutter.embedding.android.FlutterActivity
类 MainActivity: FlutterActivity()
清单
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:name="io.flutter.app.FlutterApplication"
android:label="your label"
android:icon="@mipmap/ic_launcher">
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- This keeps the window background of the activity showing
until Flutter renders its first frame. It can be removed if
there is no splash screen (such as the default splash screen
defined in @style/LaunchTheme). -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<!-- The Agora SDK requires Bluetooth permissions in case users are using Bluetooth devices.-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
【讨论】:
【参考方案2】:我可能迟到了,但今天我遇到了同样的问题,对我来说遵循这个解决方案很有用
https://github.com/hnvn/flutter_image_cropper/issues/78
删除这些部分
if (details.requested.group == 'com.android.support'
&& !details.requested.name.contains('multidex') )
details.useVersion "27.1.1"
if (details.requested.group == 'androidx.core'
&& !details.requested.name.contains('androidx') )
details.useVersion "1.0.1"
if (requested.group == "androidx")
if (!requested.name.startsWith("multidex"))
details.useVersion "$targetSdk.+"
来自 Android/build.gradle
【讨论】:
【参考方案3】:我解决了我的问题...
我删除了
if (
details.requested.group == 'com.android.support'
&& !details.requested.name.contains('multidex')
)
details.useVersion "27.1.1"
if (
details.requested.group == 'androidx.core'
&& !details.requested.name.contains('androidx')
)
details.useVersion "1.0.1"
if (requested.group == "androidx" && !requested.name.startsWith("multidex"))
details.useVersion "$targetSdk.+"
来自 android/build.gradle
它的工作原理
【讨论】:
以上是关于Flutter [local_auth] 不适用于 Android <28的主要内容,如果未能解决你的问题,请参考以下文章
Android Studio 代码建议不适用于 Flutter
Flutter dio不适用于flutter web中的post请求
为啥这些 Firestore 规则不适用于 Flutter Firebase 插件?