Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: Build

# Runs on every push and pull request. Needs no secrets: it builds unsigned artefacts and,
# to prove the release signing path works, signs once with a throw-away key made on the fly.

on:
push:
pull_request:

permissions:
contents: read

jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 40
steps:
- uses: actions/checkout@v5

- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 17

- uses: gradle/actions/setup-gradle@v5

- name: Unit tests (Google Play flavor logic)
run: ./gradlew --no-daemon :app:testPlayDebugUnitTest

- name: Build F-Droid / GitHub APK, Play debug APK and Play bundle
run: ./gradlew --no-daemon :app:assembleFossRelease :app:assemblePlayDebug :app:bundlePlayRelease

- name: The foss build must stay free of network access and Google code
run: |
APK=$(ls app/build/outputs/apk/foss/release/*.apk | head -n 1)
AAPT2=$(ls -d "$ANDROID_HOME"/build-tools/*/aapt2 | sort -V | tail -n 1)
echo "Checking $APK"
"$AAPT2" dump permissions "$APK" | tee permissions.txt
if grep -qE 'INTERNET|ACCESS_NETWORK_STATE|AD_ID' permissions.txt; then
echo "::error::foss build declares a network/ads permission"; exit 1
fi
if unzip -p "$APK" 'classes*.dex' | grep -aq 'com/google/android/gms'; then
echo "::error::foss build contains Google Play services code"; exit 1
fi
echo "foss build is clean"

- name: The play build must declare what ads and billing need
run: |
APK=$(ls app/build/outputs/apk/play/debug/*.apk | head -n 1)
AAPT2=$(ls -d "$ANDROID_HOME"/build-tools/*/aapt2 | sort -V | tail -n 1)
"$AAPT2" dump permissions "$APK" | tee play-permissions.txt
for p in INTERNET ACCESS_NETWORK_STATE AD_ID; do
grep -q "$p" play-permissions.txt || { echo "::error::play build is missing $p"; exit 1; }
done

- name: Signing smoke test with a throw-away key
env:
RELEASE_STORE_PASSWORD: throwaway-pass
RELEASE_KEY_ALIAS: smoke
RELEASE_KEY_PASSWORD: throwaway-pass
run: |
keytool -genkeypair -keystore "$RUNNER_TEMP/smoke.jks" -storepass throwaway-pass \
-keypass throwaway-pass -alias smoke -keyalg RSA -keysize 2048 -validity 2 \
-dname "CN=smoke test"
export RELEASE_STORE_FILE="$RUNNER_TEMP/smoke.jks"
./gradlew --no-daemon :app:bundlePlayRelease
AAB=$(ls app/build/outputs/bundle/playRelease/*.aab | head -n 1)
jarsigner -verify -certs "$AAB" | head -n 20
jarsigner -verify "$AAB" | grep -q "jar verified"

- name: Upload the Play debug APK for manual testing
uses: actions/upload-artifact@v4
with:
name: play-debug-apk
path: app/build/outputs/apk/play/debug/*.apk
retention-days: 7
76 changes: 76 additions & 0 deletions .github/workflows/release-aab.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: Release AAB for Google Play

# Builds the signed Android App Bundle you upload to the Play Console. The signing key never
# touches the repository: it is read from encrypted repository secrets (Settings > Secrets
# and variables > Actions), written to a temporary file for the build and deleted after.
#
# Required secrets:
# RELEASE_KEYSTORE_BASE64 the .jks file, base64-encoded
# RELEASE_STORE_PASSWORD keystore password
# RELEASE_KEY_ALIAS key alias (bcam)
# RELEASE_KEY_PASSWORD key password
#
# Run it from the Actions tab (Run workflow). The result is the "play-release-aab" artefact
# at the bottom of the run page.

on:
workflow_dispatch:

permissions:
contents: read

jobs:
bundle:
runs-on: ubuntu-latest
timeout-minutes: 40
steps:
- uses: actions/checkout@v5

- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 17

- uses: gradle/actions/setup-gradle@v5

- name: Restore the signing key
env:
KEYSTORE_B64: ${{ secrets.RELEASE_KEYSTORE_BASE64 }}
STORE_PASSWORD: ${{ secrets.RELEASE_STORE_PASSWORD }}
KEY_ALIAS: ${{ secrets.RELEASE_KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.RELEASE_KEY_PASSWORD }}
run: |
for v in KEYSTORE_B64 STORE_PASSWORD KEY_ALIAS KEY_PASSWORD; do
if [ -z "${!v}" ]; then
echo "::error::Repository secret for $v is not set - see the comment at the top of this workflow"
exit 1
fi
done
echo "$KEYSTORE_B64" | base64 -d > "$RUNNER_TEMP/release.jks"
{
echo "RELEASE_STORE_FILE=$RUNNER_TEMP/release.jks"
echo "RELEASE_STORE_PASSWORD=$STORE_PASSWORD"
echo "RELEASE_KEY_ALIAS=$KEY_ALIAS"
echo "RELEASE_KEY_PASSWORD=$KEY_PASSWORD"
} >> "$GITHUB_ENV"

- name: Build the signed bundle
run: ./gradlew --no-daemon :app:bundlePlayRelease

- name: Show which key signed it
run: |
AAB=$(ls app/build/outputs/bundle/playRelease/*.aab | head -n 1)
jarsigner -verify "$AAB" | head -n 3
keytool -printcert -jarfile "$AAB" | grep -E 'Owner|SHA1|SHA256|Valid'

- name: Upload the bundle
uses: actions/upload-artifact@v4
with:
name: play-release-aab
path: app/build/outputs/bundle/playRelease/*.aab
if-no-files-found: error
retention-days: 30

- name: Delete the key from the runner
if: always()
run: rm -f "$RUNNER_TEMP/release.jks"
10 changes: 6 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ build/
.externalNativeBuild
.cxx
local.properties
RELEASE_STORE_FILE=C:/GoshanData/keys/bcam-release.jks
RELEASE_STORE_PASSWORD=bo4A4FqxwYQ7p5L
RELEASE_KEY_ALIAS=bcam
RELEASE_KEY_PASSWORD=bo4A4FqxwYQ7p5L

# Signing material and release artefacts never belong in the repository.
*.jks
*.keystore
*.p12
*.aab

# Locally staged APKs for testing
/apk/
193 changes: 193 additions & 0 deletions PRIVACY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
# Privacy policy — Background Camera

*Last updated: 11 October 2026 · [Русская версия ниже](#политика-конфиденциальности--background-camera)*

Background Camera (`io.github.holego.bcam`) is a video recorder for Android developed by
**Holego**. This policy covers every version of the app: the one on Google Play, and the one
on F-Droid and GitHub.

## In short

* Your recordings, and the app's settings, **stay on your device**. The app never uploads
them anywhere, and the developer has no server that could receive them.
* The app has **no account, no analytics and no crash reporting of its own.**
* The **F-Droid / GitHub version has no network access at all** and no ads.
* The **Google Play version shows ads (Google AdMob)** and offers a one-time purchase that
removes them. Those two features use the internet and are the only reason this policy has
more than a few lines.

## What stays on your device

| Data | Where it lives | Leaves the device? |
|---|---|---|
| Videos and, if you enable it, their audio | The folder you pick (Android Storage Access Framework) | **No** |
| Settings (folder, camera, quality, language…) | The app's private storage | **No** |

Removing the app deletes the settings. The videos are ordinary files in your folder; the app
never deletes them, and you manage them yourself.

## Google Play version: ads

The free Google Play version shows ads provided by **Google AdMob** (Google LLC). To choose,
deliver and measure ads, and to prevent fraud, the Google Mobile Ads SDK in the app may
collect and use, according to the consent you give:

* the **advertising ID** of your device (you can reset or delete it in Android settings →
Privacy → Ads);
* your **IP address** and the **approximate location** derived from it;
* device and app information (model, OS version, language, app version);
* how you interact with ads (impressions, taps), and crash/diagnostic data from the SDK.

This data is processed by Google under [Google's privacy policy](https://policies.google.com/privacy);
see also [how Google uses data from apps that use its services](https://policies.google.com/technologies/partner-sites).
The developer does not receive this data, only aggregated ad revenue reports.

**Consent.** If you are in the European Economic Area, the United Kingdom or Switzerland, the
app first shows Google's consent message and only requests ads according to your choice. You
can review or change that choice at any time under **Ad privacy settings** on the main screen.
Elsewhere you can still reset your advertising ID in Android settings.

Ads are shown only on the setup screen, at natural pauses. **They are never shown while a
recording is running, and never when you start or stop a recording from the widget or the
notification.**

**Not for children.** The app is not directed to children under 13 (or under the applicable
age of digital consent) and does not knowingly serve ads to them.

## Google Play version: the "remove ads" purchase

The purchase is handled entirely by **Google Play Billing**. The developer never sees your
payment details. The app only learns from Google Play whether you own the product, and keeps
a local flag so it can hide ads. If you own it, the ad SDK is not started at all. A purchase
can be restored on a new device through the same Google account.

Optionally, you can watch a short rewarded video to turn ads off for 24 hours; the time of
that reward is stored on the device only.

## Permissions

| Permission | Why |
|---|---|
| Camera | To record video. |
| Microphone | Only if you turn on *Record audio*. |
| Foreground service (camera, microphone) | Keeps a recording running with the screen off; it always shows a notification with a Stop button. |
| Notifications | To show that a recording is in progress. |
| Wake lock | So a recording is not cut off when the screen turns off. |
| Internet, network state, advertising ID *(Google Play version only)* | Ads and the purchase. Not present in the F-Droid / GitHub version. |

## Responsible use

Recording people may require their consent and is regulated by law in many places. You are
responsible for using the app lawfully. While a recording runs the app always shows a
notification, and Android itself shows camera and microphone indicators.

## Your rights and contact

Because the developer does not hold personal data about you, there is nothing to access or
erase on the developer's side. For ad-related data, use **Ad privacy settings** in the app,
your Android advertising settings, and your Google account's
[Ad settings](https://adssettings.google.com).

Questions: open an issue at <https://github.com/Holego/BCam/issues> or write to the Jabber
address `Jopirat@jabber.fr`.

## Changes

If this policy changes, the new version will appear at this address with a new date.

---

# Политика конфиденциальности — Background Camera

*Обновлено: 11 октября 2026*

Background Camera (`io.github.holego.bcam`) — приложение для записи видео на Android,
разработчик — **Holego**. Политика относится ко всем версиям приложения: из Google Play и из
F-Droid / GitHub.

## Коротко

* Ваши записи и настройки приложения **остаются на вашем устройстве**. Приложение никуда их не
отправляет, а у разработчика нет сервера, который мог бы их принять.
* **Нет аккаунта, нет собственной аналитики и отчётов о сбоях.**
* **Версия из F-Droid / GitHub вообще не имеет доступа к сети** и не содержит рекламы.
* **Версия из Google Play показывает рекламу (Google AdMob)** и предлагает разовую покупку,
которая её отключает. Только эти две функции используют интернет.

## Что остаётся на устройстве

| Данные | Где хранятся | Покидают устройство? |
|---|---|---|
| Видео и, если включено, звук | Выбранная вами папка (Storage Access Framework) | **Нет** |
| Настройки (папка, камера, качество, язык…) | Приватное хранилище приложения | **Нет** |

При удалении приложения настройки удаляются. Видео — обычные файлы в вашей папке: приложение их
не удаляет, вы управляете ими сами.

## Версия Google Play: реклама

Бесплатная версия в Google Play показывает рекламу **Google AdMob** (Google LLC). Чтобы
подбирать, показывать и учитывать рекламу и предотвращать мошенничество, Google Mobile Ads SDK
может собирать и использовать — в соответствии с вашим согласием:

* **рекламный идентификатор** устройства (сбросить или удалить его можно в настройках Android →
Конфиденциальность → Реклама);
* **IP-адрес** и определяемое по нему **приблизительное местоположение**;
* сведения об устройстве и приложении (модель, версия ОС, язык, версия приложения);
* взаимодействие с рекламой (показы, нажатия) и диагностические данные SDK.

Эти данные обрабатывает Google в соответствии с
[политикой конфиденциальности Google](https://policies.google.com/privacy). Разработчик эти
данные не получает — только сводные отчёты о доходе от рекламы.

**Согласие.** Если вы находитесь в Европейской экономической зоне, Великобритании или
Швейцарии, приложение сначала показывает сообщение о согласии Google и запрашивает рекламу
только в соответствии с вашим выбором. Изменить выбор можно в любой момент: пункт **«Настройки
конфиденциальности рекламы»** на главном экране. В других регионах рекламный идентификатор можно
сбросить в настройках Android.

Реклама показывается только на экране настроек, в естественных паузах. **Её никогда нет во
время записи, а также при запуске и остановке записи через виджет или уведомление.**

**Не для детей.** Приложение не предназначено для детей младше 13 лет (или младше возраста
цифрового согласия, установленного законом) и сознательно не показывает им рекламу.

## Версия Google Play: покупка «отключить рекламу»

Покупку полностью обрабатывает **Google Play Billing**. Разработчик не видит ваши платёжные
данные. Приложение лишь узнаёт от Google Play, куплен ли товар, и хранит локальную отметку,
чтобы скрывать рекламу. Если покупка есть, рекламный SDK вообще не запускается. Покупку можно
восстановить на новом устройстве через тот же аккаунт Google.

Дополнительно можно посмотреть короткое видео и отключить рекламу на 24 часа; время такой
награды хранится только на устройстве.

## Разрешения

| Разрешение | Зачем |
|---|---|
| Камера | Запись видео. |
| Микрофон | Только если включён пункт «Записывать звук». |
| Служба переднего плана (камера, микрофон) | Запись продолжается при выключенном экране; при этом всегда показано уведомление с кнопкой «Стоп». |
| Уведомления | Показать, что идёт запись. |
| Wake lock | Чтобы запись не прерывалась при выключении экрана. |
| Интернет, состояние сети, рекламный идентификатор *(только версия Google Play)* | Реклама и покупка. В версии F-Droid / GitHub их нет. |

## Ответственное использование

Запись людей может требовать их согласия и регулируется законом во многих странах. Вы сами
отвечаете за законное использование приложения. Во время записи приложение всегда показывает
уведомление, а Android — индикаторы камеры и микрофона.

## Ваши права и связь

У разработчика нет ваших персональных данных, поэтому на его стороне нечего запрашивать или
удалять. Для данных, связанных с рекламой, используйте **«Настройки конфиденциальности
рекламы»** в приложении, настройки рекламы Android и
[настройки рекламы](https://adssettings.google.com) аккаунта Google.

Вопросы: <https://github.com/Holego/BCam/issues> или Jabber `Jopirat@jabber.fr`.

## Изменения

При изменении политики новая версия появится по этому адресу с новой датой.
Loading
Loading