Skip to content

Commit

Permalink
feat(android): sign-in with google & magic-link & email (#9868)
Browse files Browse the repository at this point in the history
- [chore(android): migrate to version catalog](16c0fb6)
- [feat(android): integrate apollo](4dcf93b)
- [fix(android): fix android email sign-in](752cf34)
- [chore(android): add stable/canary environment](72a96bf)
- [feat(android): set cookies for apollo client](7664cc4)
- [feat(android): google & magic-link sign-in](c54ce3b)
- [eat(android): change logo](8c5062a)
- [chore(android): fix pipleline](4a68299)
- [fix(android): rebase issues](c6858c5)
- [docs(android): update README for compat with java 21](6eac3ba)
- [fix(android): android pipeline](1103c87)
  • Loading branch information
aki-chang-dev committed Feb 5, 2025
1 parent cbb73d8 commit 2607e34
Show file tree
Hide file tree
Showing 65 changed files with 2,377 additions and 278 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/release-mobile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ jobs:
- name: Build
run: |
echo -n "${{ env.AFFINE_ANDROID_SIGN_KEYSTORE }}" | base64 --decode > packages/frontend/apps/android/affine.keystore
yarn workspace @affine/android cap build android
yarn workspace @affine/android cap build android --flavor ${{ env.BUILD_TYPE }} --androidreleasetype AAB
env:
AFFINE_ANDROID_KEYSTORE_PASSWORD: ${{ secrets.AFFINE_ANDROID_KEYSTORE_PASSWORD }}
AFFINE_ANDROID_KEYSTORE_ALIAS_PASSWORD: ${{ secrets.AFFINE_ANDROID_KEYSTORE_ALIAS_PASSWORD }}
Expand All @@ -243,7 +243,7 @@ jobs:
with:
serviceAccountJson: ${{ steps.auth.outputs.credentials_file_path }}
packageName: app.affine.pro
releaseFiles: packages/frontend/apps/android/App/app/build/outputs/bundle/release/app-release-signed.aab
releaseFiles: packages/frontend/apps/android/App/app/build/outputs/bundle/${{ env.BUILD_TYPE }}Release/app-${{ env.BUILD_TYPE }}-release-signed.aab
track: internal
status: draft
existingEditId: ${{ steps.bump.outputs.EDIT_ID }}
81 changes: 50 additions & 31 deletions packages/frontend/apps/android/App/app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
plugins {
alias libs.plugins.android.application
alias libs.plugins.kotlin.android
alias libs.plugins.rust.android
}

apply from: 'capacitor.build.gradle'

android {
namespace "app.affine.pro"
namespace "app.affine.pro"
compileSdk rootProject.ext.compileSdkVersion
ndkVersion = new File(sdkDirectory, "ndk").listFiles().sort().last().name
defaultConfig {
Expand All @@ -17,20 +21,35 @@ android {
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
// Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
// Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61
ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~'
}
ndk {
abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'
}
}
buildFeatures {
buildConfig true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
flavorDimensions = ['chanel']
productFlavors {
stable {
buildConfigField 'String', 'BASE_URL', '"https://app.affine.pro"'
resValue 'string', 'host', '"app.affine.pro"'
}
canary {
buildConfigField 'String', 'BASE_URL', '"https://affine.fail"'
resValue 'string', 'host', '"affine.fail"'
}
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_21
targetCompatibility JavaVersion.VERSION_21
Expand All @@ -42,49 +61,49 @@ repositories {
dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs'
}
}

dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion"
implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion"
implementation project(':capacitor-android')
testImplementation "junit:junit:$junitVersion"
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
implementation project(':capacitor-cordova-android-plugins')
implementation "net.java.dev.jna:jna:5.16.0@aar"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.1"
implementation 'androidx.core:core-ktx:1.15.0'
implementation project(':service')
implementation libs.kotlinx.coroutines.core
implementation libs.androidx.appcompat
implementation libs.androidx.browser
implementation libs.androidx.coordinatorlayout
implementation libs.androidx.core.splashscreen
implementation libs.androidx.core.ktx
implementation libs.apollo.runtime
implementation libs.jna
testImplementation libs.junit
androidTestImplementation libs.androidx.junit
androidTestImplementation libs.androidx.espresso.core
}

try {
def servicesJSON = file('google-services.json')
if (servicesJSON.text) {
apply plugin: 'com.google.gms.google-services'
}
} catch(Exception ignored) {
} catch (Exception ignored) {
logger.info("google-services.json not found, google-services plugin not applied. Push Notifications won't work")
}

apply plugin: 'org.mozilla.rust-android-gradle.rust-android'

cargo {
module = "../../../../mobile-native"
libname = "affine_mobile_native"
targets = ["arm64"]
pythonCommand = "python3.12"
targetDirectory = "../../../../../../target"
apiLevel = 28
targetIncludes = ["libaffine_mobile_native.so"]
profile = "release"
module = "../../../../mobile-native"
libname = "affine_mobile_native"
targets = ["arm64"]
pythonCommand = "python3.12"
targetDirectory = "../../../../../../target"
apiLevel = 28
targetIncludes = ["libaffine_mobile_native.so"]
profile = "release"
}

kotlin {
compilerOptions {
apiVersion = KotlinVersion.KOTLIN_2_0
jvmTarget = JvmTarget.JVM_21
}
compilerOptions {
apiVersion = KotlinVersion.KOTLIN_2_1
jvmTarget = JvmTarget.JVM_21
}
}

afterEvaluate {
Expand All @@ -103,7 +122,7 @@ android.applicationVariants.configureEach { variant ->
def t = tasks.register("generate${variant.name.capitalize()}UniFFIBindings", Exec) {
workingDir "${project.projectDir}"
// Runs the bindings generation, note that you must have uniffi-bindgen installed and in your PATH environment variable
commandLine 'cargo', 'run', '--bin', 'uniffi-bindgen', 'generate', '--library', "${buildDir}/rustJniLibs/android/arm64-v8a/libaffine_mobile_native.so", '--language', 'kotlin', '--out-dir', "${project.projectDir}/src/main/java"
commandLine "${System.getenv("CARGO_HOME")}/bin/cargo", 'run', '--bin', 'uniffi-bindgen', 'generate', '--library', "${buildDir}/rustJniLibs/android/arm64-v8a/libaffine_mobile_native.so", '--language', 'kotlin', '--out-dir', "${project.projectDir}/src/main/java"
dependsOn("cargoBuild")
}
variant.javaCompileProvider.get().dependsOn(t)
Expand Down
7 changes: 4 additions & 3 deletions packages/frontend/apps/android/App/app/capacitor.build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
sourceCompatibility JavaVersion.VERSION_21
targetCompatibility JavaVersion.VERSION_21
}
}

apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
dependencies {

implementation project(':capacitor-app')
implementation project(':capgo-inappbrowser')

}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<queries>
<intent>
<action android:name="android.support.customtabs.action.CustomTabsService" />
</intent>
</queries>

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
Expand All @@ -22,6 +28,12 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="affine" android:host="authentication" android:pathPattern=".*"/>
</intent-filter>
</activity>

<provider
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,23 @@ package app.affine.pro

import android.os.Build
import android.os.Bundle
import android.util.Log
import androidx.annotation.RequiresApi
import com.getcapacitor.BridgeActivity
import uniffi.affine_mobile_native.hashcashMint;
import com.getcapacitor.plugin.CapacitorCookies
import com.getcapacitor.plugin.CapacitorHttp
import ee.forgr.capacitor_inappbrowser.InAppBrowserPlugin


class MainActivity : BridgeActivity() {
@RequiresApi(Build.VERSION_CODES.R)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
registerPlugins(
listOf(
CapacitorHttp::class.java,
CapacitorCookies::class.java,
InAppBrowserPlugin::class.java
)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package app.affine.pro.service

import app.affine.pro.BuildConfig
import app.affine.pro.service.interceptor.CookieInterceptor
import com.apollographql.apollo.ApolloClient
import com.apollographql.apollo.api.ApolloResponse
import com.apollographql.apollo.api.Mutation
import com.apollographql.apollo.api.Query
import com.apollographql.apollo.api.Subscription

object AffineClient {

private val _client: ApolloClient by lazy {
ApolloClient.Builder().serverUrl(BuildConfig.BASE_URL)
.addHttpInterceptor(CookieInterceptor)
.build()
}

suspend fun <D : Query.Data> query(query: Query<D>): ApolloResponse<D> {
return _client.query(query).execute()
}

suspend fun <D : Mutation.Data> mutation(mutation: Mutation<D>): ApolloResponse<D> {
return _client.mutation(mutation).execute()
}

suspend fun <D : Subscription.Data> subscription(subscription: Subscription<D>): ApolloResponse<D> {
return _client.subscription(subscription).execute()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package app.affine.pro.service.interceptor

import android.webkit.CookieManager
import app.affine.pro.BuildConfig
import com.apollographql.apollo.api.http.HttpRequest
import com.apollographql.apollo.network.http.HttpInterceptor
import com.apollographql.apollo.network.http.HttpInterceptorChain

object CookieInterceptor : HttpInterceptor {
override suspend fun intercept(
request: HttpRequest,
chain: HttpInterceptorChain
) = chain.proceed(
request.newBuilder().addHeader(
"Cookie", CookieManager.getInstance().getCookie(BuildConfig.BASE_URL)
).build()
)
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

This file was deleted.

Loading

0 comments on commit 2607e34

Please sign in to comment.