安裝
- Add InsForge dependencies to your project
- Maven Central
- GitHub Packages
build.gradle.kts:
repositories {
mavenLocal() // For local development
mavenCentral()
}
dependencies {
implementation("dev.insforge:insforge-kotlin:0.1.6")
}
First, create a GitHub Personal Access Token:
- Go to GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic)
- Select permission:
read:packages
Option A: Environment Variables
Option A: Environment Variables
settings.gradle.kts (or build.gradle.kts):build.gradle.kts:Set environment variables before building:
repositories {
mavenCentral()
maven {
url = uri("https://maven.pkg.github.com/InsForge/insforge-kotlin")
credentials {
username = System.getenv("GITHUB_USER") ?: ""
password = System.getenv("GITHUB_TOKEN") ?: ""
}
}
}
dependencies {
implementation("dev.insforge:insforge-kotlin:0.1.6")
}
export GITHUB_USER="your-github-username"
export GITHUB_TOKEN="your-personal-access-token"
Option B: gradle.properties (Local Development)
Option B: gradle.properties (Local Development)
Add credentials to your global Gradle properties file:~/.gradle/gradle.properties:settings.gradle.kts:build.gradle.kts:
gpr.user=your-github-username
gpr.token=ghp_xxxxxxxxxxxx
repositories {
mavenCentral()
maven {
url = uri("https://maven.pkg.github.com/InsForge/insforge-kotlin")
credentials {
username = providers.gradleProperty("gpr.user").orNull ?: ""
password = providers.gradleProperty("gpr.token").orNull ?: ""
}
}
}
dependencies {
implementation("dev.insforge:insforge-kotlin:0.1.6")
}
The
~/.gradle/gradle.properties file is stored outside your project, so credentials won’t be accidentally committed to version control.- Initialize InsForge SDK
import dev.insforge.createInsforgeClient
import dev.insforge.auth.Auth
import dev.insforge.database.Database
import dev.insforge.storage.Storage
import dev.insforge.functions.Functions
import dev.insforge.realtime.Realtime
import dev.insforge.ai.AI
val client = createInsforgeClient(
baseUrl = "https://your-app.insforge.app",
anonKey = "your-api-key"
) {
install(Auth)
install(Database)
install(Storage)
install(Functions)
install(Realtime) {
autoReconnect = true
reconnectDelay = 5000
}
install(AI)
}
- Enable Logging (Optional)
import dev.insforge.InsforgeLogLevel
val client = createInsforgeClient(
baseUrl = "https://your-app.insforge.app",
anonKey = "your-api-key"
) {
// DEBUG: logs request method/URL and response status
// VERBOSE: logs full headers and request/response bodies
logLevel = InsforgeLogLevel.DEBUG
install(Auth)
install(Database)
// ... other modules
}
| Log Level | Description |
|---|---|
NONE | No logging (default, recommended for production) |
ERROR | Only errors |
WARN | Warnings and errors |
INFO | Informational messages |
DEBUG | Debug info (request method, URL, response status) |
VERBOSE | Full details (headers, request/response bodies) |
Use
NONE or ERROR in production to avoid exposing sensitive data in logs.Android Initialization
- Add Chrome Custom Tabs dependency to your
build.gradle.kts:
dependencies {
implementation("androidx.browser:browser:1.9.0")
}
- Initialize InsForge SDK (With Chrome Custom Tabs and Session Storage)
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import androidx.browser.customtabs.CustomTabsIntent
import dev.insforge.createInsforgeClient
import dev.insforge.ai.AI
import dev.insforge.auth.Auth
import dev.insforge.auth.BrowserLauncher
import dev.insforge.auth.ClientType
import dev.insforge.auth.SessionStorage
import dev.insforge.database.Database
import dev.insforge.functions.Functions
import dev.insforge.realtime.Realtime
import dev.insforge.storage.Storage
class InsforgeManager(private val context: Context) {
val client = createInsforgeClient(
baseUrl = "https://your-app.insforge.app",
anonKey = "your-anon-key"
) {
install(Auth) {
// 1. Chrome Custom Tabs - opens in-app, similar to iOS ASWebAuthenticationSession
browserLauncher = BrowserLauncher { url ->
val customTabsIntent = CustomTabsIntent.Builder()
.setShowTitle(true)
.build()
// Handle non-Activity context safely
if (context is Activity) {
customTabsIntent.launchUrl(context, Uri.parse(url))
} else {
customTabsIntent.intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
customTabsIntent.launchUrl(context, Uri.parse(url))
}
}
// 2. enable session persistence
persistSession = true
// 3. config SessionStorage (use SharedPreferences)
sessionStorage = object : SessionStorage {
private val prefs = context.getSharedPreferences(
"insforge_auth",
Context.MODE_PRIVATE
)
override suspend fun save(key: String, value: String) {
prefs.edit().putString(key, value).apply()
}
override suspend fun get(key: String): String? {
return prefs.getString(key, null)
}
override suspend fun remove(key: String) {
prefs.edit().remove(key).apply()
}
}
// 4. set client type for mobile
clientType = ClientType.MOBILE
}
// Install Database module
install(Database)
// Install Realtime module for real-time subscriptions
install(Realtime) {
debug = true
}
// Install other modules
install(Storage)
install(Functions)
install(AI)
}
}
- Use Jetpack DataStore for Session Storage (Optional)
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
val Context.authDataStore: DataStore<Preferences> by preferencesDataStore(name = "insforge_auth")
class DataStoreSessionStorage(private val context: Context) : SessionStorage {
override suspend fun save(key: String, value: String) {
context.authDataStore.edit { prefs ->
prefs[stringPreferencesKey(key)] = value
}
}
override suspend fun get(key: String): String? {
return context.authDataStore.data.map { prefs ->
prefs[stringPreferencesKey(key)]
}.first()
}
override suspend fun remove(key: String) {
context.authDataStore.edit { prefs ->
prefs.remove(stringPreferencesKey(key))
}
}
}
// Then use it in your InsForge client
install(Auth) {
browserLauncher = ...
persistSession = true
sessionStorage = DataStoreSessionStorage(context)
}
from()
取得用於檔案作業的貯體執行個體。範例
val bucket = insforge.storage.from("images")
upload()
上傳具有特定路徑/金鑰的檔案。參數
path(String) - 貯體中的檔案路徑/金鑰data(ByteArray) - 檔案內容(以位元組形式)options(DSL block, optional) - 上傳選項
UploadOptions
| 選項 | 類型 | 說明 |
|---|---|---|
contentType | String? | MIME 類型(例如 “image/jpeg”) |
upsert | Boolean | 如果檔案存在,覆寫(預設:false) |
metadata | Map\<String, String\>? | 自訂中繼資料 |
範例
// Basic upload
val imageData = bitmap.toByteArray()
val result = insforge.storage
.from("images")
.upload("posts/post-123/cover.jpg", imageData)
Log.d("Storage", "Uploaded: ${result.url}")
// Upload with options
val result = insforge.storage
.from("images")
.upload("posts/post-123/cover.jpg", imageData) {
contentType = "image/jpeg"
upsert = true // Overwrite if exists
metadata = mapOf("userId" to "123")
}
// Using bracket syntax
val result = insforge.storage["images"]
.upload("avatars/user-123.jpg", imageData) {
contentType = "image/jpeg"
}
從 Android Uri 上傳
開發者可以使用下列函式從 Android Uri 上傳檔案:// Android Uri Upload sample:
suspend fun uploadFromUri(
bucket: BucketApi,
uri: Uri,
context: Context,
path: String
): FileUploadResponse {
val data = context.contentResolver.openInputStream(uri)?.use {
it.readBytes()
} ?: throw IllegalArgumentException("Cannot read Uri")
val contentType = context.contentResolver.getType(uri)
return bucket.upload(path, data) {
this.contentType = contentType
}
}
uploadWithAutoKey()
上傳具有自動產生的唯一金鑰的檔案。參數
filename(String) - 原始檔案名稱(用於副檔名偵測)data(ByteArray) - 檔案內容(以位元組形式)options(DSL block, optional) - 上傳選項
範例
val imageData = bitmap.toByteArray()
val result = insforge.storage
.from("uploads")
.uploadWithAutoKey("photo.jpg", imageData) {
contentType = "image/jpeg"
}
Log.d("Storage", "Auto-generated key: ${result.key}")
Log.d("Storage", "URL: ${result.url}")
// Save to database
insforge.database
.from("posts")
.insertTyped(listOf(
Post(
imageUrl = result.url,
imageKey = result.key,
userId = userId
)
))
.returning()
.execute<Post>()
download()
將檔案下載為 ByteArray。範例
// Download file
val data = insforge.storage
.from("images")
.download(path = "posts/post-123/cover.jpg")
// Convert to Bitmap
val bitmap = BitmapFactory.decodeByteArray(data, 0, data.size)
imageView.setImageBitmap(bitmap)
delete()
從儲存空間中刪除檔案。範例
// Get the file key from database
val posts = insforge.database
.from("posts")
.select("image_key")
.eq("id", "post-123")
.execute<Post>() // Returns List<Post>
val post = posts.firstOrNull() ?: return
// Delete from storage
insforge.storage
.from("images")
.delete(post.imageKey)
// Clear database reference
insforge.database
.from("posts")
.update(buildJsonObject {
put("image_url", JsonNull)
put("image_key", JsonNull)
})
.eq("id", "post-123")
.execute<Post>()
createSignedUrl()
為檔案暫時存取建立簽署的 URL。參數
path(String) - 貯體中的檔案路徑expiresIn(Int) - 過期時間(以秒為單位)
範例
// Create a signed URL (expires in 1 hour)
val url = insforge.storage
.from("images")
.createSignedUrl("posts/post-123/cover.jpg", expiresIn = 3600)
Log.d("Storage", "Signed URL: $url")
getDownloadUrl()
取得檔案的下載 URL。範例
val strategy = insforge.storage
.from("images")
.getDownloadUrl("posts/post-123/cover.jpg")
Log.d("Storage", "Download URL: ${strategy.url}")
list()
列出貯體中具有選擇性篩選的檔案。BucketListFilter 選項
| 選項 | 類型 | 說明 |
|---|---|---|
prefix | String? | 按路徑首碼篩選 |
limit | Int | 最大結果數(預設:100) |
offset | Int | 分頁位移(預設:0) |
sortBy | String? | 排序欄位 |
sortOrder | SortOrder | ASC 或 DESC(預設:ASC) |
範例
// List all files in bucket
val files = insforge.storage
.from("images")
.list()
files.forEach { file ->
Log.d("Storage", "File: ${file.name}, Size: ${file.metadata?.size}")
}
// List with filters
val files = insforge.storage
.from("images")
.list {
prefix = "posts/"
limit = 50
offset = 0
sortBy = "created_at"
sortOrder = SortOrder.DESC
}
貯體管理
listBuckets()
列出所有儲存空間貯體。val buckets = insforge.storage.listBuckets()
buckets.forEach { bucket ->
Log.d("Storage", "Bucket: ${bucket.id}, Public: ${bucket.isPublic}")
}
createBucket()
建立新儲存空間貯體。val bucket = insforge.storage.createBucket("my-bucket") {
isPublic = true
}
Log.d("Storage", "Created bucket: ${bucket.id}")
updateBucket()
更新貯體設定。insforge.storage.updateBucket("my-bucket") {
isPublic = false
}
deleteBucket()
刪除儲存空間貯體。insforge.storage.deleteBucket("my-bucket")
進階上傳
getUploadStrategy()
取得用於大型檔案或可繼續上傳的上傳策略。val strategy = insforge.storage
.from("videos")
.getUploadStrategy("videos/large-file.mp4", fileSize = 100_000_000)
// Use strategy.url for upload
Log.d("Storage", "Upload URL: ${strategy.url}")
confirmUpload()
確認已完成的上傳。insforge.storage
.from("videos")
.confirmUpload("videos/large-file.mp4")