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的主要内容,如果未能解决你的问题,请参考以下文章

为 local_auth Flutter 添加自定义对话框

Android Studio 代码建议不适用于 Flutter

Flutter dio不适用于flutter web中的post请求

为啥这些 Firestore 规则不适用于 Flutter Firebase 插件?

Firebase Query 不适用于 Flutter,如何解决?

Flutter + Firebase 手机 OTP 不适用于其他国家/地区