feat(sdk): 初始化 Android SDK 核心功能模块
- 添加 SDK 配置管理、网络请求客户端和令牌存储功能 - 实现即时通讯 IM 模块,包括消息收发、群组管理和会话功能 - 集成推送服务和应用更新功能模块 - 创建示例应用演示 SDK 使用方法 - 配置项目依赖管理和构建设置
这个提交包含在:
父节点
b31a91f924
当前提交
173c3cbddd
@ -93,6 +93,13 @@ android {
|
||||
keyPassword 'android'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_17
|
||||
targetCompatibility JavaVersion.VERSION_17
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = "17"
|
||||
}
|
||||
buildTypes {
|
||||
debug {
|
||||
signingConfig signingConfigs.debug
|
||||
|
||||
@ -19,3 +19,4 @@ buildscript {
|
||||
}
|
||||
|
||||
apply plugin: "com.facebook.react.rootproject"
|
||||
|
||||
|
||||
@ -42,3 +42,6 @@ hermesEnabled=true
|
||||
# This allows your app to draw behind system bars for an immersive UI.
|
||||
# Note: Only works with ReactActivity and should not be used with custom Activity.
|
||||
edgeToEdgeEnabled=false
|
||||
|
||||
# Suppress Kotlin/Java JVM target mismatch from third-party libs
|
||||
kotlin.jvm.target.validation.mode=IGNORE
|
||||
|
||||
@ -15,8 +15,8 @@
|
||||
|
||||
| 配置项 | 值 |
|
||||
|--------|-----|
|
||||
| API 域名 | `https://sentry.xuqinmin.com` |
|
||||
| IM WebSocket | `wss://sentry.xuqinmin.com/ws/im` |
|
||||
| API 域名 | `https://dev.xuqinmin.com` |
|
||||
| IM WebSocket | `wss://dev.xuqinmin.com/ws/im` |
|
||||
| 演示 AppId | `ak_demo_chat` |
|
||||
| 演示用户 | `demo_alice`(Alice)、`demo_bob`(Bob) |
|
||||
| 演示模块 | `chat-home` |
|
||||
@ -142,7 +142,7 @@ cd XuqmGroup-RNChatDemo
|
||||
| `/api/v1/rn/` | update-service | 8084 |
|
||||
| `/api/` | tenant-service | 8081 |
|
||||
|
||||
所有接口通过 Nginx 反代至 `https://sentry.xuqinmin.com`。
|
||||
所有接口通过 Nginx 反代至 `https://dev.xuqinmin.com`。
|
||||
|
||||
---
|
||||
|
||||
|
||||
105
scripts/postinstall.js
普通文件
105
scripts/postinstall.js
普通文件
@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict'
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
const pickerFile = path.join(
|
||||
__dirname, '..', 'node_modules', 'react-native-document-picker',
|
||||
'android', 'src', 'main', 'java', 'com', 'reactnativedocumentpicker',
|
||||
'RNDocumentPickerModule.java',
|
||||
)
|
||||
|
||||
if (!fs.existsSync(pickerFile)) {
|
||||
console.log('[postinstall] react-native-document-picker not found, skipping patch')
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
let content = fs.readFileSync(pickerFile, 'utf8')
|
||||
|
||||
if (!content.includes('GuardedResultAsyncTask')) {
|
||||
console.log('[postinstall] react-native-document-picker already patched')
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
content = content.replace(
|
||||
'import com.facebook.react.bridge.GuardedResultAsyncTask;',
|
||||
'import java.util.concurrent.Executors;',
|
||||
)
|
||||
content = content.replace(
|
||||
' new ProcessDataTask(getReactApplicationContext(), uris, copyTo, promise).execute();',
|
||||
` final ReactApplicationContext ctx = getReactApplicationContext();
|
||||
final List<Uri> finalUris = uris;
|
||||
final String finalCopyTo = copyTo;
|
||||
Executors.newSingleThreadExecutor().execute(() -> {
|
||||
WritableArray results = Arguments.createArray();
|
||||
for (Uri u : finalUris) {
|
||||
results.pushMap(ProcessDataTask.getMetadataStatic(u, ctx.getApplicationContext(), finalCopyTo));
|
||||
}
|
||||
promise.resolve(results);
|
||||
});`,
|
||||
)
|
||||
content = content.replace(
|
||||
'private static class ProcessDataTask extends GuardedResultAsyncTask<ReadableArray> {',
|
||||
'private static class ProcessDataTask {',
|
||||
)
|
||||
content = content.replace(
|
||||
` private final WeakReference<Context> weakContext;
|
||||
private final List<Uri> uris;
|
||||
private final String copyTo;
|
||||
private final Promise promise;
|
||||
|
||||
protected ProcessDataTask(ReactContext reactContext, List<Uri> uris, String copyTo, Promise promise) {
|
||||
super(reactContext.getExceptionHandler());
|
||||
this.weakContext = new WeakReference<>(reactContext.getApplicationContext());
|
||||
this.uris = uris;
|
||||
this.copyTo = copyTo;
|
||||
this.promise = promise;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ReadableArray doInBackgroundGuarded() {
|
||||
WritableArray results = Arguments.createArray();
|
||||
for (Uri uri : uris) {
|
||||
results.pushMap(getMetadata(uri));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecuteGuarded(ReadableArray readableArray) {
|
||||
promise.resolve(readableArray);
|
||||
}
|
||||
|
||||
private WritableMap getMetadata(Uri uri) {
|
||||
Context context = weakContext.get();
|
||||
if (context == null) {
|
||||
return Arguments.createMap();
|
||||
}`,
|
||||
` static WritableMap getMetadataStatic(Uri uri, Context context, String copyTo) {
|
||||
if (context == null) {
|
||||
return Arguments.createMap();
|
||||
}`,
|
||||
)
|
||||
content = content.replace(
|
||||
' prepareFileUri(context, map, uri);',
|
||||
' prepareFileUri(context, map, uri, copyTo);',
|
||||
)
|
||||
content = content.replace(
|
||||
' private void prepareFileUri(Context context, WritableMap map, Uri uri) {',
|
||||
' private static void prepareFileUri(Context context, WritableMap map, Uri uri, String copyTo) {',
|
||||
)
|
||||
content = content.replace(
|
||||
' copyFileToLocalStorage(context, map, uri);',
|
||||
' copyFileToLocalStorage(context, map, uri, copyTo);',
|
||||
)
|
||||
content = content.replace(
|
||||
' private void copyFileToLocalStorage(Context context, WritableMap map, Uri uri) {',
|
||||
' private static void copyFileToLocalStorage(Context context, WritableMap map, Uri uri, String copyTo) {',
|
||||
)
|
||||
content = content.replace(
|
||||
' public File safeGetDestination(',
|
||||
' public static File safeGetDestination(',
|
||||
)
|
||||
|
||||
fs.writeFileSync(pickerFile, content, 'utf8')
|
||||
console.log('[postinstall] react-native-document-picker patched successfully')
|
||||
@ -1,6 +1,6 @@
|
||||
import { load, K } from '../utils/storage'
|
||||
|
||||
const BASE = 'https://sentry.xuqinmin.com/api/demo'
|
||||
const BASE = 'https://dev.xuqinmin.com/api/demo'
|
||||
const APP_ID = 'ak_demo_chat'
|
||||
|
||||
async function getToken(): Promise<string | null> {
|
||||
|
||||
@ -6,7 +6,7 @@ import { save, load, clearSession, K } from '../utils/storage'
|
||||
import pluginMeta from '../../plugin.json'
|
||||
|
||||
const APP_ID = 'ak_demo_chat'
|
||||
const SERVER_URL = 'https://sentry.xuqinmin.com'
|
||||
const SERVER_URL = 'https://dev.xuqinmin.com'
|
||||
|
||||
interface AuthState {
|
||||
ready: boolean
|
||||
|
||||
正在加载...
在新工单中引用
屏蔽一个用户