From 10708364fe4028ae7cdfba0d664d83356bf1b5f6 Mon Sep 17 00:00:00 2001 From: kapusch Date: Sat, 24 Jan 2026 10:08:25 +0100 Subject: [PATCH 1/3] feat: Add Facebook Android interop wrapper and related documentation - Introduced a new interop wrapper for Facebook Login on Android, including necessary AARs. - Created CODE_OF_CONDUCT.md and CONTRIBUTING.md for community guidelines. - Added DependencyLocks for deterministic AAR restoration. - Developed integration and source mode documentation for developers. - Implemented a sample Android application demonstrating the interop functionality. - Established a security policy for reporting vulnerabilities. - Included third-party notices for compliance with Facebook SDK licensing. - Configured build scripts and Gradle settings for Android native components. --- .editorconfig | 15 +++ .github/pull_request_template.md | 11 +++ .github/workflows/ci.yml | 59 ++++++++++++ .github/workflows/publish.yml | 82 +++++++++++++++++ .gitignore | 32 +++++++ AGENTS.md | 22 +++++ CODE_OF_CONDUCT.md | 27 ++++++ CONTRIBUTING.md | 42 +++++++++ DependencyLocks/Android/lockstate.txt | 7 ++ Docs/Integration.md | 28 ++++++ Docs/SourceMode.md | 13 +++ README.md | 50 +++++++++- SECURITY.md | 10 ++ THIRD_PARTY_NOTICES.md | 13 +++ global.json | 6 ++ .../Kapusch.Facebook.Android.Sample.csproj | 41 +++++++++ .../Properties/AndroidManifest.template.xml | 29 ++++++ .../Kapusch.Facebook.Android.Sample/README.md | 25 +++++ .../Resources/values/strings.template.xml | 8 ++ .../src/MainActivity.cs | 68 ++++++++++++++ samples/README.md | 9 ++ .../Facebook/AndroidFacebookInterop.cs | 22 +++++ .../Facebook/NativeSignInStatus.cs | 8 ++ ...ch.FacebookApisForAndroidComponents.csproj | 64 +++++++++++++ .../Native/Android/build.gradle.kts | 3 + .../Native/Android/build.sh | 48 ++++++++++ .../Android/facebookinterop/build.gradle.kts | 28 ++++++ .../facebookinterop/consumer-rules.pro | 2 + .../src/main/AndroidManifest.xml | 14 +++ .../FacebookInteropConstants.java | 13 +++ .../androidinterop/FacebookLoginActivity.java | 92 +++++++++++++++++++ .../FacebookLogoutReceiver.java | 18 ++++ .../Native/Android/gradle.properties | 3 + .../Native/Android/restore-facebook-aars.sh | 82 +++++++++++++++++ .../Native/Android/settings.gradle.kts | 2 + .../Kapusch.Facebook.Android.props | 6 ++ .../Kapusch.Facebook.Android.targets | 58 ++++++++++++ .../nuget-readme.md | 7 ++ 38 files changed, 1066 insertions(+), 1 deletion(-) create mode 100644 .editorconfig create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/publish.yml create mode 100644 .gitignore create mode 100644 AGENTS.md create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 DependencyLocks/Android/lockstate.txt create mode 100644 Docs/Integration.md create mode 100644 Docs/SourceMode.md create mode 100644 SECURITY.md create mode 100644 THIRD_PARTY_NOTICES.md create mode 100644 global.json create mode 100644 samples/Kapusch.Facebook.Android.Sample/Kapusch.Facebook.Android.Sample.csproj create mode 100644 samples/Kapusch.Facebook.Android.Sample/Properties/AndroidManifest.template.xml create mode 100644 samples/Kapusch.Facebook.Android.Sample/README.md create mode 100644 samples/Kapusch.Facebook.Android.Sample/Resources/values/strings.template.xml create mode 100644 samples/Kapusch.Facebook.Android.Sample/src/MainActivity.cs create mode 100644 samples/README.md create mode 100644 src/Kapusch.FacebookApisForAndroidComponents/Facebook/AndroidFacebookInterop.cs create mode 100644 src/Kapusch.FacebookApisForAndroidComponents/Facebook/NativeSignInStatus.cs create mode 100644 src/Kapusch.FacebookApisForAndroidComponents/Kapusch.FacebookApisForAndroidComponents.csproj create mode 100644 src/Kapusch.FacebookApisForAndroidComponents/Native/Android/build.gradle.kts create mode 100755 src/Kapusch.FacebookApisForAndroidComponents/Native/Android/build.sh create mode 100644 src/Kapusch.FacebookApisForAndroidComponents/Native/Android/facebookinterop/build.gradle.kts create mode 100644 src/Kapusch.FacebookApisForAndroidComponents/Native/Android/facebookinterop/consumer-rules.pro create mode 100644 src/Kapusch.FacebookApisForAndroidComponents/Native/Android/facebookinterop/src/main/AndroidManifest.xml create mode 100644 src/Kapusch.FacebookApisForAndroidComponents/Native/Android/facebookinterop/src/main/java/com/kapusch/facebook/androidinterop/FacebookInteropConstants.java create mode 100644 src/Kapusch.FacebookApisForAndroidComponents/Native/Android/facebookinterop/src/main/java/com/kapusch/facebook/androidinterop/FacebookLoginActivity.java create mode 100644 src/Kapusch.FacebookApisForAndroidComponents/Native/Android/facebookinterop/src/main/java/com/kapusch/facebook/androidinterop/FacebookLogoutReceiver.java create mode 100644 src/Kapusch.FacebookApisForAndroidComponents/Native/Android/gradle.properties create mode 100755 src/Kapusch.FacebookApisForAndroidComponents/Native/Android/restore-facebook-aars.sh create mode 100644 src/Kapusch.FacebookApisForAndroidComponents/Native/Android/settings.gradle.kts create mode 100644 src/Kapusch.FacebookApisForAndroidComponents/buildTransitive/Kapusch.Facebook.Android.props create mode 100644 src/Kapusch.FacebookApisForAndroidComponents/buildTransitive/Kapusch.Facebook.Android.targets create mode 100644 src/Kapusch.FacebookApisForAndroidComponents/nuget-readme.md diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..603c143 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.cs] +indent_style = tab +indent_size = 4 + +[*.{yml,yaml,json,md,sh,gradle,kts,xml}] +indent_style = space +indent_size = 2 diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..cc9d28f --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,11 @@ +## Summary + +- What does this change do? + +## Checklist + +- [ ] No secrets committed +- [ ] Built wrapper: `bash src/Kapusch.FacebookApisForAndroidComponents/Native/Android/build.sh` +- [ ] Restored pinned AARs: `bash src/Kapusch.FacebookApisForAndroidComponents/Native/Android/restore-facebook-aars.sh` +- [ ] Packed NuGet: `dotnet pack src/Kapusch.FacebookApisForAndroidComponents/Kapusch.FacebookApisForAndroidComponents.csproj -c Release -o artifacts/nuget` +- [ ] Updated docs if behavior/integration changed diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..3d2328c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,59 @@ +name: ci + +on: + pull_request: + workflow_dispatch: + +permissions: + contents: read + +jobs: + build_pack_android: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-dotnet@v4 + with: + dotnet-version: "10.0.x" + + - uses: actions/setup-java@v4 + with: + distribution: "microsoft" + java-version: "21" + + - name: Setup Android SDK + uses: android-actions/setup-android@v3 + + - name: Install Android workload + run: | + dotnet workload install android + + - name: Cache NuGet + uses: actions/cache@v4 + with: + path: ~/.nuget/packages + key: ${{ runner.os }}-nuget-${{ hashFiles('global.json', '**/*.csproj') }} + + - name: Build Android wrapper + run: | + bash src/Kapusch.FacebookApisForAndroidComponents/Native/Android/build.sh + + - name: Restore pinned Facebook AARs + run: | + bash src/Kapusch.FacebookApisForAndroidComponents/Native/Android/restore-facebook-aars.sh + + - name: Pack + run: | + dotnet pack src/Kapusch.FacebookApisForAndroidComponents/Kapusch.FacebookApisForAndroidComponents.csproj \ + -c Release \ + -o artifacts/nuget + + - name: Build Android sample + run: | + dotnet build samples/Kapusch.Facebook.Android.Sample/Kapusch.Facebook.Android.Sample.csproj -c Debug + + - uses: actions/upload-artifact@v4 + with: + name: nuget + path: artifacts/nuget/*.nupkg diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..1b02c20 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,82 @@ +name: publish + +on: + workflow_dispatch: + push: + tags: + - "v*" + +permissions: + contents: read + packages: write + +jobs: + pack_and_publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Determine package version + id: version + shell: bash + run: | + if [[ "${{ github.ref }}" =~ ^refs/tags/v ]]; then + REF="${{ github.ref }}" + VERSION="${REF#refs/tags/v}" + else + CSPROJ="src/Kapusch.FacebookApisForAndroidComponents/Kapusch.FacebookApisForAndroidComponents.csproj" + BASE_VERSION=$(grep -oE '[^<]+' "$CSPROJ" | head -n 1 | sed 's///' || echo "0.1.0") + COMMIT_SHORT=$(git rev-parse --short HEAD) + RUN_NUMBER="${{ github.run_number }}" + VERSION="${BASE_VERSION}-prerelease.${RUN_NUMBER}.${COMMIT_SHORT}" + fi + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + echo "Package version: ${VERSION}" + + - uses: actions/setup-dotnet@v4 + with: + dotnet-version: "10.0.x" + + - uses: actions/setup-java@v4 + with: + distribution: "microsoft" + java-version: "21" + + - name: Setup Android SDK + uses: android-actions/setup-android@v3 + + - name: Install Android workload + run: | + dotnet workload install android + + - name: Cache NuGet + uses: actions/cache@v4 + with: + path: ~/.nuget/packages + key: ${{ runner.os }}-nuget-${{ hashFiles('global.json', '**/*.csproj') }} + + - name: Build Android wrapper + run: | + bash src/Kapusch.FacebookApisForAndroidComponents/Native/Android/build.sh + + - name: Restore pinned Facebook AARs + run: | + bash src/Kapusch.FacebookApisForAndroidComponents/Native/Android/restore-facebook-aars.sh + + - name: Pack + run: | + dotnet pack src/Kapusch.FacebookApisForAndroidComponents/Kapusch.FacebookApisForAndroidComponents.csproj \ + -c Release \ + -o artifacts/nuget \ + /p:PackageVersion="${{ steps.version.outputs.version }}" + + - name: Push to GitHub Packages + env: + NUGET_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + dotnet nuget push artifacts/nuget/*.nupkg \ + --api-key "$NUGET_AUTH_TOKEN" \ + --source "https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json" \ + --skip-duplicate diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..798093f --- /dev/null +++ b/.gitignore @@ -0,0 +1,32 @@ +# .NET +bin/ +obj/ +*.user +*.suo +*.userosscache +*.sln.docstates + +# NuGet +*.nupkg +*.snupkg +artifacts/ + +# macOS +.DS_Store + +# Gradle / Android +.gradle/ +**/.gradle/ +local.properties +**/local.properties +**/build/ + +# Local caches used by restore +.kapusch/ + +# Native build output (repo-only) +src/**/Native/Android/build/ + +# Sample local config +samples/**/google-services.json +samples/**/secrets.* diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..9aaa645 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,22 @@ +# Kapusch.FacebookApisForAndroidComponents — AI Working Agreement + +## Goals +- Produce a reproducible Android NuGet package for Facebook Login interop. +- Do not commit secrets. + +## Packaging constraints +- Public OSS repo: keep docs/sample generic and not app-specific. +- The NuGet ships the required `.aar` artifacts and injects them into consuming apps via `buildTransitive` `AndroidAarLibrary`. +- Consuming apps must not download native deps at build time. +- This repo may download dependencies during CI/build, but consuming apps must not. + +## Repo layout +- `src/Kapusch.FacebookApisForAndroidComponents/` — NuGet project (managed API + buildTransitive MSBuild) +- `src/Kapusch.FacebookApisForAndroidComponents/Native/Android/` — Gradle wrapper library + scripts (repo-only) +- `DependencyLocks/` — pinned third-party artifacts (URLs + SHA256) +- `Docs/` — integration docs +- `samples/` — optional sample template (no secrets committed) + +## Safety +- Do not add new dependency ingestion paths without documenting them in `README.md`. +- Do not commit real app ids/secrets. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..462c8cd --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,27 @@ +# Code of Conduct + +## Our Pledge + +We pledge to make participation in this project and our community a harassment-free experience for everyone. + +## Our Standards + +Examples of behavior that contributes to a positive environment include: +- Being respectful and considerate in language and actions +- Giving and gracefully accepting constructive feedback +- Focusing on what is best for the community + +Examples of unacceptable behavior include: +- Harassment, discrimination, or hateful conduct +- Trolling, insulting or derogatory comments, and personal or political attacks +- Publishing others’ private information without explicit permission + +## Enforcement + +Project maintainers are responsible for clarifying and enforcing standards. + +To report a Code of Conduct issue, contact the project maintainers. + +## Attribution + +This document is based on the Contributor Covenant. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..49ec310 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,42 @@ +# Contributing + +Thanks for contributing! + +## Prerequisites + +- JDK 21 +- Android SDK installed (set `ANDROID_SDK_ROOT` or `ANDROID_HOME`) +- .NET SDK 10 (this repo pins `10.0.100` via `global.json`) + +## Local build + +If you are working without the NuGet (ProjectReference), see `Docs/SourceMode.md`. + +Build the Android wrapper AAR: + +- `bash src/Kapusch.FacebookApisForAndroidComponents/Native/Android/build.sh` + +Restore pinned Facebook AARs: + +- `bash src/Kapusch.FacebookApisForAndroidComponents/Native/Android/restore-facebook-aars.sh` + +Pack the NuGet: + +- `dotnet pack src/Kapusch.FacebookApisForAndroidComponents/Kapusch.FacebookApisForAndroidComponents.csproj -c Release -o artifacts/nuget` + +## Formatting + +- C#: follow `.editorconfig` (tabs, LF). +- Java/Kotlin/Gradle: keep changes minimal and consistent with existing style. + +## Pull requests + +- Keep PRs focused and well-scoped. +- Do not commit secrets. +- If you update the Facebook SDK version, update both: + - `src/Kapusch.FacebookApisForAndroidComponents/Native/Android/facebookinterop/build.gradle.kts` + - `DependencyLocks/Android/lockstate.txt` (URLs + SHA256) + +## License + +By contributing, you agree that your contributions will be licensed under the repository license (MIT). diff --git a/DependencyLocks/Android/lockstate.txt b/DependencyLocks/Android/lockstate.txt new file mode 100644 index 0000000..a9b1e48 --- /dev/null +++ b/DependencyLocks/Android/lockstate.txt @@ -0,0 +1,7 @@ +# Pinned Android artifacts for deterministic restore. +# Format: + +https://repo1.maven.org/maven2/com/facebook/android/facebook-login/18.1.3/facebook-login-18.1.3.aar 30a0bb79b74244228c63101c26353ad61a973e156ca55b712b59fe56fc952100 facebook-login-18.1.3.aar +https://repo1.maven.org/maven2/com/facebook/android/facebook-core/18.1.3/facebook-core-18.1.3.aar ef480916149e078f955195981130b05746ca33b41618911e7093aa32c03d601b facebook-core-18.1.3.aar +https://repo1.maven.org/maven2/com/facebook/android/facebook-common/18.1.3/facebook-common-18.1.3.aar 62adfb1cd05184065d69033a9f917709b392004f87a8aa1cc1c4f0e9fb5ca781 facebook-common-18.1.3.aar +https://repo1.maven.org/maven2/com/facebook/android/facebook-bolts/18.1.3/facebook-bolts-18.1.3.aar 05c6bae0130487e63add05854a3bbd21465c06a295a2104b3948d8759536b699 facebook-bolts-18.1.3.aar diff --git a/Docs/Integration.md b/Docs/Integration.md new file mode 100644 index 0000000..743fe34 --- /dev/null +++ b/Docs/Integration.md @@ -0,0 +1,28 @@ +# Integration (Android) + +This package injects a small Android Activity (provided by an embedded AAR) that runs the Facebook Login flow and returns its result via `Intent` extras. + +## Required AndroidManifest entries + +You must include the required Meta/Facebook Android SDK entries in your app manifest (example only; use resources, do not hardcode secrets): + +- `com.facebook.sdk.ApplicationId` +- `com.facebook.sdk.ClientToken` + +You also need to declare `com.facebook.FacebookActivity` and `com.facebook.CustomTabActivity` as per Facebook SDK documentation. + +## Launching the flow + +From your app, start the interop Activity: +- `AndroidFacebookInterop.LoginActivityClassName` + +Then parse the `Intent` extras: +- `AndroidFacebookInterop.ExtraStatus` +- `AndroidFacebookInterop.ExtraAccessToken` +- `AndroidFacebookInterop.ExtraUserId` +- `AndroidFacebookInterop.ExtraErrorCode` +- `AndroidFacebookInterop.ExtraErrorMessage` + +## Sign-out + +Call `AndroidFacebookInterop.SendSignOutBroadcast(context)`. diff --git a/Docs/SourceMode.md b/Docs/SourceMode.md new file mode 100644 index 0000000..06fecc4 --- /dev/null +++ b/Docs/SourceMode.md @@ -0,0 +1,13 @@ +# Source mode + +For local development, you can reference the project directly and inject the native AARs from the repo build output. + +## Steps + +1. Build native assets: + - `bash src/Kapusch.FacebookApisForAndroidComponents/Native/Android/build.sh` + - `bash src/Kapusch.FacebookApisForAndroidComponents/Native/Android/restore-facebook-aars.sh` +2. Reference `src/Kapusch.FacebookApisForAndroidComponents/Kapusch.FacebookApisForAndroidComponents.csproj` from your app. +3. Import the build targets: + - `src/Kapusch.FacebookApisForAndroidComponents/buildTransitive/Kapusch.Facebook.Android.targets` +4. Set `UseKapuschFacebookAndroidInteropFromSource=true` in your app project. diff --git a/README.md b/README.md index d56a6ca..410bb98 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,50 @@ # FacebookApisForAndroidComponents -Facebook Android native bindings packaging, integration docs and sample + +Public OSS repository that packages **Facebook Login for Android** into a consumable .NET NuGet. + +## Package + +- NuGet ID: `Kapusch.Facebook.Android` + +## What this repo ships + +A NuGet package that: +- provides a small managed API for starting a Facebook Login flow on Android, and +- redistributes the required **Facebook Android SDK AARs** inside the `.nupkg` (classic/native packaging), +- injects the AARs into consuming apps via `buildTransitive` `AndroidAarLibrary` items. + +## Third-party licenses + +See `THIRD_PARTY_NOTICES.md`. + +## Developer docs + +- Integration: `Docs/Integration.md` +- Source mode: `Docs/SourceMode.md` +- Samples: `samples/README.md` + +## Build (local) + +Prereqs: +- JDK 21 +- Android SDK installed (set `ANDROID_SDK_ROOT` or `ANDROID_HOME`) +- .NET SDK 10 (`global.json` pins 10.0.100) + +Build the native wrapper (repo-only): +- `bash src/Kapusch.FacebookApisForAndroidComponents/Native/Android/build.sh` + +Restore pinned Facebook AARs (repo-only): +- `bash src/Kapusch.FacebookApisForAndroidComponents/Native/Android/restore-facebook-aars.sh` + +Pack the NuGet: +- `dotnet pack src/Kapusch.FacebookApisForAndroidComponents/Kapusch.FacebookApisForAndroidComponents.csproj -c Release -o artifacts/nuget` + +## Consumption + +- Install the package from GitHub Packages (pre-release). +- Follow `Docs/Integration.md` for required AndroidManifest entries / meta-data. + +## CI + +- PR CI is build-only. +- Publishing is handled by a workflow that pushes a pre-release to GitHub Packages. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..07af9a0 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,10 @@ +# Security Policy + +## Reporting a Vulnerability + +Please do not open public issues for security reports. + +Instead, use GitHub Security Advisories for this repository: +- Go to the repository page → **Security** → **Advisories** → **Report a vulnerability**. + +We will acknowledge receipt and work on a fix. diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md new file mode 100644 index 0000000..e4b5cca --- /dev/null +++ b/THIRD_PARTY_NOTICES.md @@ -0,0 +1,13 @@ +# Third-Party Notices + +This repository and its NuGet package (`Kapusch.Facebook.Android`) redistribute third-party binaries. + +## Facebook Android SDK + +- Upstream: facebook-android-sdk +- Source: https://github.com/facebook/facebook-android-sdk + +The NuGet package includes pinned Facebook SDK `.aar` files under `android/deps/`. +The exact pinned artifacts (URLs + SHA256) are tracked in `DependencyLocks/Android/lockstate.txt`. + +If you are redistributing this package further, ensure you comply with the upstream license terms. diff --git a/global.json b/global.json new file mode 100644 index 0000000..512142d --- /dev/null +++ b/global.json @@ -0,0 +1,6 @@ +{ + "sdk": { + "version": "10.0.100", + "rollForward": "latestFeature" + } +} diff --git a/samples/Kapusch.Facebook.Android.Sample/Kapusch.Facebook.Android.Sample.csproj b/samples/Kapusch.Facebook.Android.Sample/Kapusch.Facebook.Android.Sample.csproj new file mode 100644 index 0000000..5334799 --- /dev/null +++ b/samples/Kapusch.Facebook.Android.Sample/Kapusch.Facebook.Android.Sample.csproj @@ -0,0 +1,41 @@ + + + net10.0-android + Exe + enable + enable + 21 + com.kapusch.facebookandroid.sample + Kapusch Facebook Android Sample + true + + + <_SampleManifest>$(MSBuildThisFileDirectory)Properties/AndroidManifest.xml + <_SampleManifestTemplate>$(MSBuildThisFileDirectory)Properties/AndroidManifest.template.xml + + + + + + <_SampleStrings>$(MSBuildThisFileDirectory)Resources/values/strings.xml + <_SampleStringsTemplate>$(MSBuildThisFileDirectory)Resources/values/strings.template.xml + + + + + + + + + diff --git a/samples/Kapusch.Facebook.Android.Sample/Properties/AndroidManifest.template.xml b/samples/Kapusch.Facebook.Android.Sample/Properties/AndroidManifest.template.xml new file mode 100644 index 0000000..25e92f7 --- /dev/null +++ b/samples/Kapusch.Facebook.Android.Sample/Properties/AndroidManifest.template.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + diff --git a/samples/Kapusch.Facebook.Android.Sample/README.md b/samples/Kapusch.Facebook.Android.Sample/README.md new file mode 100644 index 0000000..15e097b --- /dev/null +++ b/samples/Kapusch.Facebook.Android.Sample/README.md @@ -0,0 +1,25 @@ +# Kapusch.Facebook.Android.Sample + +Small, buildable Android sample project for validating: +- Managed API compilation +- Native asset injection via `AndroidAarLibrary` (wrapper + Facebook AARs) + +No secrets are committed. + +## Build (local) + +Prereqs: +- JDK 21 +- Android SDK (`ANDROID_SDK_ROOT` or `ANDROID_HOME`) +- .NET SDK 10 (`global.json` pins 10.0.100) + +Build native assets (repo-only): +```bash +bash src/Kapusch.FacebookApisForAndroidComponents/Native/Android/build.sh +bash src/Kapusch.FacebookApisForAndroidComponents/Native/Android/restore-facebook-aars.sh +``` + +Build the sample: +```bash +dotnet build samples/Kapusch.Facebook.Android.Sample/Kapusch.Facebook.Android.Sample.csproj -c Debug +``` diff --git a/samples/Kapusch.Facebook.Android.Sample/Resources/values/strings.template.xml b/samples/Kapusch.Facebook.Android.Sample/Resources/values/strings.template.xml new file mode 100644 index 0000000..2eb875e --- /dev/null +++ b/samples/Kapusch.Facebook.Android.Sample/Resources/values/strings.template.xml @@ -0,0 +1,8 @@ + + + Kapusch Facebook Android Sample + + 000000000000000 + 00000000000000000000000000000000 + fb000000000000000 + diff --git a/samples/Kapusch.Facebook.Android.Sample/src/MainActivity.cs b/samples/Kapusch.Facebook.Android.Sample/src/MainActivity.cs new file mode 100644 index 0000000..da32b0a --- /dev/null +++ b/samples/Kapusch.Facebook.Android.Sample/src/MainActivity.cs @@ -0,0 +1,68 @@ +using Android.App; +using Android.Content; +using Android.OS; +using Android.Widget; +using Kapusch.Facebook.Android; + +namespace Kapusch.Facebook.Android.Sample; + +[Activity(Label = "Kapusch Facebook Android Sample", MainLauncher = true)] +public sealed class MainActivity : Activity +{ + private const int LoginRequestCode = 4242; + + protected override void OnCreate(Bundle? savedInstanceState) + { + base.OnCreate(savedInstanceState); + + var button = new Button(this) { Text = "Start Facebook Login" }; + button.Click += (_, _) => + { + var intent = new Intent(); + intent.SetClassName(PackageName, AndroidFacebookInterop.LoginActivityClassName); + StartActivityForResult(intent, LoginRequestCode); + }; + + SetContentView(button); + } + + protected override void OnActivityResult(int requestCode, Result resultCode, Intent? data) + { + base.OnActivityResult(requestCode, resultCode, data); + + if (requestCode != LoginRequestCode) + return; + + var hasData = data is not null; + var status = hasData + ? (NativeSignInStatus) + data!.GetIntExtra( + AndroidFacebookInterop.ExtraStatus, + (int)NativeSignInStatus.Cancelled + ) + : NativeSignInStatus.Cancelled; + + if (!hasData) + { + Toast.MakeText(this, "No result data", ToastLength.Short)?.Show(); + return; + } + + switch (status) + { + case NativeSignInStatus.Success: + var token = data!.GetStringExtra(AndroidFacebookInterop.ExtraAccessToken); + Toast + .MakeText(this, $"Success (token len: {token?.Length ?? 0})", ToastLength.Short) + ?.Show(); + break; + case NativeSignInStatus.Cancelled: + Toast.MakeText(this, "Cancelled", ToastLength.Short)?.Show(); + break; + case NativeSignInStatus.Failed: + var error = data!.GetStringExtra(AndroidFacebookInterop.ExtraErrorMessage); + Toast.MakeText(this, $"Failed: {error}", ToastLength.Short)?.Show(); + break; + } + } +} diff --git a/samples/README.md b/samples/README.md new file mode 100644 index 0000000..7c0faed --- /dev/null +++ b/samples/README.md @@ -0,0 +1,9 @@ +# Samples + +Principles: +- No secrets committed. +- Keep values in local-only files (generated from templates). + +## Android + +- `samples/Kapusch.Facebook.Android.Sample/` — minimal Android sample that links against the wrapper AAR + Facebook AARs. diff --git a/src/Kapusch.FacebookApisForAndroidComponents/Facebook/AndroidFacebookInterop.cs b/src/Kapusch.FacebookApisForAndroidComponents/Facebook/AndroidFacebookInterop.cs new file mode 100644 index 0000000..14cfe30 --- /dev/null +++ b/src/Kapusch.FacebookApisForAndroidComponents/Facebook/AndroidFacebookInterop.cs @@ -0,0 +1,22 @@ +using Android.Content; + +namespace Kapusch.Facebook.Android; + +public static class AndroidFacebookInterop +{ + public static string LoginActivityClassName => "com.kapusch.facebook.androidinterop.FacebookLoginActivity"; + + public static string ExtraStatus => "kfb_status"; + public static string ExtraAccessToken => "kfb_access_token"; + public static string ExtraUserId => "kfb_user_id"; + public static string ExtraErrorCode => "kfb_error_code"; + public static string ExtraErrorMessage => "kfb_error_message"; + + public static string LogoutAction => "com.kapusch.facebook.androidinterop.LOGOUT"; + + public static void SendSignOutBroadcast(Context context) + { + var intent = new Intent(LogoutAction); + context.SendBroadcast(intent); + } +} diff --git a/src/Kapusch.FacebookApisForAndroidComponents/Facebook/NativeSignInStatus.cs b/src/Kapusch.FacebookApisForAndroidComponents/Facebook/NativeSignInStatus.cs new file mode 100644 index 0000000..973649e --- /dev/null +++ b/src/Kapusch.FacebookApisForAndroidComponents/Facebook/NativeSignInStatus.cs @@ -0,0 +1,8 @@ +namespace Kapusch.Facebook.Android; + +public enum NativeSignInStatus +{ + Success = 0, + Cancelled = 1, + Failed = 2, +} diff --git a/src/Kapusch.FacebookApisForAndroidComponents/Kapusch.FacebookApisForAndroidComponents.csproj b/src/Kapusch.FacebookApisForAndroidComponents/Kapusch.FacebookApisForAndroidComponents.csproj new file mode 100644 index 0000000..b7c10f3 --- /dev/null +++ b/src/Kapusch.FacebookApisForAndroidComponents/Kapusch.FacebookApisForAndroidComponents.csproj @@ -0,0 +1,64 @@ + + + net10.0-android + enable + enable + $(DefaultItemExcludes);Native/** + Kapusch.Facebook.Android + Kapusch + Facebook Android auth interop wrapper + classic AAR packaging. + MIT + https://github.com/Kapusch/FacebookApisForAndroidComponents + true + true + false + $(NoWarn);NU5128 + Kapusch.Facebook.Android + Kapusch.Facebook.Android + 0.1.0 + nuget-readme.md + Native/Android/build/aar/kfb-facebookinterop-release.aar + Native/Android/build/deps + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/build.gradle.kts b/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/build.gradle.kts new file mode 100644 index 0000000..c97b4bf --- /dev/null +++ b/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("com.android.library") version "8.3.2" apply false +} diff --git a/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/build.sh b/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/build.sh new file mode 100755 index 0000000..d251561 --- /dev/null +++ b/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/build.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +BUILD_DIR="$ROOT_DIR/build" + +GRADLE_VERSION="8.7" +GRADLE_HOME="$ROOT_DIR/.gradle/gradle-$GRADLE_VERSION" +GRADLE_BIN="$GRADLE_HOME/bin/gradle" +GRADLE_USER_HOME="${GRADLE_USER_HOME:-$ROOT_DIR/.gradle/user-home}" +export GRADLE_USER_HOME + +ANDROID_SDK="${ANDROID_SDK_ROOT:-${ANDROID_HOME:-}}" +if [ -z "$ANDROID_SDK" ]; then + DEFAULT_MACOS_SDK="$HOME/Library/Android/sdk" + DEFAULT_LINUX_SDK="$HOME/Android/Sdk" + + if [ -d "$DEFAULT_MACOS_SDK" ]; then + ANDROID_SDK="$DEFAULT_MACOS_SDK" + elif [ -d "$DEFAULT_LINUX_SDK" ]; then + ANDROID_SDK="$DEFAULT_LINUX_SDK" + else + echo "ANDROID_SDK_ROOT (or ANDROID_HOME) is required to build Android native interop." >&2 + exit 1 + fi +fi + +mkdir -p "$ROOT_DIR/.gradle" "$GRADLE_USER_HOME" +cat > "$ROOT_DIR/local.properties" < + + + + + + + + + diff --git a/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/facebookinterop/src/main/java/com/kapusch/facebook/androidinterop/FacebookInteropConstants.java b/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/facebookinterop/src/main/java/com/kapusch/facebook/androidinterop/FacebookInteropConstants.java new file mode 100644 index 0000000..332e6f6 --- /dev/null +++ b/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/facebookinterop/src/main/java/com/kapusch/facebook/androidinterop/FacebookInteropConstants.java @@ -0,0 +1,13 @@ +package com.kapusch.facebook.androidinterop; + +public final class FacebookInteropConstants { + public static final String EXTRA_STATUS = "kfb_status"; + public static final String EXTRA_ACCESS_TOKEN = "kfb_access_token"; + public static final String EXTRA_USER_ID = "kfb_user_id"; + public static final String EXTRA_ERROR_CODE = "kfb_error_code"; + public static final String EXTRA_ERROR_MESSAGE = "kfb_error_message"; + + public static final String LOGOUT_ACTION = "com.kapusch.facebook.androidinterop.LOGOUT"; + + private FacebookInteropConstants() {} +} diff --git a/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/facebookinterop/src/main/java/com/kapusch/facebook/androidinterop/FacebookLoginActivity.java b/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/facebookinterop/src/main/java/com/kapusch/facebook/androidinterop/FacebookLoginActivity.java new file mode 100644 index 0000000..10833f0 --- /dev/null +++ b/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/facebookinterop/src/main/java/com/kapusch/facebook/androidinterop/FacebookLoginActivity.java @@ -0,0 +1,92 @@ +package com.kapusch.facebook.androidinterop; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; + +import com.facebook.FacebookCallback; +import com.facebook.FacebookException; +import com.facebook.login.LoginManager; +import com.facebook.login.LoginResult; + +import com.facebook.CallbackManager; + +import java.util.Arrays; + +public final class FacebookLoginActivity extends Activity { + private static final int STATUS_SUCCESS = 0; + private static final int STATUS_CANCELLED = 1; + private static final int STATUS_FAILED = 2; + + private CallbackManager callbackManager; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + callbackManager = CallbackManager.Factory.create(); + + LoginManager loginManager = LoginManager.getInstance(); + loginManager.registerCallback(callbackManager, new FacebookCallback() { + @Override + public void onSuccess(LoginResult loginResult) { + String accessToken = loginResult.getAccessToken() != null ? loginResult.getAccessToken().getToken() : null; + String userId = loginResult.getAccessToken() != null ? loginResult.getAccessToken().getUserId() : null; + + if (accessToken == null || accessToken.isEmpty()) { + completeFailed("missing_access_token", "Facebook access token is missing."); + return; + } + + Intent data = new Intent(); + data.putExtra(FacebookInteropConstants.EXTRA_STATUS, STATUS_SUCCESS); + data.putExtra(FacebookInteropConstants.EXTRA_ACCESS_TOKEN, accessToken); + data.putExtra(FacebookInteropConstants.EXTRA_USER_ID, userId); + setResult(RESULT_OK, data); + finish(); + } + + @Override + public void onCancel() { + Intent data = new Intent(); + data.putExtra(FacebookInteropConstants.EXTRA_STATUS, STATUS_CANCELLED); + setResult(RESULT_CANCELED, data); + finish(); + } + + @Override + public void onError(FacebookException error) { + completeFailed(error.getClass().getSimpleName(), error.getMessage()); + } + + private void completeFailed(String errorCode, String errorMessage) { + Intent data = new Intent(); + data.putExtra(FacebookInteropConstants.EXTRA_STATUS, STATUS_FAILED); + data.putExtra(FacebookInteropConstants.EXTRA_ERROR_CODE, errorCode); + data.putExtra(FacebookInteropConstants.EXTRA_ERROR_MESSAGE, errorMessage); + setResult(RESULT_OK, data); + finish(); + } + }); + + try { + loginManager.logInWithReadPermissions(this, Arrays.asList("public_profile", "email")); + } catch (Exception ex) { + Intent data = new Intent(); + data.putExtra(FacebookInteropConstants.EXTRA_STATUS, STATUS_FAILED); + data.putExtra(FacebookInteropConstants.EXTRA_ERROR_CODE, ex.getClass().getSimpleName()); + data.putExtra(FacebookInteropConstants.EXTRA_ERROR_MESSAGE, ex.getMessage()); + setResult(RESULT_OK, data); + finish(); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + if (callbackManager != null) { + callbackManager.onActivityResult(requestCode, resultCode, data); + } + } +} diff --git a/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/facebookinterop/src/main/java/com/kapusch/facebook/androidinterop/FacebookLogoutReceiver.java b/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/facebookinterop/src/main/java/com/kapusch/facebook/androidinterop/FacebookLogoutReceiver.java new file mode 100644 index 0000000..323f8b1 --- /dev/null +++ b/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/facebookinterop/src/main/java/com/kapusch/facebook/androidinterop/FacebookLogoutReceiver.java @@ -0,0 +1,18 @@ +package com.kapusch.facebook.androidinterop; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import com.facebook.login.LoginManager; + +public final class FacebookLogoutReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + try { + LoginManager.getInstance().logOut(); + } catch (Exception ignored) { + // Best-effort only. + } + } +} diff --git a/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/gradle.properties b/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/gradle.properties new file mode 100644 index 0000000..18825f9 --- /dev/null +++ b/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx2g -Dfile.encoding=UTF-8 +android.useAndroidX=true +android.nonTransitiveRClass=true diff --git a/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/restore-facebook-aars.sh b/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/restore-facebook-aars.sh new file mode 100755 index 0000000..c4e38d3 --- /dev/null +++ b/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/restore-facebook-aars.sh @@ -0,0 +1,82 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$ROOT_DIR/../../../.." && pwd)" +LOCK_FILE="$REPO_ROOT/DependencyLocks/Android/lockstate.txt" +DEPS_OUT="$ROOT_DIR/build/deps" + +mkdir -p "$DEPS_OUT" + +if [ ! -f "$LOCK_FILE" ]; then + echo "Missing lockstate.txt (expected at $LOCK_FILE)." >&2 + exit 1 +fi + +sha256_file() { + local file="$1" + if command -v shasum >/dev/null 2>&1; then + shasum -a 256 "$file" | awk '{print $1}' + return 0 + fi + if command -v sha256sum >/dev/null 2>&1; then + sha256sum "$file" | awk '{print $1}' + return 0 + fi + echo "No SHA-256 tool found (need shasum or sha256sum)." >&2 + return 1 +} + +echo "[KapuschFacebookInteropAndroid] Restoring pinned dependencies from lock file..." + +tmp_dir="$(mktemp -d)" +cleanup() { rm -rf "$tmp_dir"; } +trap cleanup EXIT + +downloaded_any=false + +while IFS= read -r line || [ -n "$line" ]; do + case "$line" in + ''|'#'*) continue ;; + esac + + url="$(echo "$line" | awk '{print $1}')" + expected_sha="$(echo "$line" | awk '{print $2}')" + filename="$(echo "$line" | awk '{print $3}')" + + if [ -z "$url" ] || [ -z "$expected_sha" ] || [ -z "$filename" ]; then + echo "Invalid lock line (expected: ): $line" >&2 + exit 1 + fi + + out_path="$DEPS_OUT/$filename" + tmp_path="$tmp_dir/$filename" + + echo "[KapuschFacebookInteropAndroid] Downloading $filename" + curl -fsSL --retry 3 --retry-delay 1 -o "$tmp_path" "$url" + + actual_sha="$(sha256_file "$tmp_path")" + if [ "$actual_sha" != "$expected_sha" ]; then + echo "SHA256 mismatch for $filename" >&2 + echo "Expected: $expected_sha" >&2 + echo "Actual: $actual_sha" >&2 + exit 1 + fi + + mv -f "$tmp_path" "$out_path" + downloaded_any=true + +done < "$LOCK_FILE" + +if [ "$downloaded_any" != true ]; then + echo "No artifacts restored (lock file empty?)." >&2 + exit 1 +fi + +if ls "$DEPS_OUT"/facebook-*.aar >/dev/null 2>&1; then + echo "[KapuschFacebookInteropAndroid] Done: $DEPS_OUT" + exit 0 +fi + +echo "Restored artifacts did not include any facebook-*.aar. Check lock file contents." >&2 +exit 1 diff --git a/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/settings.gradle.kts b/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/settings.gradle.kts new file mode 100644 index 0000000..2944bbc --- /dev/null +++ b/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/settings.gradle.kts @@ -0,0 +1,2 @@ +rootProject.name = "KapuschFacebookInteropAndroid" +include(":facebookinterop") diff --git a/src/Kapusch.FacebookApisForAndroidComponents/buildTransitive/Kapusch.Facebook.Android.props b/src/Kapusch.FacebookApisForAndroidComponents/buildTransitive/Kapusch.Facebook.Android.props new file mode 100644 index 0000000..07fe0e9 --- /dev/null +++ b/src/Kapusch.FacebookApisForAndroidComponents/buildTransitive/Kapusch.Facebook.Android.props @@ -0,0 +1,6 @@ + + + false + false + + diff --git a/src/Kapusch.FacebookApisForAndroidComponents/buildTransitive/Kapusch.Facebook.Android.targets b/src/Kapusch.FacebookApisForAndroidComponents/buildTransitive/Kapusch.Facebook.Android.targets new file mode 100644 index 0000000..a90f887 --- /dev/null +++ b/src/Kapusch.FacebookApisForAndroidComponents/buildTransitive/Kapusch.Facebook.Android.targets @@ -0,0 +1,58 @@ + + + <_KapuschFacebookAndroidPackageRoot>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..')) + + + + <_KapuschFacebookAndroidSourceRoot>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)../Native/Android/build')) + + + + + <_KapuschFacebookAndroidWrapperAar>$([System.IO.Path]::Combine('$(_KapuschFacebookAndroidSourceRoot)', 'aar', 'kfb-facebookinterop-release.aar')) + <_KapuschFacebookAndroidDepsDir>$([System.IO.Path]::Combine('$(_KapuschFacebookAndroidSourceRoot)', 'deps')) + + + + + + + + + + + + + + + + + + <_KapuschFacebookAndroidWrapperAar>$([System.IO.Path]::Combine('$(_KapuschFacebookAndroidPackageRoot)', 'android', 'aar', 'kfb-facebookinterop-release.aar')) + <_KapuschFacebookAndroidDepsDir>$([System.IO.Path]::Combine('$(_KapuschFacebookAndroidPackageRoot)', 'android', 'deps')) + + + + + + + + + + + + diff --git a/src/Kapusch.FacebookApisForAndroidComponents/nuget-readme.md b/src/Kapusch.FacebookApisForAndroidComponents/nuget-readme.md new file mode 100644 index 0000000..14fbf8d --- /dev/null +++ b/src/Kapusch.FacebookApisForAndroidComponents/nuget-readme.md @@ -0,0 +1,7 @@ +# Kapusch.Facebook.Android + +This package embeds a small Android interop Activity and the required Facebook Android SDK AARs, and injects them into consuming apps via `buildTransitive` MSBuild. + +## Notes +- No secrets are included. +- You must configure your AndroidManifest / resources as required by the Facebook Android SDK. From 65359b55de3c1d2603df14d133c60ad4202e0089 Mon Sep 17 00:00:00 2001 From: kapusch Date: Sat, 24 Jan 2026 10:22:58 +0100 Subject: [PATCH 2/3] Fix Gradle plugin repositories for CI --- .../Native/Android/settings.gradle.kts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/settings.gradle.kts b/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/settings.gradle.kts index 2944bbc..928c70e 100644 --- a/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/settings.gradle.kts +++ b/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/settings.gradle.kts @@ -1,2 +1,17 @@ +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +dependencyResolutionManagement { + repositories { + google() + mavenCentral() + } +} + rootProject.name = "KapuschFacebookInteropAndroid" include(":facebookinterop") From 2927970fecb1ff6b842e2eca3cd1d9a0994308e2 Mon Sep 17 00:00:00 2001 From: kapusch Date: Sat, 24 Jan 2026 11:22:12 +0100 Subject: [PATCH 3/3] feat: Update sample project configuration and add missing resources --- .gitignore | 4 ++++ .../Kapusch.Facebook.Android.Sample.csproj | 6 +++++- .../values/{strings.template.xml => strings.template} | 0 .../Kapusch.Facebook.Android.Sample/src/MainActivity.cs | 9 ++++++++- .../Native/Android/facebookinterop/build.gradle.kts | 2 +- 5 files changed, 18 insertions(+), 3 deletions(-) rename samples/Kapusch.Facebook.Android.Sample/Resources/values/{strings.template.xml => strings.template} (100%) diff --git a/.gitignore b/.gitignore index 798093f..e7f1b91 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,7 @@ src/**/Native/Android/build/ # Sample local config samples/**/google-services.json samples/**/secrets.* + +# Sample generated files +samples/**/AndroidManifest.xml +samples/**/strings.xml diff --git a/samples/Kapusch.Facebook.Android.Sample/Kapusch.Facebook.Android.Sample.csproj b/samples/Kapusch.Facebook.Android.Sample/Kapusch.Facebook.Android.Sample.csproj index 5334799..512115f 100644 --- a/samples/Kapusch.Facebook.Android.Sample/Kapusch.Facebook.Android.Sample.csproj +++ b/samples/Kapusch.Facebook.Android.Sample/Kapusch.Facebook.Android.Sample.csproj @@ -22,7 +22,7 @@ <_SampleStrings>$(MSBuildThisFileDirectory)Resources/values/strings.xml - <_SampleStringsTemplate>$(MSBuildThisFileDirectory)Resources/values/strings.template.xml + <_SampleStringsTemplate>$(MSBuildThisFileDirectory)Resources/values/strings.template + + + + diff --git a/samples/Kapusch.Facebook.Android.Sample/Resources/values/strings.template.xml b/samples/Kapusch.Facebook.Android.Sample/Resources/values/strings.template similarity index 100% rename from samples/Kapusch.Facebook.Android.Sample/Resources/values/strings.template.xml rename to samples/Kapusch.Facebook.Android.Sample/Resources/values/strings.template diff --git a/samples/Kapusch.Facebook.Android.Sample/src/MainActivity.cs b/samples/Kapusch.Facebook.Android.Sample/src/MainActivity.cs index da32b0a..41b6189 100644 --- a/samples/Kapusch.Facebook.Android.Sample/src/MainActivity.cs +++ b/samples/Kapusch.Facebook.Android.Sample/src/MainActivity.cs @@ -18,8 +18,15 @@ protected override void OnCreate(Bundle? savedInstanceState) var button = new Button(this) { Text = "Start Facebook Login" }; button.Click += (_, _) => { + var packageName = PackageName; + if (string.IsNullOrWhiteSpace(packageName)) + { + Toast.MakeText(this, "Missing package name", ToastLength.Short)?.Show(); + return; + } + var intent = new Intent(); - intent.SetClassName(PackageName, AndroidFacebookInterop.LoginActivityClassName); + intent.SetClassName(packageName, AndroidFacebookInterop.LoginActivityClassName); StartActivityForResult(intent, LoginRequestCode); }; diff --git a/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/facebookinterop/build.gradle.kts b/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/facebookinterop/build.gradle.kts index 43967ca..23c7221 100644 --- a/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/facebookinterop/build.gradle.kts +++ b/src/Kapusch.FacebookApisForAndroidComponents/Native/Android/facebookinterop/build.gradle.kts @@ -7,7 +7,7 @@ android { compileSdk = 34 defaultConfig { - minSdk = 26 + minSdk = 21 consumerProguardFiles("consumer-rules.pro") }