Android集成Azure认知搜索客户端运行时异常排查求助
Azure认知搜索Android客户端兼容性问题排查
问题背景
已在Azure门户成功创建索引器与索引,门户端可正常执行查询操作。但在minSdk为26、compileSdk为33的Android应用中,使用Java构建Azure认知搜索客户端对接索引时,调用搜索方法触发运行时异常,怀疑是依赖包与Android API级别存在兼容性问题。
build.gradle配置
plugins { id 'com.android.application' id 'com.google.gms.google-services' } android { namespace 'com.example.hiddeneye' compileSdk 33 defaultConfig { applicationId "com.example.hiddeneye" minSdk 26 targetSdk 33 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } buildFeatures{ viewBinding true } compileOptions { coreLibraryDesugaringEnabled true sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } packagingOptions { resources { excludes += ['META-INF/INDEX.LIST', 'META-INF/NOTICE.md', 'META-INF/io.netty.versions.properties', 'META-INF/LICENSE.md'] } } } dependencies { implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'com.google.android.material:material:1.8.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.navigation:navigation-fragment:2.5.3' implementation 'androidx.navigation:navigation-ui:2.5.3' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' implementation 'com.google.code.gson:gson:2.10.1' implementation 'androidx.recyclerview:recyclerview:1.3.0' implementation 'androidx.cardview:cardview:1.0.0' // Azure blob storage implementation 'com.azure.android:azure-core:1.0.0-beta.12' implementation 'com.microsoft.azure.android:azure-storage-android:2.0.0@aar' // Azure Cogntive Search implementation 'com.azure:azure-search-documents:11.5.5' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3' }
搜索实现方法
public void searchVideos(String searchQuery) { System.out.println("search method block"); Executor serialExecutor = Executors.newSingleThreadExecutor(); serialExecutor.execute(new Runnable() { @Override public void run() { System.out.println("run method block"); try { System.out.println("client builder block"); searchClient = new SearchClientBuilder() .endpoint(endpoint) .credential(adminKey) .indexName(indexName) .buildClient(); System.out.println("search options block"); SearchOptions options = new SearchOptions(); options.setIncludeTotalCount(true); options.setFilter(""); options.setOrderBy(""); options.setSelect("videoPath", "age"); System.out.println("search results block"); SearchPagedIterable results = searchClient.search(searchQuery, options, Context.NONE); System.out.println("search items block"); List<VideoAttribute> items = new ArrayList<>(); for (SearchResult result : results) { VideoAttribute item = result.getDocument(VideoAttribute.class); items.add(item); } System.out.println(items.get(1)); videoAttributesLiveData.postValue(items); } catch (Exception e) { e.printStackTrace(); } } }); }
调用搜索方法的代码
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment CognitiveSearchRepository searchRepository = new CognitiveSearchRepository(); searchRepository.searchVideos("*"); return inflater.inflate(R.layout.fragment_settings, container, false); }
运行时报错信息
E/AndroidRuntime: FATAL EXCEPTION: pool-3-thread-1 java.lang.ExceptionInInitializerError at com.azure.core.implementation.ReflectionUtils.getLookupToUse(ReflectionUtils.java:119) at com.azure.core.util.ExpandableStringEnum.getDefaultConstructor(ExpandableStringEnum.java:88) at com.azure.core.util.ExpandableStringEnum.$r8$lambda$SMtq8BJfA6t_qJk1WfhslLPTCwc(Unknown Source:0) at com.azure.core.util.ExpandableStringEnum$$ExternalSyntheticLambda1.apply(Unknown Source:2) at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1710) at com.azure.core.util.ExpandableStringEnum.fromString(ExpandableStringEnum.java:68) at com.azure.core.http.HttpHeaderName.fromString(HttpHeaderName.java:60) at com.azure.core.http.HttpHeaderName.<clinit>(HttpHeaderName.java:88) at com.azure.core.http.HttpHeaderName.fromString(HttpHeaderName.java:56) at com.azure.core.http.policy.RequestIdPolicy.<init>(RequestIdPolicy.java:33) at com.azure.search.documents.implementation.util.Utility.buildHttpPipeline(Utility.java:130) at com.azure.search.documents.SearchClientBuilder.getHttpPipeline(SearchClientBuilder.java:203) at com.azure.search.documents.SearchClientBuilder.buildAsyncClient(SearchClientBuilder.java:175) at com.azure.search.documents.SearchClientBuilder.buildClient(SearchClientBuilder.java:153) at com.example.hiddeneye.Repository.CognitiveSearchRepository$1.run(CognitiveSearchRepository.java:51) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637) at java.lang.Thread.run(Thread.java:1012) Caused by: java.lang.RuntimeException: Unable to use package-private MethodHandles.Lookup constructor. at com.azure.core.implementation.ReflectionUtils.<clinit>(ReflectionUtils.java:84) ... 17 more Caused by: java.lang.NoSuchMethodException: java.lang.invoke.MethodHandles$Lookup.<init> [class java.lang.Class] at java.lang.Class.getConstructor0(Class.java:2363) at java.lang.Class.getDeclaredConstructor(Class.java:2201) at com.azure.core.implementation.ReflectionUtils.<clinit>(ReflectionUtils.java:76) ... 17 more
解决方案
核心问题分析
报错根源是混用了通用Java版的com.azure:azure-search-documents和Android版的com.azure.android:azure-core,前者依赖的反射逻辑使用了Android API 26不支持的MethodHandles.Lookup私有构造方法,导致初始化失败。
修复步骤
替换为Android专属依赖
移除通用Java版的搜索依赖,改用Azure官方为Android优化的认知搜索客户端:// 移除旧依赖:implementation 'com.azure:azure-search-documents:11.5.5' implementation 'com.azure.android:azure-search-documents:1.0.0-beta.6'保持已有的Android版
azure-core依赖版本一致:implementation 'com.azure.android:azure-core:1.0.0-beta.12'调整客户端构建代码
Android版API与通用版略有差异,推荐使用异步客户端适配Android主线程规则:public void searchVideos(String searchQuery) { SearchAsyncClient searchAsyncClient = new SearchClientBuilder() .endpoint(endpoint) .credential(new AzureKeyCredential(adminKey)) .indexName(indexName) .buildAsyncClient(); SearchOptions options = new SearchOptions(); options.setIncludeTotalCount(true); options.setFilter(""); options.setOrderBy(""); options.setSelect("videoPath", "age"); searchAsyncClient.search(searchQuery, options) .subscribe(results -> { List<VideoAttribute> items = new ArrayList<>(); for (SearchResult result : results) { VideoAttribute item = result.getDocument(VideoAttribute.class); items.add(item); } videoAttributesLiveData.postValue(items); }, error -> error.printStackTrace()); }确认脱糖配置有效性
保留原有的coreLibraryDesugaring配置,确保Java 8特性在Android API 26上正常运行:compileOptions { coreLibraryDesugaringEnabled true sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
额外注意事项
- 所有Azure相关依赖必须统一使用
com.azure.android前缀的包,避免混用通用Java版和Android版组件。 - Android版Azure SDK版本号与通用版独立,需确保依赖版本相互匹配。
内容的提问来源于stack exchange,提问作者Joel Tan
相关产品推荐
相关产品推荐

