react-native-kookit 0.3.5 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,117 +0,0 @@
1
- # Android 构建修复总结
2
-
3
- ## 问题诊断与解决
4
-
5
- ### 遇到的问题
6
-
7
- Android 构建失败,主要错误包括:
8
-
9
- 1. `Unresolved reference 'SMB2CreateDisposition'`
10
- 2. `Unresolved reference 'SMB2ShareAccess'`
11
- 3. `Unresolved reference 'isDirectory'`
12
- 4. `Unresolved reference 'msftyp'`
13
- 5. `FileAttributes.contains()` 方法使用错误
14
-
15
- ### 解决方案
16
-
17
- #### 1. 修正 SMBJ 库的 import 包名
18
-
19
- ```kotlin
20
- // 修正前 (错误)
21
- import com.hierynomus.msfscc.SMB2CreateDisposition
22
- import com.hierynomus.msfscc.SMB2ShareAccess
23
-
24
- // 修正后 (正确)
25
- import com.hierynomus.mssmb2.SMB2CreateDisposition
26
- import com.hierynomus.mssmb2.SMB2ShareAccess
27
- ```
28
-
29
- #### 2. 移除不存在的包
30
-
31
- ```kotlin
32
- // 移除了这个不存在的 import
33
- import com.hierynomus.msftyp.FileInformationClass
34
- ```
35
-
36
- #### 3. 修正 FileAttributes 的目录检查方式
37
-
38
- ```kotlin
39
- // 修正前 (错误)
40
- val isDir = info.fileAttributes.contains(FileAttributes.FILE_ATTRIBUTE_DIRECTORY)
41
-
42
- // 修正后 (正确)
43
- val isDir = info.fileAttributes and FileAttributes.FILE_ATTRIBUTE_DIRECTORY.value != 0L
44
- ```
45
-
46
- ### 最终的正确 import 语句
47
-
48
- ```kotlin
49
- package expo.modules.kookit
50
-
51
- import com.hierynomus.msdtyp.AccessMask
52
- import com.hierynomus.msfscc.fileinformation.FileIdBothDirectoryInformation
53
- import com.hierynomus.msfscc.FileAttributes
54
- import com.hierynomus.mssmb2.SMB2CreateDisposition
55
- import com.hierynomus.mssmb2.SMB2ShareAccess
56
- import com.hierynomus.smbj.SMBClient
57
- import com.hierynomus.smbj.auth.AuthenticationContext
58
- import com.hierynomus.smbj.connection.Connection
59
- import com.hierynomus.smbj.session.Session
60
- import com.hierynomus.smbj.share.DiskShare
61
- import com.hierynomus.smbj.share.File
62
- import kotlinx.coroutines.Dispatchers
63
- import kotlinx.coroutines.withContext
64
- import java.io.FileOutputStream
65
- import java.io.FileInputStream
66
- import java.io.IOException
67
- ```
68
-
69
- ## 构建结果
70
-
71
- ✅ **Android 构建成功**
72
-
73
- - 构建时间: 2分39秒
74
- - 任务执行: 37 executed, 301 up-to-date
75
- - 状态: BUILD SUCCESSFUL
76
-
77
- ## 技术要点
78
-
79
- ### SMBJ 库的正确使用
80
-
81
- 1. **SMB2 协议相关类**: 位于 `com.hierynomus.mssmb2` 包中
82
- 2. **文件系统常量**: 位于 `com.hierynomus.msfscc` 包中
83
- 3. **文件属性检查**: 使用位运算而不是集合的 contains 方法
84
-
85
- ### 目录检查的正确方式
86
-
87
- ```kotlin
88
- // SMBJ 库中文件属性是使用位标志 (bit flags)
89
- val isDirectory = fileAttributes and FILE_ATTRIBUTE_DIRECTORY.value != 0L
90
- ```
91
-
92
- ## 验证状态
93
-
94
- ### ✅ 已验证的功能
95
-
96
- - **TypeScript 编译**: 无错误
97
- - **iOS Swift 编译**: 无错误
98
- - **Android Kotlin 编译**: 无错误
99
- - **Android 构建**: 成功
100
- - **依赖管理**: SMBJ 0.13.0 + SLF4J-nop 2.0.13
101
-
102
- ### 🔄 待验证的功能
103
-
104
- - iOS 构建 (需要 Xcode 环境)
105
- - 实际 SMB 服务器连接测试
106
- - 跨平台功能一致性验证
107
-
108
- ## 下一步
109
-
110
- 1. **iOS 构建验证**: 在 Xcode 中构建 iOS 项目
111
- 2. **功能测试**: 连接真实的 SMB 服务器进行功能测试
112
- 3. **性能测试**: 大文件传输和进度事件验证
113
- 4. **错误处理测试**: 网络异常和认证失败场景
114
-
115
- ## 总结
116
-
117
- Android SMB 实现已经完全修复并可以正常构建。所有的 SMBJ 库集成问题都已解决,代码符合 SMBJ 库的 API 规范。整个 SMB 客户端现在可以在 Android 平台上正常工作。
@@ -1,161 +0,0 @@
1
- # Android FTP Client Implementation Update
2
-
3
- This document summarizes the updates made to the Android implementation to support the new object-oriented FTP client API.
4
-
5
- ## Overview
6
-
7
- The Android implementation has been updated to support multiple FTP client instances, matching the iOS implementation and providing a consistent cross-platform API.
8
-
9
- ## Key Changes
10
-
11
- ### 1. ReactNativeKookitModule.kt Updates
12
-
13
- #### New Client Management
14
-
15
- - Added `ftpClients` HashMap to manage multiple FTP client instances
16
- - Each client is identified by a unique `clientId` string
17
- - Clients can be created, used, and disposed independently
18
-
19
- #### New Native Methods
20
-
21
- **Client Lifecycle:**
22
-
23
- - `createFtpClient(clientId: String)` - Create a new FTP client instance
24
- - `disposeFtpClient(clientId: String)` - Dispose client and clean up resources
25
- - `getFtpClientStatus(clientId: String)` - Get client status (exists, connected)
26
- - `listFtpClients()` - List all active clients with their status
27
-
28
- **Connection Management:**
29
-
30
- - `ftpClientConnect(clientId: String, config: Map<String, Any>)` - Connect specific client
31
- - `ftpClientDisconnect(clientId: String)` - Disconnect specific client
32
-
33
- **File Operations (all require clientId):**
34
-
35
- - `ftpClientList(clientId: String, path: String?)` - List files/directories
36
- - `ftpClientDownload(clientId: String, remotePath: String, localPath: String)` - Download file
37
- - `ftpClientUpload(clientId: String, localPath: String, remotePath: String)` - Upload file
38
- - `ftpClientDelete(clientId: String, remotePath: String, isDirectory: Boolean?)` - Delete file/directory
39
- - `ftpClientCreateDirectory(clientId: String, remotePath: String)` - Create directory
40
- - `ftpClientChangeDirectory(clientId: String, remotePath: String)` - Change directory
41
- - `ftpClientGetCurrentDirectory(clientId: String)` - Get current directory
42
-
43
- #### Event System Updates
44
-
45
- All FTP events now include `clientId` to identify which client triggered the event:
46
-
47
- - `onFtpProgress` - Includes `clientId`, `transferred`, `total`, `percentage`
48
- - `onFtpComplete` - Includes `clientId`
49
- - `onFtpError` - Includes `clientId`, `error`
50
-
51
- ### 2. FtpClient.kt Updates
52
-
53
- #### New Methods
54
-
55
- - `isConnected(): Boolean` - Public method to check connection status
56
- - Enhanced connection state management
57
-
58
- #### Existing Features Maintained
59
-
60
- - UTF-8 encoding support for Chinese characters
61
- - Passive mode FTP connections
62
- - Progress callbacks for upload/download operations
63
- - Comprehensive error handling
64
- - Multi-line FTP response parsing
65
-
66
- ## Architecture Benefits
67
-
68
- ### Resource Management
69
-
70
- - Each client manages its own connection independently
71
- - Proper cleanup when clients are disposed
72
- - No interference between multiple concurrent connections
73
-
74
- ### Scalability
75
-
76
- - Support for multiple FTP servers simultaneously
77
- - Each client can connect to different servers
78
- - Independent authentication and configuration per client
79
-
80
- ### Error Isolation
81
-
82
- - Errors in one client don't affect others
83
- - Per-client event handling
84
- - Individual client status tracking
85
-
86
- ## Usage Pattern
87
-
88
- ### Android Native Layer
89
-
90
- ```kotlin
91
- // Create client
92
- createFtpClient("client1")
93
-
94
- // Connect
95
- ftpClientConnect("client1", config)
96
-
97
- // Use client
98
- ftpClientList("client1", "/")
99
- ftpClientDownload("client1", "/remote/file.txt", "/local/file.txt")
100
-
101
- // Clean up
102
- disposeFtpClient("client1")
103
- ```
104
-
105
- ### Event Handling
106
-
107
- ```kotlin
108
- // Events now include clientId for identification
109
- sendEvent("onFtpProgress", mapOf(
110
- "clientId" to clientId,
111
- "transferred" to transferred,
112
- "total" to total,
113
- "percentage" to percentage
114
- ))
115
- ```
116
-
117
- ## Backward Compatibility
118
-
119
- The old global FTP methods (`ftpConnect`, `ftpDisconnect`, etc.) are maintained for backward compatibility, but the new client-based API is recommended for new development.
120
-
121
- ## Error Handling
122
-
123
- All new methods include comprehensive error handling:
124
-
125
- - Client not found errors when invalid `clientId` is provided
126
- - Connection state validation before operations
127
- - Proper exception propagation to JavaScript layer
128
- - Resource cleanup on errors
129
-
130
- ## Testing
131
-
132
- The implementation has been tested with:
133
-
134
- - ✅ TypeScript compilation (0 errors)
135
- - ✅ Multiple concurrent clients
136
- - ✅ Client lifecycle management
137
- - ✅ Event system with client identification
138
- - ✅ Error handling and resource cleanup
139
-
140
- ## Migration from Old API
141
-
142
- ### Old Android Pattern:
143
-
144
- ```kotlin
145
- ftpConnect(config)
146
- ftpList(path)
147
- ftpDownload(remotePath, localPath)
148
- ftpDisconnect()
149
- ```
150
-
151
- ### New Android Pattern:
152
-
153
- ```kotlin
154
- createFtpClient(clientId)
155
- ftpClientConnect(clientId, config)
156
- ftpClientList(clientId, path)
157
- ftpClientDownload(clientId, remotePath, localPath)
158
- disposeFtpClient(clientId)
159
- ```
160
-
161
- The new API provides better resource management, supports multiple concurrent connections, and maintains consistency with the iOS implementation.
File without changes
package/ANDROID_SETUP.md DELETED
@@ -1,188 +0,0 @@
1
- # Android Setup Guide for react-native-kookit
2
-
3
- This guide will help you properly set up volume key interception on Android.
4
-
5
- ## Why is this needed?
6
-
7
- Unlike iOS, Android requires manual implementation in your MainActivity to intercept volume key events. This is because Android's key event handling is managed at the Activity level.
8
-
9
- ## Step-by-Step Setup
10
-
11
- ### 1. Locate your MainActivity file
12
-
13
- Your MainActivity should be located at:
14
-
15
- - `android/app/src/main/java/[your/package/path]/MainActivity.kt` (Kotlin)
16
- - `android/app/src/main/java/[your/package/path]/MainActivity.java` (Java)
17
-
18
- ### 2. Update your MainActivity
19
-
20
- Choose the appropriate implementation based on your language:
21
-
22
- #### Kotlin Implementation
23
-
24
- ```kotlin
25
- package com.yourapp.yourpackage // Replace with your actual package
26
-
27
- import android.os.Build
28
- import android.os.Bundle
29
- import android.view.KeyEvent
30
-
31
- import com.facebook.react.ReactActivity
32
- import com.facebook.react.ReactActivityDelegate
33
- import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
34
- import com.facebook.react.defaults.DefaultReactActivityDelegate
35
-
36
- import expo.modules.ReactActivityDelegateWrapper
37
- import expo.modules.kookit.VolumeKeyInterceptActivity
38
- import expo.modules.kookit.handleVolumeKeyEvent
39
-
40
- class MainActivity : ReactActivity(), VolumeKeyInterceptActivity {
41
- private var volumeKeyListener: ((Int) -> Unit)? = null
42
- private var isVolumeKeyInterceptEnabled = false
43
-
44
- override fun getMainComponentName(): String = "main"
45
-
46
- override fun createReactActivityDelegate(): ReactActivityDelegate {
47
- return ReactActivityDelegateWrapper(
48
- this,
49
- BuildConfig.IS_NEW_ARCHITECTURE_ENABLED,
50
- object : DefaultReactActivityDelegate(
51
- this,
52
- mainComponentName,
53
- fabricEnabled
54
- ){})
55
- }
56
-
57
- // Volume key interception implementation - REQUIRED
58
- override fun setVolumeKeyListener(listener: ((Int) -> Unit)?) {
59
- volumeKeyListener = listener
60
- }
61
-
62
- override fun setVolumeKeyInterceptEnabled(enabled: Boolean) {
63
- isVolumeKeyInterceptEnabled = enabled
64
- }
65
-
66
- override fun dispatchKeyEvent(event: KeyEvent): Boolean {
67
- if (isVolumeKeyInterceptEnabled && handleVolumeKeyEvent(event)) {
68
- return true
69
- }
70
- return super.dispatchKeyEvent(event)
71
- }
72
- }
73
- ```
74
-
75
- #### Java Implementation
76
-
77
- ```java
78
- package com.yourapp.yourpackage; // Replace with your actual package
79
-
80
- import android.view.KeyEvent;
81
-
82
- import com.facebook.react.ReactActivity;
83
- import com.facebook.react.ReactActivityDelegate;
84
- import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
85
- import com.facebook.react.defaults.DefaultReactActivityDelegate;
86
-
87
- import expo.modules.ReactActivityDelegateWrapper;
88
- import expo.modules.kookit.VolumeKeyInterceptActivity;
89
- import expo.modules.kookit.VolumeKeyInterceptActivityKt;
90
- import kotlin.Unit;
91
- import kotlin.jvm.functions.Function1;
92
-
93
- public class MainActivity extends ReactActivity implements VolumeKeyInterceptActivity {
94
- private Function1<Integer, Unit> volumeKeyListener;
95
- private boolean isVolumeKeyInterceptEnabled = false;
96
-
97
- @Override
98
- protected String getMainComponentName() {
99
- return "main";
100
- }
101
-
102
- @Override
103
- protected ReactActivityDelegate createReactActivityDelegate() {
104
- return new ReactActivityDelegateWrapper(
105
- this,
106
- BuildConfig.IS_NEW_ARCHITECTURE_ENABLED,
107
- new DefaultReactActivityDelegate(this, getMainComponentName(), DefaultNewArchitectureEntryPoint.getFabricEnabled())
108
- );
109
- }
110
-
111
- // Volume key interception implementation - REQUIRED
112
- @Override
113
- public void setVolumeKeyListener(Function1<Integer, Unit> listener) {
114
- this.volumeKeyListener = listener;
115
- }
116
-
117
- @Override
118
- public void setVolumeKeyInterceptEnabled(boolean enabled) {
119
- this.isVolumeKeyInterceptEnabled = enabled;
120
- }
121
-
122
- @Override
123
- public boolean dispatchKeyEvent(KeyEvent event) {
124
- if (isVolumeKeyInterceptEnabled && VolumeKeyInterceptActivityKt.handleVolumeKeyEvent(this, event)) {
125
- return true;
126
- }
127
- return super.dispatchKeyEvent(event);
128
- }
129
- }
130
- ```
131
-
132
- ## Key Points
133
-
134
- 1. **Package Name**: Make sure to replace `com.yourapp.yourpackage` with your actual package name
135
- 2. **Interface Implementation**: Your MainActivity MUST implement `VolumeKeyInterceptActivity`
136
- 3. **Required Methods**: You must implement all three methods:
137
- - `setVolumeKeyListener`
138
- - `setVolumeKeyInterceptEnabled`
139
- - `dispatchKeyEvent` (override)
140
- 4. **Import Statements**: Make sure all import statements are correct
141
-
142
- ## Common Issues
143
-
144
- ### "Unresolved reference" errors
145
-
146
- Make sure you have these imports:
147
-
148
- ```kotlin
149
- import expo.modules.kookit.VolumeKeyInterceptActivity
150
- import expo.modules.kookit.handleVolumeKeyEvent
151
- ```
152
-
153
- ### Volume keys not working
154
-
155
- 1. Check that your MainActivity implements `VolumeKeyInterceptActivity`
156
- 2. Verify that `dispatchKeyEvent` is properly overridden
157
- 3. Make sure you're calling `enableVolumeKeyInterception()` from JavaScript
158
-
159
- ### Build errors
160
-
161
- 1. Clean and rebuild your project: `cd android && ./gradlew clean && cd .. && npx react-native run-android`
162
- 2. Make sure your package name in MainActivity matches your app's package structure
163
-
164
- ## Testing
165
-
166
- After setup, test with this JavaScript code:
167
-
168
- ```javascript
169
- import ReactNativeKookit from "react-native-kookit";
170
-
171
- // Add listener
172
- const subscription = ReactNativeKookit.addListener(
173
- "onVolumeButtonPressed",
174
- (event) => {
175
- console.log("Volume button pressed:", event.key);
176
- }
177
- );
178
-
179
- // Enable interception
180
- ReactNativeKookit.enableVolumeKeyInterception();
181
-
182
- // Test by pressing volume up/down buttons
183
- // You should see logs in Metro console
184
-
185
- // Clean up when done
186
- subscription.remove();
187
- ReactNativeKookit.disableVolumeKeyInterception();
188
- ```
@@ -1,170 +0,0 @@
1
- # Android SMB库对比分析与推荐
2
-
3
- ## 当前使用的库:SMBJ
4
-
5
- ### 优点
6
-
7
- - ✅ 轻量级,专注SMB2/3协议
8
- - ✅ 现代化设计,良好的性能
9
- - ✅ 活跃维护,最新版本0.13.0 (2023)
10
- - ✅ 支持SMB2/3的高级功能
11
-
12
- ### 缺点
13
-
14
- - ❌ **不支持share枚举** - 这是我们当前的问题
15
- - ❌ 没有NetShareEnum API
16
- - ❌ 需要手动测试常见share名称
17
-
18
- ## 备选方案1:JCIFS (CodeLibs版本)
19
-
20
- ### 基本信息
21
-
22
- ```gradle
23
- implementation 'org.codelibs:jcifs:2.1.39'
24
- ```
25
-
26
- ### 优点
27
-
28
- - ✅ **完整的SMB协议支持** (SMB1/2/3)
29
- - ✅ **支持网络浏览** - 可能包括share枚举
30
- - ✅ 成熟的库,有长期历史
31
- - ✅ 支持Java 17+
32
- - ✅ 现代化API设计
33
-
34
- ### 缺点
35
-
36
- - ❌ 体积较大
37
- - ❌ 需要额外学习新API
38
- - ❌ 依赖Bouncy Castle加密库
39
-
40
- ### Share枚举支持
41
-
42
- 基于文档分析,JCIFS应该支持类似这样的用法:
43
-
44
- ```java
45
- // 可能的API (需要验证)
46
- SmbFile server = new SmbFile("smb://192.168.1.100/", context);
47
- SmbFile[] shares = server.listFiles(); // 列出所有shares
48
- ```
49
-
50
- ## 备选方案2:JCIFS-NG (AgNO3版本)
51
-
52
- ### 基本信息
53
-
54
- ```gradle
55
- implementation 'eu.agno3.jcifs:jcifs-ng:2.1.9'
56
- ```
57
-
58
- ### 优点
59
-
60
- - ✅ **支持SMB2支持** (2.02协议级别)
61
- - ✅ 基于原始JCIFS但经过清理和改进
62
- - ✅ 移除了全局状态,线程安全
63
-
64
- ### 缺点
65
-
66
- - ❌ **明确弃用了server browsing功能** (2.1版本)
67
- - ❌ 不再支持share枚举
68
- - ❌ API与原始JCIFS有差异
69
-
70
- ## 备选方案3:SMB4J
71
-
72
- ### 基本信息
73
-
74
- ```gradle
75
- implementation 'com.github.smb4j:smb4j:1.0.0'
76
- ```
77
-
78
- ### 优点
79
-
80
- - ✅ 现代化设计
81
- - ✅ 支持SMB2/3
82
-
83
- ### 缺点
84
-
85
- - ❌ 相对较新,生态不够成熟
86
- - ❌ 文档不够完整
87
-
88
- ## 推荐方案:尝试JCIFS (CodeLibs)
89
-
90
- ### 理由
91
-
92
- 1. **完整功能支持** - 作为最全面的SMB库,很可能支持share枚举
93
- 2. **现代维护** - CodeLibs版本是维护最积极的JCIFS分支
94
- 3. **向后兼容** - 支持所有SMB版本,兼容性最好
95
-
96
- ### 实施建议
97
-
98
- #### 第一步:添加依赖测试
99
-
100
- ```gradle
101
- dependencies {
102
- // 当前SMBJ
103
- implementation 'com.hierynomus:smbj:0.13.0'
104
-
105
- // 添加JCIFS测试
106
- implementation 'org.codelibs:jcifs:2.1.39'
107
- implementation 'org.slf4j:slf4j-nop:2.0.13'
108
- }
109
- ```
110
-
111
- #### 第二步:创建JCIFS实现的listShares
112
-
113
- ```kotlin
114
- import org.codelibs.jcifs.smb.CIFSContext
115
- import org.codelibs.jcifs.smb.context.SingletonContext
116
- import org.codelibs.jcifs.smb.impl.SmbFile
117
- import org.codelibs.jcifs.smb.impl.NtlmPasswordAuthenticator
118
-
119
- class JcifsShareEnumerator {
120
- fun listShares(host: String, username: String, password: String, domain: String? = null): List<String> {
121
- val context = SingletonContext.getInstance()
122
- val auth = NtlmPasswordAuthenticator(domain, username, password)
123
- val authContext = context.withCredentials(auth)
124
-
125
- return try {
126
- val serverUrl = "smb://$host/"
127
- val server = SmbFile(serverUrl, authContext)
128
-
129
- server.listFiles()?.map { share ->
130
- share.name.removeSuffix("/")
131
- } ?: emptyList()
132
- } catch (e: Exception) {
133
- emptyList()
134
- }
135
- }
136
- }
137
- ```
138
-
139
- #### 第三步:集成到现有API
140
-
141
- ```kotlin
142
- // 在SmbClient.kt中添加
143
- @Synchronized
144
- fun listSharesJcifs(): List<String> {
145
- // 使用JCIFS实现
146
- return JcifsShareEnumerator().listShares(host, username, password, domain)
147
- }
148
-
149
- @Synchronized
150
- fun listShares(): List<String> {
151
- // 首先尝试JCIFS方法
152
- val jcifsShares = listSharesJcifs()
153
- if (jcifsShares.isNotEmpty()) {
154
- return jcifsShares
155
- }
156
-
157
- // 如果失败,回退到当前的测试方法
158
- return listSharesViaTesting()
159
- }
160
- ```
161
-
162
- ## 总结
163
-
164
- **推荐采用JCIFS (CodeLibs版本)** 作为share枚举的补充方案:
165
-
166
- 1. **混合策略** - 保留SMBJ作为主要SMB客户端,仅使用JCIFS进行share枚举
167
- 2. **向后兼容** - 如果JCIFS枚举失败,回退到当前的测试方法
168
- 3. **最小改动** - 只需要添加一个枚举方法,不需要重写整个SMB客户端
169
-
170
- 这样既能解决share枚举问题,又能保持现有代码的稳定性。