├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── values-eo
│ │ │ │ └── strings.xml
│ │ │ ├── values-uk
│ │ │ │ └── strings.xml
│ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── values
│ │ │ │ ├── ic_launcher_background.xml
│ │ │ │ ├── menu_prefs_keys.xml
│ │ │ │ ├── arrays.xml
│ │ │ │ ├── colors.xml
│ │ │ │ └── shared_prefs_keys.xml
│ │ │ ├── color
│ │ │ │ ├── button_text_color.xml
│ │ │ │ ├── pref_two_state_color_text.xml
│ │ │ │ └── pref_two_state_color_text_secondary.xml
│ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── drawable
│ │ │ │ ├── ic_signal_cellular_4_bar_white_24dp.xml
│ │ │ │ ├── ic_add_white_24dp.xml
│ │ │ │ ├── ic_warning_24px.xml
│ │ │ │ ├── ic_signal_wifi_4_bar_white_24dp.xml
│ │ │ │ ├── ic_bluetooth_white_24dp.xml
│ │ │ │ ├── button_background.xml
│ │ │ │ ├── an2linux_icon.xml
│ │ │ │ └── ic_launcher_foreground.xml
│ │ │ ├── layout
│ │ │ │ ├── dialog_certificate_spinner_textview.xml
│ │ │ │ ├── dialog_certificate_spinner_dropdown_textview.xml
│ │ │ │ ├── view_progressbar.xml
│ │ │ │ ├── view_add_bluetooth_server.xml
│ │ │ │ ├── enabled_applications_filter_fragment.xml
│ │ │ │ ├── view_dialog_tcp_base.xml
│ │ │ │ ├── view_dialog_pairing.xml
│ │ │ │ ├── activity_enabled_applications.xml
│ │ │ │ ├── view_dialog_bottom_buttons.xml
│ │ │ │ ├── activity_server_configuration.xml
│ │ │ │ ├── numberpicker_dialog.xml
│ │ │ │ ├── view_bluetooth_item.xml
│ │ │ │ ├── view_dialog_wifi.xml
│ │ │ │ ├── view_dialog_mobile.xml
│ │ │ │ ├── activity_client_certificate.xml
│ │ │ │ ├── custom_notification_settings_recyclerview_item.xml
│ │ │ │ ├── view_dialog_bluetooth.xml
│ │ │ │ ├── view_server_item.xml
│ │ │ │ └── activity_custom_notification_settings.xml
│ │ │ ├── values-sw360dp-v13
│ │ │ │ └── values-preference.xml
│ │ │ ├── xml
│ │ │ │ ├── enabled_applications_preferences.xml
│ │ │ │ ├── main_preferences.xml
│ │ │ │ └── notification_preferences.xml
│ │ │ ├── values-hu
│ │ │ │ └── strings.xml
│ │ │ └── values-tr
│ │ │ │ └── strings.xml
│ │ └── java
│ │ │ └── kiwi
│ │ │ └── root
│ │ │ └── an2linuxclient
│ │ │ ├── interfaces
│ │ │ ├── OnItemClickListener.java
│ │ │ ├── CertificateSpinnerItem.java
│ │ │ └── ServerAdapterListCallbacks.java
│ │ │ ├── preferences
│ │ │ ├── CheckBoxPreferenceData.java
│ │ │ ├── MaxTitleSizePreference.java
│ │ │ ├── MaxMessageSizePreference.java
│ │ │ ├── ThemedNumberPicker.java
│ │ │ ├── IconSizePreference.java
│ │ │ ├── NumberPickerPreference.java
│ │ │ └── NumberPickerPreferenceDialog.java
│ │ │ ├── data
│ │ │ ├── CustomSettingsAppData.java
│ │ │ ├── TcpServer.java
│ │ │ ├── CertificateIdAndFingerprint.java
│ │ │ ├── BluetoothServer.java
│ │ │ ├── Server.java
│ │ │ ├── WifiServer.java
│ │ │ ├── MobileServer.java
│ │ │ └── NotificationSettings.java
│ │ │ ├── network
│ │ │ ├── NotificationConnection.java
│ │ │ ├── PairingConnectionCallbackMessage.java
│ │ │ ├── PairingConnection.java
│ │ │ ├── ThreadPoolHandler.java
│ │ │ ├── NotificationHandler.java
│ │ │ ├── NotificationConnectionHandler.java
│ │ │ └── TcpNotificationConnection.java
│ │ │ ├── activities
│ │ │ ├── ClientCertificateActivity.java
│ │ │ ├── EnabledApplicationsActivity.java
│ │ │ └── CustomNotificationSettingsActivity.java
│ │ │ ├── utils
│ │ │ ├── BootReceiver.java
│ │ │ ├── AN2LinuxService.java
│ │ │ ├── AN2LinuxTileService.java
│ │ │ └── ConnectionHelper.java
│ │ │ ├── views
│ │ │ ├── CustomProgressDialog.java
│ │ │ ├── BluetoothPairedListDialog.java
│ │ │ ├── TcpServerDialog.java
│ │ │ ├── MobileDialogNew.java
│ │ │ ├── WifiDialogNew.java
│ │ │ ├── BluetoothDialogEdit.java
│ │ │ ├── BluetoothDialogNew.java
│ │ │ ├── WifiDialogEdit.java
│ │ │ └── MobileDialogEdit.java
│ │ │ ├── fragments
│ │ │ ├── EnabledApplicationsFilterFragment.java
│ │ │ ├── ClientCertificateFragment.java
│ │ │ └── EnabledApplicationsPreferenceFragment.java
│ │ │ ├── crypto
│ │ │ ├── RsaHelper.java
│ │ │ ├── Sha256Helper.java
│ │ │ └── KeyGeneratorService.java
│ │ │ ├── adapters
│ │ │ ├── BluetoothPairedDevicesAdapter.java
│ │ │ └── CustomNotificationSettingsAdapter.java
│ │ │ ├── App.java
│ │ │ └── viewmodels
│ │ │ └── CustomNotificationSettingsViewModel.java
│ └── debug
│ │ └── res
│ │ └── values
│ │ └── strings.xml
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── fastlane
├── metadata
│ └── android
│ │ ├── en-US
│ │ ├── title.txt
│ │ ├── short_description.txt
│ │ ├── images
│ │ │ ├── icon.png
│ │ │ ├── featureGraphic.png
│ │ │ ├── promoGraphic.png
│ │ │ └── phoneScreenshots
│ │ │ │ ├── 1.png
│ │ │ │ ├── 2.png
│ │ │ │ ├── 3.png
│ │ │ │ ├── 4.png
│ │ │ │ ├── 5.png
│ │ │ │ ├── 6.png
│ │ │ │ ├── 7.png
│ │ │ │ └── 8.png
│ │ ├── changelogs
│ │ │ ├── 16.txt
│ │ │ ├── 19.txt
│ │ │ ├── 8.txt
│ │ │ ├── 14.txt
│ │ │ ├── 10.txt
│ │ │ ├── 18.txt
│ │ │ ├── 15.txt
│ │ │ ├── 9.txt
│ │ │ └── 17.txt
│ │ └── full_description.txt
│ │ ├── sv-SE
│ │ ├── title.txt
│ │ ├── short_description.txt
│ │ └── full_description.txt
│ │ ├── de-DE
│ │ ├── title.txt
│ │ ├── short_description.txt
│ │ └── full_description.txt
│ │ ├── no-NO
│ │ ├── title.txt
│ │ ├── short_description.txt
│ │ └── full_description.txt
│ │ ├── pl-PL
│ │ ├── title.txt
│ │ ├── short_description.txt
│ │ ├── changelogs
│ │ │ ├── 16.txt
│ │ │ ├── 14.txt
│ │ │ └── 8.txt
│ │ └── full_description.txt
│ │ └── ru-RU
│ │ ├── title.txt
│ │ ├── short_description.txt
│ │ └── full_description.txt
├── Appfile
└── Fastfile
├── Gemfile
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .idea
├── runConfigurations.xml
└── codeStyles
│ └── Project.xml
├── gradle.properties
├── README.md
├── gradlew.bat
└── .gitignore
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/title.txt:
--------------------------------------------------------------------------------
1 | AN2Linux
--------------------------------------------------------------------------------
/fastlane/metadata/android/sv-SE/title.txt:
--------------------------------------------------------------------------------
1 | AN2Linux
--------------------------------------------------------------------------------
/fastlane/metadata/android/de-DE/title.txt:
--------------------------------------------------------------------------------
1 | AN2Linux
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/no-NO/title.txt:
--------------------------------------------------------------------------------
1 | AN2Linux
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/pl-PL/title.txt:
--------------------------------------------------------------------------------
1 | AN2Linux
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/ru-RU/title.txt:
--------------------------------------------------------------------------------
1 | AN2Linux
2 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source "https://rubygems.org"
2 |
3 | gem "fastlane"
4 |
--------------------------------------------------------------------------------
/fastlane/Appfile:
--------------------------------------------------------------------------------
1 | json_key_file("fastlane/key.json")
2 | package_name("kiwi.root.an2linuxclient")
3 |
--------------------------------------------------------------------------------
/app/src/main/res/values-eo/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-uk/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/short_description.txt:
--------------------------------------------------------------------------------
1 | Sync Android notifications encrypted to a Linux desktop
--------------------------------------------------------------------------------
/fastlane/metadata/android/no-NO/short_description.txt:
--------------------------------------------------------------------------------
1 | Synkroniser Android-varsler kryptert til en Linux-PC
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/pl-PL/short_description.txt:
--------------------------------------------------------------------------------
1 | Synchronizuj powiadomienia Androida zaszyfrowane z pulpitem Linux
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/ru-RU/short_description.txt:
--------------------------------------------------------------------------------
1 | Синхронизуйте зашифрованные уведомления с Android на компьютер с Linux
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/sv-SE/short_description.txt:
--------------------------------------------------------------------------------
1 | Synkronisera Android-notifikationer krypterat till en Linux-desktop
2 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rootkiwi/an2linuxclient/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/fastlane/metadata/android/de-DE/short_description.txt:
--------------------------------------------------------------------------------
1 | Android-Benachrichtigungen verschlüsselt mit Linux-Desktop synchronisieren
2 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rootkiwi/an2linuxclient/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rootkiwi/an2linuxclient/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rootkiwi/an2linuxclient/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rootkiwi/an2linuxclient/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rootkiwi/an2linuxclient/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rootkiwi/an2linuxclient/HEAD/fastlane/metadata/android/en-US/images/icon.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/featureGraphic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rootkiwi/an2linuxclient/HEAD/fastlane/metadata/android/en-US/images/featureGraphic.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/promoGraphic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rootkiwi/an2linuxclient/HEAD/fastlane/metadata/android/en-US/images/promoGraphic.png
--------------------------------------------------------------------------------
/app/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #323232
4 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rootkiwi/an2linuxclient/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rootkiwi/an2linuxclient/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rootkiwi/an2linuxclient/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rootkiwi/an2linuxclient/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/4.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rootkiwi/an2linuxclient/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/5.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rootkiwi/an2linuxclient/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/6.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rootkiwi/an2linuxclient/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/7.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rootkiwi/an2linuxclient/HEAD/fastlane/metadata/android/en-US/images/phoneScreenshots/8.png
--------------------------------------------------------------------------------
/app/src/debug/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | AN2Linux.debug
3 | kiwi.root.an2linuxclient.debug
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/color/button_text_color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Mar 23 19:11:21 CET 2020
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/res/color/pref_two_state_color_text.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/interfaces/OnItemClickListener.java:
--------------------------------------------------------------------------------
1 | package kiwi.root.an2linuxclient.interfaces;
2 |
3 | import kiwi.root.an2linuxclient.data.CustomSettingsAppData;
4 |
5 | public interface OnItemClickListener {
6 | void onItemClick(CustomSettingsAppData appData);
7 | }
8 |
--------------------------------------------------------------------------------
/app/src/main/res/color/pref_two_state_color_text_secondary.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/16.txt:
--------------------------------------------------------------------------------
1 | 0.11.0 (Oct 25, 2019)
2 | - Norwegian (bokmål) translation by bilde2910, thank you!
3 |
4 | 0.10.0 (Oct 9, 2019)
5 | - Add support for commas in WiFi SSID
6 |
7 | 0.9.2 (Sep 4, 2019)
8 | - Add information about battery optimizations (Doze) introduced in Android 6.0.
9 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/pl-PL/changelogs/16.txt:
--------------------------------------------------------------------------------
1 | 0.11.0 (25.02.2019)
2 | - Norweski (bokmål) tłumaczenie przez bilde2910, dziękuję!
3 |
4 | 0.10.0 (9 października 2019)
5 | - Dodaj obsługę przecinków w WiFi SSID
6 |
7 | 0.9.2 (4 września 2019)
8 | - Dodaj informacje o optymalizacji baterii (Doze) wprowadzone w Android 6.0.
9 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_signal_cellular_4_bar_white_24dp.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/preferences/CheckBoxPreferenceData.java:
--------------------------------------------------------------------------------
1 | package kiwi.root.an2linuxclient.preferences;
2 |
3 | import android.graphics.drawable.Drawable;
4 |
5 | public class CheckBoxPreferenceData {
6 |
7 | public String key;
8 | public String title;
9 | public String summary;
10 | public Drawable icon;
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_add_white_24dp.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/data/CustomSettingsAppData.java:
--------------------------------------------------------------------------------
1 | package kiwi.root.an2linuxclient.data;
2 |
3 | import android.graphics.drawable.Drawable;
4 |
5 | public class CustomSettingsAppData {
6 |
7 | public Drawable appIcon;
8 | public String appName;
9 | public String packageName;
10 | public boolean isUsingCustomSettings;
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/interfaces/CertificateSpinnerItem.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.interfaces;
10 |
11 | public interface CertificateSpinnerItem {
12 | String toString();
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_warning_24px.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_certificate_spinner_textview.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_certificate_spinner_dropdown_textview.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values-sw360dp-v13/values-preference.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | false
6 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/19.txt:
--------------------------------------------------------------------------------
1 | 0.13.1 (Mar 21, 2021)
2 | - Bunch of translations, thank you all!
3 | - Russian added/updated by: Vlad & Andrey F
4 | - German updated by: Maximilian H, Translator & Simon Kreuzer
5 | - French updated by: Aearil
6 | - Polish updated by: Atrate & Jakub Fabijan
7 | - Spanish updated by: badlop & Vi-dot1
8 | - Hungarian added by: SoftwareByRedline
9 | - Turkish added by: Burak Hüseyin Ekseli
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_signal_wifi_4_bar_white_24dp.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/enabled_applications_preferences.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/8.txt:
--------------------------------------------------------------------------------
1 | 0.6.0 (May 12, 2017)
2 | - New preference added for minimum notification priority
3 |
4 | 0.5.1 (Apr 12, 2017)
5 | - Fix bug that caused AN2Linux to crash when opening individual app settings (affecting Android 4.4-5.1)
6 |
7 | 0.5.0 (Apr 5, 2017)
8 | - Replace sha1 with sha256
9 |
10 | 0.4.0 (Apr 1, 2017)
11 | - Allow notification settings to be set individually per app
12 |
13 | 0.3.0 (Feb 6, 2017)
14 | - New preference added for custom icon size
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_bluetooth_white_24dp.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/14.txt:
--------------------------------------------------------------------------------
1 | 0.9.2 (Sep 4, 2019)
2 | - Add information about battery optimizations (Doze) introduced in Android 6.0.
3 |
4 | 0.9.0 (Sep 1, 2019)
5 | - Add support for filtering apps with text search in 'Enabled applications' settings.
6 |
7 | - Add quick settings tile for toggle enable/disable AN2Linux.
8 |
9 | - Change minimum version required from Android 4.4 (API 19) to Android 4.3 (API 18).
10 |
11 | - New setting: don't send notification if phone display is turned on.
12 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/10.txt:
--------------------------------------------------------------------------------
1 | 0.8.0 (May 26, 2018)
2 | - From Android 8.1 COARSE_LOCATION permission is needed to access WiFi SSID! Also it seems
3 | that location services needs to be turned on as well, otherwise the SSID reported will
4 | be "unknown ssid".
5 |
6 | - Setting to run AN2Linux as a foreground service, thank you Eyenseo!
7 |
8 | - Dutch translation by Vistaus, thank you!
9 |
10 | - Spanish translation by CalebCDE, thank you!
11 |
12 | 0.7.0 (Jan 16, 2018)
13 | - New icon created by conrad-heimbold@github, thank you!
--------------------------------------------------------------------------------
/fastlane/metadata/android/pl-PL/changelogs/14.txt:
--------------------------------------------------------------------------------
1 | 0.9.2 (4 września 2019)
2 | - Dodaj informacje o optymalizacji baterii (Doze) wprowadzone w Android 6.0.
3 |
4 | 0.9.0 (1 września 2019)
5 | - Dodaj obsługę filtrowania aplikacji z wyszukiwaniem tekstu w ustawieniach "Włączone aplikacje".
6 |
7 | - Dodaj płytki szybkie ustawienia, aby włączyć / wyłączyć AN2Linux.
8 |
9 | - Zmień minimalną wersję wymaganą z Androida 4.4 (API 19) na Androida 4.3 (API 18).
10 |
11 | - Nowe ustawienie: nie wysyłaj powiadomień, jeśli wyświetlacz telefonu jest włączony.
12 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/18.txt:
--------------------------------------------------------------------------------
1 | 0.13.0 (Dec 1, 2020)
2 | - Polish translation added by WaldiS.
3 | - French translation added by J. Lavoie.
4 | - Norwegian translation updated by Allan Nordhøy.
5 | - German translation updated by Simon Kreuzer and J. Lavoie.
6 | - Thank you!
7 |
8 | 0.12.0 (Mar 25, 2020)
9 | - Add location permissions for Android 10. Android 10 requires fine instead of coarse location
10 | permission to access the WiFi SSID. And it need it 'all the time' to be able to use
11 | SSID whitelist while AN2Linux is running in background.
12 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/interfaces/ServerAdapterListCallbacks.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.interfaces;
10 |
11 | import kiwi.root.an2linuxclient.data.Server;
12 |
13 | public interface ServerAdapterListCallbacks {
14 | void addServer(Server server);
15 | void deleteServer(int serverListPosition);
16 | void updateServer(Server server, int serverListPosition);
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
12 |
13 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_progressbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/15.txt:
--------------------------------------------------------------------------------
1 | 0.10.0 (Oct 9, 2019)
2 | - Add support for commas in WiFi SSID
3 |
4 | 0.9.2 (Sep 4, 2019)
5 | - Add information about battery optimizations (Doze) introduced in Android 6.0.
6 |
7 | 0.9.0 (Sep 1, 2019)
8 | - Add support for filtering apps with text search in 'Enabled applications' settings.
9 |
10 | - Add quick settings tile for toggle enable/disable AN2Linux.
11 |
12 | - Change minimum version required from Android 4.4 (API 19) to Android 4.3 (API 18).
13 |
14 | - New setting: don't send notification if phone display is turned on.
15 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/9.txt:
--------------------------------------------------------------------------------
1 | 0.7.0 (Jan 16, 2018)
2 | - New icon created by conrad-heimbold@github, thank you!
3 |
4 | 0.6.0 (May 12, 2017)
5 | - New preference added for minimum notification priority
6 |
7 | 0.5.1 (Apr 12, 2017)
8 | - Fix bug that caused AN2Linux to crash when opening individual app settings (affecting Android 4.4-5.1)
9 |
10 | 0.5.0 (Apr 5, 2017)
11 | - Replace sha1 with sha256
12 |
13 | 0.4.0 (Apr 1, 2017)
14 | - Allow notification settings to be set individually per app
15 |
16 | 0.3.0 (Feb 6, 2017)
17 | - New preference added for custom icon size
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_add_bluetooth_server.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/17.txt:
--------------------------------------------------------------------------------
1 | 0.12.0 (Mar 25, 2020)
2 | - Add location permissions for Android 10. Android 10 requires fine instead of coarse location
3 | permission to access the WiFi SSID. And it need it 'all the time' to be able to use
4 | SSID whitelist while AN2Linux is running in background.
5 |
6 | 0.11.0 (Oct 25, 2019)
7 | - Norwegian (bokmål) translation by bilde2910, thank you!
8 |
9 | 0.10.0 (Oct 9, 2019)
10 | - Add support for commas in WiFi SSID
11 |
12 | 0.9.2 (Sep 4, 2019)
13 | - Add information about battery optimizations (Doze) introduced in Android 6.0.
14 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/pl-PL/changelogs/8.txt:
--------------------------------------------------------------------------------
1 | 0.6.0 (12 maja 2017 r.)
2 | - Dodano nową preferencję dla minimalnego priorytetu powiadomień
3 |
4 | 0.5.1 (12 kwi 2017)
5 | - Naprawić błąd, który spowodował AWARIĘ AN2Linux podczas otwierania poszczególnych ustawień aplikacji (wpływających na Androida 4.4-5.1)
6 |
7 | 0.5.0 (5 kwi 2017)
8 | - Wymień sha1 na sha256
9 |
10 | 0.4.0 (1 kwi 2017)
11 | - Zezwalaj na ustawienia powiadomień, które mają być ustawiane indywidualnie dla każdej aplikacji
12 |
13 | 0.3.0 (6 lutego 2017)
14 | - Dodano nowe preferencje dla niestandardowego rozmiaru ikony
15 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/values-hu/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Az eszköz nem támogatja az akkumulátoroptimalizálás kikapsolását
4 | Három különböző típusú szerver van: WiFi, Mobil és Bluetooth.
5 | \n
6 | \nEz azt jelenti, hogy az AN2Linux csak akkor próbálja elküldeni az értesítéseket a szervernek, ha a megfelelő típusúhoz van csatlakozva.
7 | \n
8 | \nPéldául ha WiFi-hez van csatlakozva, akkor csak a WiFi szerverekhez próbál csatlakozni, mobilszerverekhez nem.
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/menu_prefs_keys.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | main_display_test_notification_key
4 | main_changelog_key
5 | main_license_key
6 | enabled_apps_pref_screen
7 | notification_settings_global_category
8 | open_ignore_battery_optimization_settings_key
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - Min
5 | - Low
6 | - Default
7 | - High
8 | - Max
9 |
10 |
11 | - -2
12 | - -1
13 | - 0
14 | - 1
15 | - 2
16 |
17 | -2
18 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/no-NO/full_description.txt:
--------------------------------------------------------------------------------
1 | AN2Linux lar deg synkronisere varsler på telefonen din til Linux-PCen din kryptert med TLS.
2 |
3 | Den kan gjøre dette over WiFi, mobildata eller Bluetooth.
4 |
5 | For at AN2Linux skal virke må du ha AN2Linux-serveren kjørende på PCen din.
6 |
7 | For mer informasjon les README-filene fra git.
8 | Hvis du opplever problemer kan du opprette en sak på GitHub.
9 |
10 | AN2Linux er fri, åpen-kildekode-programvare lisensiert under GNU GPLv3.
11 |
12 | Kildekoden til denne appen:
13 | https://github.com/rootkiwi/an2linuxclient/
14 |
15 | Kildekoden til serveren:
16 | https://github.com/rootkiwi/an2linuxserver/
17 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/full_description.txt:
--------------------------------------------------------------------------------
1 | AN2Linux allows you to sync notifications on your phone to your Linux desktop encrypted using TLS.
2 |
3 | It can do so over WiFi, Mobile data or Bluetooth.
4 |
5 | For AN2Linux to work you need to have AN2Linux-server running on your computer.
6 |
7 | For more info read the README files from the git repositories.
8 | If you have any issues you can create an Issue on GitHub.
9 |
10 | AN2Linux is free and open-source software licensed under GNU GPLv3.
11 |
12 | Source code this app:
13 | https://github.com/rootkiwi/an2linuxclient/
14 |
15 | Source code AN2Linux-server:
16 | https://github.com/rootkiwi/an2linuxserver/
17 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/sv-SE/full_description.txt:
--------------------------------------------------------------------------------
1 | AN2Linux låter dig synkronisera notifikationer på din telefon till din Linux-desktop krypterat med TLS.
2 |
3 | Detta är möjligt via WiFi, mobildata eller Bluetooth.
4 |
5 | För att AN2Linux ska fungera måste du ha AN2Linux-server körandes på din dator.
6 |
7 | För mer information kan du läsa README-filerna från git.
8 | Om du har några problem kan du skapa ett 'Issue' på GitHub.
9 |
10 | AN2Linux är fri programvara med öppen källkod licensierad under GNU GPLv3.
11 |
12 | Källkod för denna app:
13 | https://github.com/rootkiwi/an2linuxclient/
14 |
15 | Källkod för AN2Linux-server:
16 | https://github.com/rootkiwi/an2linuxserver/
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/enabled_applications_filter_fragment.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | @color/colorAccent
4 | @color/colorAccent
5 | #1DE9B6
6 |
7 | #FFFFFF
8 | #E0E0E0
9 | #BDBDBD
10 | #757575
11 | #515151
12 | #323232
13 | #212121
14 |
15 | #64FFDA
16 | #00BFA5
17 |
18 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/pl-PL/full_description.txt:
--------------------------------------------------------------------------------
1 | AN2Linux pozwala na synchronizację powiadomień w telefonie do pulpitu Linuksa zaszyfrowanych za pomocą TLS.
2 |
3 | Może to zrobić przez WiFi, dane komórkowe lub Bluetooth.
4 |
5 | Aby AN2Linux działał, musisz mieć serwer AN2Linux uruchomiony na twoim komputerze.
6 |
7 | Aby uzyskać więcej informacji, przeczytaj pliki README z repozytoriów git.
8 | Jeśli masz jakiekolwiek problemy, możesz utworzyć problem w usłudze GitHub.
9 |
10 | AN2Linux jest darmowym i otwartym oprogramowaniem licencjonowanym na licencji GNU GPLv3.
11 |
12 | Kod źródłowy tej aplikacji:
13 | https://github.com/rootkiwi/an2linuxclient/
14 |
15 | Kod źródłowy AN2Linux-server:
16 | https://github.com/rootkiwi/an2linuxserver/
17 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/ru-RU/full_description.txt:
--------------------------------------------------------------------------------
1 | AN2Linux позволяет синхронизовать уведомления с вашего телефона на компьютер с Linux и шифровать их при помощи TLS.
2 |
3 | Это можно делать через WiFi, мобильную сеть или Bluetooth.
4 |
5 | Для работы AN2Linux на компьютере должен быть запущен AN2Linux-server.
6 |
7 | Для получения дополнительной информации смотрите файл README в git-репозитории.
8 | Если вы столкнулись с какой-то проблемой, то создайте Issue на GitHub.
9 |
10 | AN2Linux это свободное ПО с открытым исходным кодом, выпущенное под лицензией GNU GPL v3.
11 |
12 | Исходный код этого приложения:
13 | https://github.com/rootkiwi/an2linuxclient/
14 |
15 | Исходный код AN2Linux-server:
16 | https://github.com/rootkiwi/an2linuxserver/
17 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/de-DE/full_description.txt:
--------------------------------------------------------------------------------
1 | Mit AN2Linux können Sie die Benachrichtigungen von Ihrem Smartphone auf Ihren Linux-Computer synchronisieren, und zwar TLS-verschlüsselt.
2 |
3 | AN2Linux funktioniert über WLAN, Mobile Daten und Bluetooth.
4 |
5 | Auf Ihrem Computer muss dazu die Anwendung AN2Linux-server (s. u.) laufen.
6 |
7 | Um mehr zu erfahren, lesen Sie die README-Datei auf GitHub.
8 | Falls Sie Schwierigkeiten haben, können sie ebenso auf Github ein Issue erstellen.
9 |
10 | AN2Linux is freie und quelloffene Software, die unter der GNU GPLv3 lizensiert ist.
11 |
12 | Quelltext dieser App:
13 | https://github.com/rootkiwi/an2linuxclient/
14 |
15 | Quelltext von AN2Linux-server:
16 | https://github.com/rootkiwi/an2linuxserver/
17 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/preferences/MaxTitleSizePreference.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.preferences;
10 |
11 | import android.content.Context;
12 | import android.util.AttributeSet;
13 |
14 | public class MaxTitleSizePreference extends NumberPickerPreference {
15 |
16 | private static final int MIN_VALUE = 1;
17 | private static final int MAX_VALUE = 999;
18 | public static final int DEFAULT_VALUE = 20;
19 |
20 | public MaxTitleSizePreference(Context context, AttributeSet attrs) {
21 | super(context, attrs, MIN_VALUE, MAX_VALUE, DEFAULT_VALUE);
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/preferences/MaxMessageSizePreference.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.preferences;
10 |
11 | import android.content.Context;
12 | import android.util.AttributeSet;
13 |
14 | public class MaxMessageSizePreference extends NumberPickerPreference {
15 |
16 | private static final int MIN_VALUE = 1;
17 | private static final int MAX_VALUE = 999;
18 | public static final int DEFAULT_VALUE = 120;
19 |
20 | public MaxMessageSizePreference(Context context, AttributeSet attrs) {
21 | super(context, attrs, MIN_VALUE, MAX_VALUE, DEFAULT_VALUE);
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/data/TcpServer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.data;
10 |
11 | public abstract class TcpServer extends Server {
12 |
13 | String ipOrHostname;
14 | int portNumber;
15 |
16 | void setIpOrHostname(String ipOrHostname) {
17 | this.ipOrHostname = ipOrHostname;
18 | }
19 |
20 | void setPortNumber(int portNumber) {
21 | this.portNumber = portNumber;
22 | }
23 |
24 | public String getIpOrHostname() {
25 | return this.ipOrHostname;
26 | }
27 |
28 | public int getPortNumber() {
29 | return this.portNumber;
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_dialog_tcp_base.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
12 |
13 |
16 |
17 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/network/NotificationConnection.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.network;
10 |
11 | import android.content.Context;
12 |
13 | import java.security.cert.Certificate;
14 |
15 | import kiwi.root.an2linuxclient.data.Notification;
16 |
17 | abstract class NotificationConnection implements Runnable {
18 |
19 | Context c;
20 | Notification n;
21 | Certificate serverCert;
22 |
23 | final byte NOTIF_CONN = 1;
24 |
25 | NotificationConnection(Context c, Notification n, Certificate serverCert) {
26 | this.c = c;
27 | this.n = n;
28 | this.serverCert = serverCert;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/preferences/ThemedNumberPicker.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.preferences;
10 |
11 | import android.content.Context;
12 | import android.util.AttributeSet;
13 | import android.view.ContextThemeWrapper;
14 | import android.widget.NumberPicker;
15 |
16 | import kiwi.root.an2linuxclient.R;
17 |
18 | public class ThemedNumberPicker extends NumberPicker {
19 |
20 | public ThemedNumberPicker(Context context) {
21 | this(context, null);
22 | }
23 |
24 | public ThemedNumberPicker(Context context, AttributeSet attrs) {
25 | super(new ContextThemeWrapper(context, R.style.NumberPickerStyle), attrs);
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/res/values-tr/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Öncelikli hizmeti etkinleştir
4 | AN2Linux\'ü etkinleştir
5 | Hakkında
6 | Ayarlar
7 | Kurulum
8 | Cihaz sertifikası ve anahtarı
9 | Sunucu ayarı
10 | Özel ayarlar
11 | Bildirim ayarları
12 | Etkin uygulamalar
13 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | ## For more details on how to configure your build environment visit
2 | # http://www.gradle.org/docs/current/userguide/build_environment.html
3 | #
4 | # Specifies the JVM arguments used for the daemon process.
5 | # The setting is particularly useful for tweaking memory settings.
6 | # Default value: -Xmx1024m -XX:MaxPermSize=256m
7 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
8 | #
9 | # When configured, Gradle will run in incubating parallel mode.
10 | # This option should only be used with decoupled projects. More details, visit
11 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
12 | # org.gradle.parallel=true
13 | #Sat Aug 31 15:01:44 CEST 2019
14 | android.enableJetifier=true
15 | org.gradle.jvmargs=-Xmx1024M -Dkotlin.daemon.jvm.options\="-Xmx1024M"
16 | android.useAndroidX=true
17 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/data/CertificateIdAndFingerprint.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.data;
10 |
11 | import kiwi.root.an2linuxclient.crypto.Sha256Helper;
12 | import kiwi.root.an2linuxclient.interfaces.CertificateSpinnerItem;
13 |
14 | public class CertificateIdAndFingerprint implements CertificateSpinnerItem {
15 |
16 | private long id;
17 | private String fingerprint;
18 |
19 | CertificateIdAndFingerprint(long id, String fingerprint){
20 | this.id = id;
21 | this.fingerprint = fingerprint;
22 | }
23 |
24 | public long getId() {
25 | return id;
26 | }
27 |
28 | @Override
29 | public String toString() {
30 | return Sha256Helper.getFourLineHexString(fingerprint);
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/preferences/IconSizePreference.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.preferences;
10 |
11 | import android.content.Context;
12 | import android.util.AttributeSet;
13 |
14 | import kiwi.root.an2linuxclient.R;
15 |
16 | public class IconSizePreference extends NumberPickerPreference {
17 |
18 | private static final int MIN_VALUE = 20;
19 | private static final int MAX_VALUE = 100;
20 | public static final int DEFAULT_VALUE = 64;
21 |
22 | public IconSizePreference(Context context, AttributeSet attrs) {
23 | super(context, attrs, MIN_VALUE, MAX_VALUE, DEFAULT_VALUE);
24 | }
25 |
26 | @Override
27 | String getSummaryString(){
28 | return getContext().getString(R.string.main_icon_size_summary, value);
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_dialog_pairing.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
14 |
15 |
21 |
22 |
27 |
28 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in {SDKHOME}/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | -assumenosideeffects class android.util.Log {
20 | public static boolean isLoggable(java.lang.String, int);
21 | public static int v(...);
22 | public static int i(...);
23 | public static int w(...);
24 | public static int d(...);
25 | public static int e(...);
26 | }
27 |
28 | -dontwarn org.spongycastle.**
29 | -keep class org.spongycastle.** {*;}
30 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/activities/ClientCertificateActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.activities;
10 |
11 | import android.app.FragmentManager;
12 | import android.os.Bundle;
13 | import androidx.appcompat.app.AppCompatActivity;
14 |
15 | import kiwi.root.an2linuxclient.fragments.ClientCertificateFragment;
16 |
17 | public class ClientCertificateActivity extends AppCompatActivity {
18 |
19 | @Override
20 | protected void onCreate(Bundle savedInstanceState) {
21 | super.onCreate(savedInstanceState);
22 |
23 | final String TAG = "ClientCertificateFragment";
24 |
25 | FragmentManager fm = getFragmentManager();
26 | ClientCertificateFragment fragment = (ClientCertificateFragment) fm.findFragmentByTag(TAG);
27 |
28 | if (fragment == null) {
29 | fragment = new ClientCertificateFragment();
30 | fm.beginTransaction().replace(android.R.id.content, fragment, TAG).commit();
31 | }
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_enabled_applications.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
16 |
17 |
18 |
19 |
22 |
23 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_dialog_bottom_buttons.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
16 |
17 |
24 |
25 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_server_configuration.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
18 |
19 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/utils/BootReceiver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.utils;
10 |
11 | import android.content.BroadcastReceiver;
12 | import android.content.Context;
13 | import android.content.Intent;
14 | import android.preference.PreferenceManager;
15 | import kiwi.root.an2linuxclient.R;
16 |
17 | public class BootReceiver extends BroadcastReceiver {
18 | @Override
19 | public void onReceive(Context context, Intent intent) {
20 | boolean an2linuxEnabled = PreferenceManager.getDefaultSharedPreferences(context)
21 | .getBoolean(context.getString(R.string.preference_enable_an2linux), false);
22 |
23 | if (an2linuxEnabled){
24 | boolean useForegroundService = PreferenceManager.getDefaultSharedPreferences(context)
25 | .getBoolean(context.getString(R.string.preference_enable_service), false);
26 |
27 | if (useForegroundService){
28 | context.startService(new Intent(context, AN2LinuxService.class));
29 | }
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/numberpicker_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
18 |
19 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/views/CustomProgressDialog.java:
--------------------------------------------------------------------------------
1 | package kiwi.root.an2linuxclient.views;
2 |
3 | import android.graphics.PorterDuff;
4 | import android.os.Bundle;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.view.WindowManager;
9 | import android.widget.ProgressBar;
10 |
11 | import androidx.fragment.app.DialogFragment;
12 |
13 | import kiwi.root.an2linuxclient.R;
14 |
15 | public class CustomProgressDialog extends DialogFragment {
16 |
17 | @Override
18 | public void onCreate(Bundle savedInstanceState) {
19 | super.onCreate(savedInstanceState);
20 | setStyle(DialogFragment.STYLE_NO_TITLE, R.style.ProgressDialogStyle);
21 | }
22 |
23 | @Override
24 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
25 | View view = inflater.inflate(R.layout.view_progressbar, container);
26 | getDialog().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
27 | ((ProgressBar) view.findViewById(R.id.progressBar))
28 | .getIndeterminateDrawable()
29 | .setColorFilter(getResources().getColor(R.color.colorAccent), PorterDuff.Mode.SRC_ATOP);
30 | return view;
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_bluetooth_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
16 |
22 |
23 |
30 |
31 |
32 |
33 |
38 |
39 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_dialog_wifi.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
18 |
19 |
20 |
21 |
24 |
25 |
29 |
30 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/an2linux_icon.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/network/PairingConnectionCallbackMessage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.network;
10 |
11 | import java.security.cert.Certificate;
12 |
13 | public class PairingConnectionCallbackMessage {
14 |
15 | private CallbackType type;
16 | private String verifyHash;
17 | private Certificate serverCert;
18 |
19 | public enum CallbackType {
20 | NOT_CONNECTED,
21 | DISALLOWED_SSID,
22 | NOT_CONNECTED_TO_WIFI,
23 | NOT_ALLOWED_TO_ROAM,
24 | BLUETOOTH_NOT_ENABLED,
25 | UNKNOWN_HOST,
26 | TIMED_OUT,
27 | FAILED_TO_CONNECT,
28 | TLS_HANDSHAKE_COMPLETED,
29 | SERVER_ACCEPTED_PAIR,
30 | SERVER_DENIED_PAIR,
31 | SOCKET_CLOSED
32 | }
33 |
34 | public PairingConnectionCallbackMessage(CallbackType type){
35 | this.type = type;
36 | }
37 |
38 | public PairingConnectionCallbackMessage(CallbackType type, String verifyHash, Certificate serverCert){
39 | this.type = type;
40 | this.verifyHash = verifyHash;
41 | this.serverCert = serverCert;
42 | }
43 |
44 | public CallbackType getType(){
45 | return this.type;
46 | }
47 |
48 | public String getVerifyHash(){
49 | return this.verifyHash;
50 | }
51 |
52 | public Certificate getServerCert(){
53 | return this.serverCert;
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
6 |
8 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_dialog_mobile.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
17 |
18 |
19 |
20 |
23 |
24 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/activities/EnabledApplicationsActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.activities;
10 |
11 | import android.os.Bundle;
12 |
13 | import androidx.annotation.Nullable;
14 | import androidx.appcompat.app.AppCompatActivity;
15 | import androidx.lifecycle.Observer;
16 | import androidx.lifecycle.ViewModelProviders;
17 |
18 | import kiwi.root.an2linuxclient.R;
19 | import kiwi.root.an2linuxclient.viewmodels.EnabledApplicationsViewModel;
20 | import kiwi.root.an2linuxclient.views.CustomProgressDialog;
21 |
22 | public class EnabledApplicationsActivity extends AppCompatActivity {
23 |
24 | private CustomProgressDialog progressDialog;
25 |
26 | @Override
27 | protected void onCreate(Bundle savedInstanceState) {
28 | super.onCreate(savedInstanceState);
29 | setContentView(R.layout.activity_enabled_applications);
30 |
31 | EnabledApplicationsViewModel viewModel = ViewModelProviders.of(this).get(EnabledApplicationsViewModel.class);
32 | viewModel.getOperationRunning().observe(this, operationIsRunning -> {
33 | if (operationIsRunning) {
34 | progressDialog = new CustomProgressDialog();
35 | progressDialog.setCancelable(false);
36 | progressDialog.show(getSupportFragmentManager(), "progressDialog");
37 | } else {
38 | if (progressDialog != null) {
39 | progressDialog.dismiss();
40 | }
41 | }
42 | });
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_client_certificate.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
16 |
17 |
26 |
27 |
36 |
37 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/network/PairingConnection.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.network;
10 |
11 | import android.content.Context;
12 |
13 | import java.io.InputStream;
14 | import java.io.OutputStream;
15 | import java.util.Observable;
16 | import java.util.Observer;
17 |
18 | abstract class PairingConnection implements Runnable {
19 |
20 | Context c;
21 | private PairingObservable observable;
22 |
23 | boolean mCancel;
24 | boolean mPairResponseSent;
25 | OutputStream mOut;
26 | InputStream mIn;
27 |
28 | final byte INITIATE_PAIRING = 0;
29 | final byte DENY_PAIRING = 2;
30 | final byte ACCEPT_PAIRING = 3;
31 |
32 | PairingConnection(Context c) {
33 | this.c = c;
34 | this.observable = new PairingObservable();
35 | }
36 |
37 | abstract void acceptPairing();
38 |
39 | abstract void denyPairing();
40 |
41 | void cancel() {
42 | if (!mPairResponseSent && mOut != null) {
43 | denyPairing();
44 | }
45 | mCancel = true;
46 | }
47 |
48 | void notifyObservers(Object data) {
49 | observable.notifyObservers(data);
50 | }
51 |
52 | void addObserver(Observer observer) {
53 | observable.addObserver(observer);
54 | }
55 |
56 | void deleteObservers(){
57 | observable.deleteObservers();
58 | }
59 |
60 | private class PairingObservable extends Observable {
61 |
62 | @Override
63 | public void notifyObservers(Object data) {
64 | setChanged();
65 | super.notifyObservers(data);
66 | }
67 |
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/network/ThreadPoolHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.network;
10 |
11 | import java.util.concurrent.LinkedBlockingQueue;
12 | import java.util.concurrent.ThreadPoolExecutor;
13 | import java.util.concurrent.TimeUnit;
14 |
15 | class ThreadPoolHandler {
16 |
17 | private static ThreadPoolExecutor threadPool;
18 | private static ThreadPoolExecutor bluetoothThreadPool;
19 |
20 | private static final long KEEP_ALIVE_TIME = 30;
21 | private static final TimeUnit TIME_UNIT = TimeUnit.SECONDS;
22 |
23 | static void enqueueRunnable(Runnable r){
24 | if (threadPool == null || threadPool.isShutdown()){
25 | final int CORE_POOL_SIZE = 2;
26 | final int MAXIMUM_POOL_SIZE = 2;
27 | threadPool = new ThreadPoolExecutor(CORE_POOL_SIZE,
28 | MAXIMUM_POOL_SIZE,
29 | KEEP_ALIVE_TIME, TIME_UNIT,
30 | new LinkedBlockingQueue<>());
31 | threadPool.allowCoreThreadTimeOut(true);
32 | }
33 | threadPool.execute(r);
34 | }
35 |
36 | /**
37 | * needed so that no more than one bluetooth connection is active at any time
38 | */
39 | static void enqueueBtConn(Runnable r){
40 | if (bluetoothThreadPool == null || bluetoothThreadPool.isShutdown()){
41 | final int CORE_POOL_SIZE = 0;
42 | final int MAXIMUM_POOL_SIZE = 1;
43 | bluetoothThreadPool = new ThreadPoolExecutor(CORE_POOL_SIZE,
44 | MAXIMUM_POOL_SIZE,
45 | KEEP_ALIVE_TIME, TIME_UNIT,
46 | new LinkedBlockingQueue<>());
47 | }
48 | bluetoothThreadPool.execute(r);
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/custom_notification_settings_recyclerview_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
21 |
22 |
32 |
33 |
42 |
43 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/network/NotificationHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.network;
10 |
11 | import android.content.Context;
12 | import android.service.notification.StatusBarNotification;
13 |
14 | import java.util.List;
15 |
16 | import kiwi.root.an2linuxclient.data.BluetoothServer;
17 | import kiwi.root.an2linuxclient.data.Notification;
18 | import kiwi.root.an2linuxclient.data.ServerDatabaseHandler;
19 | import kiwi.root.an2linuxclient.data.MobileServer;
20 | import kiwi.root.an2linuxclient.data.WifiServer;
21 |
22 | public class NotificationHandler {
23 |
24 | public static void handleStatusBarNotification(StatusBarNotification sbn, Context c){
25 | Notification n = new Notification(sbn, c);
26 | sendNotificationToAllEnabledServers(n, c);
27 | }
28 |
29 | private static void sendNotificationToAllEnabledServers(Notification n, Context c){
30 | ServerDatabaseHandler dbHandler = ServerDatabaseHandler.getInstance(c);
31 |
32 | List allEnabledWifiServers = dbHandler.getAllEnabledWifiServers();
33 | if (allEnabledWifiServers.size() > 0) {
34 | NotificationConnectionHandler.sendToAllEnabledWifiServers(n, c, allEnabledWifiServers);
35 | }
36 |
37 | List allEnabledMobileServers = dbHandler.getAllEnabledMobileServers();
38 | if (allEnabledMobileServers.size() > 0) {
39 | NotificationConnectionHandler.sendToAllEnabledMobileServers(n, c, allEnabledMobileServers);
40 | }
41 |
42 | List allEnabledBluetoothServers = dbHandler.getAllEnabledBluetoothServers();
43 | if (allEnabledBluetoothServers.size() > 0) {
44 | NotificationConnectionHandler.sendToAllEnabledBluetoothServers(n, c, allEnabledBluetoothServers);
45 | }
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 29
5 | defaultConfig {
6 | applicationId "kiwi.root.an2linuxclient"
7 | minSdkVersion 18
8 | targetSdkVersion 29
9 | versionCode 19
10 | versionName "0.13.1"
11 | }
12 | buildTypes {
13 | release {
14 | minifyEnabled true
15 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
16 | }
17 | debug {
18 | applicationIdSuffix ".debug"
19 | versionNameSuffix '-DEBUG'
20 | }
21 | }
22 | lintOptions {
23 | // disable errors on lint
24 | abortOnError false
25 | }
26 | compileOptions {
27 | sourceCompatibility = 1.8
28 | targetCompatibility = 1.8
29 | }
30 | }
31 |
32 | ext {
33 | // https://developer.android.com/jetpack/androidx/versions/
34 |
35 | appcompatVersion = "1.1.0"
36 | annotationVersion = "1.1.0"
37 | preferenceVersion = "1.1.0"
38 | recyclerViewVersion = "1.1.0"
39 | constraintLayoutVersion = "1.1.3"
40 | lifecycleVersion = "2.2.0"
41 |
42 | materialVersion = "1.0.0"
43 | }
44 |
45 | dependencies {
46 | implementation "androidx.appcompat:appcompat:$appcompatVersion"
47 | implementation "androidx.annotation:annotation:$annotationVersion"
48 | implementation "androidx.preference:preference:$preferenceVersion"
49 | implementation "androidx.recyclerview:recyclerview:$recyclerViewVersion"
50 | implementation "androidx.constraintlayout:constraintlayout:$constraintLayoutVersion"
51 |
52 | // ViewModel and LiveData
53 | implementation "androidx.lifecycle:lifecycle-extensions:$lifecycleVersion"
54 | annotationProcessor "androidx.lifecycle:lifecycle-common-java8:$lifecycleVersion"
55 |
56 | // For Floating Action Button
57 | implementation "com.google.android.material:material:$materialVersion"
58 |
59 | implementation "com.madgag.spongycastle:pkix:1.54.0.0" // for X.509 certificate generation
60 | }
61 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AN2Linux - client (Android app)
2 | Sync Android notifications encrypted using TLS to a Linux desktop over WiFi, Mobile data or Bluetooth.
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | ## AN2Linux server
12 | Setup instructions for AN2Linux server can be found here:
13 | https://github.com/rootkiwi/an2linuxserver/.
14 |
15 | ## Translation
16 | Help with translation using Weblate.
17 |
18 |
19 |
20 |
21 | ## Screenshots
22 |
23 |
24 | ## License
25 | [GNU General Public License 3](https://www.gnu.org/licenses/gpl-3.0.html).
26 |
27 | See LICENSE for more details.
28 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/fragments/EnabledApplicationsFilterFragment.java:
--------------------------------------------------------------------------------
1 | package kiwi.root.an2linuxclient.fragments;
2 |
3 | import android.os.Bundle;
4 | import android.text.Editable;
5 | import android.text.TextWatcher;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.EditText;
10 |
11 | import androidx.annotation.NonNull;
12 | import androidx.annotation.Nullable;
13 | import androidx.fragment.app.Fragment;
14 | import androidx.lifecycle.ViewModelProviders;
15 |
16 | import kiwi.root.an2linuxclient.R;
17 | import kiwi.root.an2linuxclient.viewmodels.EnabledApplicationsViewModel;
18 |
19 | public class EnabledApplicationsFilterFragment extends Fragment {
20 |
21 | @Override
22 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
23 | @Nullable Bundle savedInstanceState) {
24 | return inflater.inflate(R.layout.enabled_applications_filter_fragment, container, false);
25 | }
26 |
27 | @Override
28 | public void onActivityCreated(@Nullable Bundle savedInstanceState) {
29 | super.onActivityCreated(savedInstanceState);
30 | final EnabledApplicationsViewModel viewModel = ViewModelProviders.of(getActivity()).get(EnabledApplicationsViewModel.class);
31 |
32 | EditText filterInputEditText = getView().findViewById(R.id.filterInputEditText);
33 | filterInputEditText.addTextChangedListener(new TextWatcher() {
34 | @Override
35 | public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
36 | }
37 |
38 | @Override
39 | public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
40 | }
41 |
42 | @Override
43 | public void afterTextChanged(Editable editable) {
44 | String filter = editable.toString().trim().toLowerCase();
45 | viewModel.filterTextChanged(filter);
46 | }
47 | });
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_dialog_bluetooth.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
18 |
19 |
22 |
23 |
27 |
28 |
31 |
32 |
35 |
36 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/utils/AN2LinuxService.java:
--------------------------------------------------------------------------------
1 | package kiwi.root.an2linuxclient.utils;
2 |
3 | import android.app.*;
4 | import android.content.Intent;
5 | import android.os.Build;
6 | import android.os.IBinder;
7 | import androidx.core.app.NotificationCompat;
8 | import kiwi.root.an2linuxclient.R;
9 | import kiwi.root.an2linuxclient.activities.MainSettingsActivity;
10 |
11 | import static kiwi.root.an2linuxclient.App.CHANNEL_ID_FOREGROUND_SERVICE;
12 | import static kiwi.root.an2linuxclient.App.NOTIFICATION_ID_FOREGROUND_SERVICE;
13 |
14 | public class AN2LinuxService extends Service {
15 |
16 | @Override
17 | public int onStartCommand(Intent intent, int flags, int startId) {
18 | do_foreground();
19 | return START_STICKY;
20 | }
21 |
22 | @Override
23 | public IBinder onBind(Intent intent) {
24 | return null;
25 | }
26 |
27 | @Override
28 | public void onDestroy() {
29 | stopSelf();
30 | stopForeground(true);
31 |
32 | super.onDestroy();
33 | }
34 |
35 | private void do_foreground() {
36 | NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(
37 | this, CHANNEL_ID_FOREGROUND_SERVICE
38 | );
39 |
40 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
41 | notificationBuilder.setCategory(Notification.CATEGORY_SERVICE);
42 | } else{
43 | notificationBuilder.setPriority(Notification.PRIORITY_MIN);
44 | }
45 | notificationBuilder.setOngoing(true);
46 | notificationBuilder.setSmallIcon(R.drawable.an2linux_icon);
47 | notificationBuilder.setTicker(getString(R.string.main_enable_service_notification_channel_name));
48 | notificationBuilder.setContentIntent(
49 | PendingIntent.getActivity(this, 0,
50 | new Intent(this, MainSettingsActivity.class),
51 | PendingIntent.FLAG_UPDATE_CURRENT)
52 | );
53 | Notification n = notificationBuilder.build();
54 |
55 | startForeground(NOTIFICATION_ID_FOREGROUND_SERVICE, n);
56 | }
57 | }
58 |
59 |
--------------------------------------------------------------------------------
/app/src/main/res/values/shared_prefs_keys.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | enabled_applications
4 | device_key_and_cert
5 | notification_settings_global
6 | notification_settings_custom
7 | privatekey
8 | certificate
9 | version_code_seen
10 | main_setup_category_key
11 | preference_enable_an2linux
12 | preference_enable_service
13 | preference_enable_disable_all_applications
14 | preference_include_notification_title
15 | preference_force_title
16 | preference_title_max_size
17 | preference_include_notification_message
18 | preference_message_max_size
19 | preference_include_notification_icon
20 | preference_icon_size
21 | preference_dont_send_if_screen_on
22 | preference_block_ongoing
23 | preference_block_foreground
24 | preference_block_group
25 | preference_block_local
26 | preference_use_custom_settings
27 | preference_min_notification_priority
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/preferences/NumberPickerPreference.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.preferences;
10 |
11 | import android.content.Context;
12 | import android.content.res.TypedArray;
13 | import android.util.AttributeSet;
14 |
15 | import androidx.annotation.Nullable;
16 | import androidx.preference.DialogPreference;
17 |
18 | import kiwi.root.an2linuxclient.R;
19 |
20 | abstract public class NumberPickerPreference extends DialogPreference {
21 |
22 | int value;
23 | private int minValue;
24 | private int maxValue;
25 | private int defaultValue;
26 |
27 | NumberPickerPreference(Context context, AttributeSet attrs,
28 | int minValue, int maxValue, int defaultValue) {
29 | super(context, attrs);
30 | this.minValue = minValue;
31 | this.maxValue = maxValue;
32 | this.defaultValue = defaultValue;
33 | setDialogLayoutResource(R.layout.numberpicker_dialog);
34 | setPositiveButtonText(android.R.string.ok);
35 | setNegativeButtonText(android.R.string.cancel);
36 | setDialogIcon(null);
37 | setDialogTitle(null);
38 | }
39 |
40 | String getSummaryString(){
41 | return String.valueOf(value);
42 | }
43 |
44 | @Override
45 | protected void onSetInitialValue(@Nullable Object defaultValue) {
46 | value = getPersistedInt(defaultValue == null ? this.defaultValue : (int) defaultValue);
47 | persistInt(value);
48 | }
49 |
50 | @Override
51 | protected Object onGetDefaultValue(TypedArray a, int index) {
52 | return a.getInt(index, defaultValue);
53 | }
54 |
55 | int getValue() {
56 | return value;
57 | }
58 |
59 | int getMinValue() {
60 | return minValue;
61 | }
62 |
63 | int getMaxValue() {
64 | return maxValue;
65 | }
66 |
67 | void saveValue(int value) {
68 | this.value = value;
69 | findPreferenceInHierarchy(getKey()).setSummary(getSummaryString());
70 | persistInt(value);
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/data/BluetoothServer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.data;
10 |
11 | import java.security.cert.Certificate;
12 |
13 | public class BluetoothServer extends Server {
14 |
15 | private String bluetoothMacAddress;
16 | private String bluetoothName;
17 |
18 | BluetoothServer(){
19 | }
20 |
21 | /**Add server to database existing certificate*/
22 | public BluetoothServer(String bluetoothMacAddress,
23 | String bluetoothName){
24 | this.bluetoothMacAddress = bluetoothMacAddress;
25 | this.bluetoothName = bluetoothName;
26 | }
27 |
28 | /**Add server to database new certificate*/
29 | public BluetoothServer(Certificate certificate,
30 | String bluetoothMacAddress,
31 | String bluetoothName){
32 | this.certificate = certificate;
33 | this.bluetoothMacAddress = bluetoothMacAddress;
34 | this.bluetoothName = bluetoothName;
35 | }
36 |
37 | /**Update server in database existing certificate*/
38 | public BluetoothServer(long id,
39 | String bluetoothName){
40 | this.id = id;
41 | this.bluetoothName = bluetoothName;
42 | }
43 |
44 | /**Update server in database new certificate*/
45 | public BluetoothServer(long id,
46 | Certificate certificate,
47 | String bluetoothName){
48 | this.id = id;
49 | this.certificate = certificate;
50 | this.bluetoothName = bluetoothName;
51 | }
52 |
53 | void setBluetoothMacAddress(String bluetoothMacAddress) {
54 | this.bluetoothMacAddress = bluetoothMacAddress;
55 | }
56 |
57 | void setBluetoothName(String bluetoothName) {
58 | this.bluetoothName = bluetoothName;
59 | }
60 |
61 | public String getBluetoothMacAddress() {
62 | return this.bluetoothMacAddress;
63 | }
64 |
65 | public String getBluetoothName() {
66 | return this.bluetoothName;
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/utils/AN2LinuxTileService.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.utils;
10 |
11 | import android.content.Context;
12 | import android.content.SharedPreferences;
13 | import android.os.Build;
14 | import android.preference.PreferenceManager;
15 | import android.service.quicksettings.Tile;
16 | import android.service.quicksettings.TileService;
17 | import androidx.annotation.RequiresApi;
18 |
19 | import kiwi.root.an2linuxclient.R;
20 |
21 | @RequiresApi(Build.VERSION_CODES.N)
22 | public class AN2LinuxTileService extends TileService {
23 |
24 | @Override
25 | public void onStartListening() {
26 | super.onStartListening();
27 |
28 | Context c = getApplicationContext();
29 | boolean an2linuxEnabled = PreferenceManager.getDefaultSharedPreferences(c)
30 | .getBoolean(c.getString(R.string.preference_enable_an2linux), false);
31 |
32 | Tile tile = getQsTile();
33 |
34 | if (an2linuxEnabled) {
35 | tile.setState(Tile.STATE_ACTIVE);
36 | } else {
37 | tile.setState(Tile.STATE_INACTIVE);
38 | }
39 | tile.updateTile();
40 | }
41 |
42 | @Override
43 | public void onClick() {
44 | super.onClick();
45 |
46 | Context c = getApplicationContext();
47 |
48 | SharedPreferences sharedPrefsDefault = PreferenceManager.getDefaultSharedPreferences(c);
49 | boolean an2linuxEnabled = sharedPrefsDefault.getBoolean(c.getString(R.string.preference_enable_an2linux), false);
50 |
51 | Tile tile = getQsTile();
52 | SharedPreferences.Editor edit = sharedPrefsDefault.edit();
53 |
54 | if (an2linuxEnabled) {
55 | tile.setState(Tile.STATE_INACTIVE);
56 | edit.putBoolean(c.getString(R.string.preference_enable_an2linux), false);
57 | } else {
58 | tile.setState(Tile.STATE_ACTIVE);
59 | edit.putBoolean(c.getString(R.string.preference_enable_an2linux), true);
60 | }
61 | tile.updateTile();
62 | edit.apply();
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/crypto/RsaHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.crypto;
10 |
11 | import android.content.Context;
12 | import android.content.SharedPreferences;
13 | import android.util.Base64;
14 | import android.util.Log;
15 |
16 | import java.security.KeyFactory;
17 | import java.security.KeyPair;
18 | import java.security.KeyPairGenerator;
19 | import java.security.PrivateKey;
20 | import java.security.spec.PKCS8EncodedKeySpec;
21 |
22 | import kiwi.root.an2linuxclient.R;
23 |
24 | import static android.content.Context.MODE_PRIVATE;
25 |
26 | class RsaHelper {
27 |
28 | static void initialiseRsaKeyAndCert(Context c){
29 | try {
30 | SharedPreferences deviceKeyPref = c.getSharedPreferences(
31 | c.getString(R.string.device_key_and_cert), MODE_PRIVATE);
32 | KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
33 | kpg.initialize(4096);
34 | KeyPair keyPair = kpg.generateKeyPair();
35 | deviceKeyPref.edit().putString(c.getString(R.string.privatekey),
36 | Base64.encodeToString(keyPair.getPrivate().getEncoded(), Base64.NO_WRAP)).apply();
37 | Log.d("RsaHelper", "Generated new keypair successfully");
38 | TlsHelper.initialiseCertificate(c, keyPair);
39 | } catch (Exception e){
40 | Log.e("RsaHelper", "initialiseRsaKeyAndCert");
41 | Log.e("StackTrace", Log.getStackTraceString(e));
42 | }
43 | }
44 |
45 | static PrivateKey getPrivateKey(Context c){
46 | try {
47 | SharedPreferences deviceKeyPref = c.getSharedPreferences(c.getString(R.string.device_key_and_cert), MODE_PRIVATE);
48 | byte[] privateKeyBytes = Base64.decode(deviceKeyPref.getString(c.getString(R.string.privatekey), ""), Base64.DEFAULT);
49 | return KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes));
50 | } catch (Exception e) {
51 | Log.e("RsaHelper", "getPrivateKey");
52 | Log.e("StackTrace", Log.getStackTraceString(e));
53 | return null;
54 | }
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_server_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
17 |
18 |
24 |
25 |
29 |
30 |
35 |
36 |
41 |
42 |
48 |
49 |
50 |
51 |
59 |
60 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/data/Server.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.data;
10 |
11 | import android.util.Log;
12 |
13 | import org.spongycastle.cert.X509CertificateHolder;
14 | import org.spongycastle.cert.jcajce.JcaX509CertificateConverter;
15 |
16 | import java.security.cert.Certificate;
17 | import java.security.cert.CertificateEncodingException;
18 |
19 | public abstract class Server implements Comparable {
20 |
21 | long id;
22 | private boolean isEnabled;
23 | Certificate certificate;
24 | private long certificateId;
25 |
26 | public void setId(long id) {
27 | this.id = id;
28 | }
29 |
30 | public void setIsEnabled(boolean isEnabled) {
31 | this.isEnabled = isEnabled;
32 | }
33 |
34 | public void setCertificate(byte[] certificateBytes){
35 | try {
36 | X509CertificateHolder certificateHolder = new X509CertificateHolder(certificateBytes);
37 | this.certificate = new JcaX509CertificateConverter().getCertificate(certificateHolder);
38 | } catch (Exception e) {
39 | Log.e("Server", "setCertificate");
40 | Log.e("StackTrace", Log.getStackTraceString(e));
41 | }
42 | }
43 |
44 | void setCertificateId(long certificateId){
45 | this.certificateId = certificateId;
46 | }
47 |
48 | public long getId() {
49 | return this.id;
50 | }
51 |
52 | public boolean isEnabled() {
53 | return this.isEnabled;
54 | }
55 |
56 | public Certificate getCertificate(){
57 | return this.certificate;
58 | }
59 |
60 | byte[] getCertificateBytes(){
61 | try {
62 | return this.certificate.getEncoded();
63 | } catch (CertificateEncodingException e){
64 | Log.e("Server", "getCertificateBytes");
65 | Log.e("StackTrace", Log.getStackTraceString(e));
66 | return null;
67 | }
68 | }
69 |
70 | public long getCertificateId(){
71 | return certificateId;
72 | }
73 |
74 | @Override
75 | public int compareTo(Server server) {
76 | return Long.valueOf(this.id).compareTo(server.getId());
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/data/WifiServer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.data;
10 |
11 | import java.security.cert.Certificate;
12 |
13 | public class WifiServer extends TcpServer {
14 |
15 | private String ssidWhitelist;
16 |
17 | WifiServer(){
18 | }
19 |
20 | /**Add server to database existing certificate*/
21 | public WifiServer(String ipOrHostname,
22 | int portNumber,
23 | String ssidWhitelist){
24 | this.ipOrHostname = ipOrHostname;
25 | this.portNumber = portNumber;
26 | this.ssidWhitelist = ssidWhitelist;
27 | }
28 |
29 | /**Add server to database new certificate*/
30 | public WifiServer(Certificate certificate,
31 | String ipOrHostname,
32 | int portNumber,
33 | String ssidWhitelist){
34 | this.certificate = certificate;
35 | this.ipOrHostname = ipOrHostname;
36 | this.portNumber = portNumber;
37 | this.ssidWhitelist = ssidWhitelist;
38 | }
39 |
40 | /**Update server in database existing certificate*/
41 | public WifiServer(long id,
42 | String ipOrHostname,
43 | int portNumber,
44 | String ssidWhitelist){
45 | this.id = id;
46 | this.ipOrHostname = ipOrHostname;
47 | this.portNumber = portNumber;
48 | this.ssidWhitelist = ssidWhitelist;
49 | }
50 |
51 | /**Update server in database new certificate*/
52 | public WifiServer(long id,
53 | Certificate certificate,
54 | String ipOrHostname,
55 | int portNumber,
56 | String ssidWhitelist){
57 | this.id = id;
58 | this.certificate = certificate;
59 | this.ipOrHostname = ipOrHostname;
60 | this.portNumber = portNumber;
61 | this.ssidWhitelist = ssidWhitelist;
62 | }
63 |
64 | void setSsidWhitelist(String ssidWhitelist) {
65 | this.ssidWhitelist = ssidWhitelist;
66 | }
67 |
68 | public String getSsidWhitelist() {
69 | return this.ssidWhitelist;
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/crypto/Sha256Helper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.crypto;
10 |
11 | import android.util.Log;
12 |
13 | import java.security.MessageDigest;
14 | import java.util.Formatter;
15 |
16 | public class Sha256Helper {
17 |
18 | public static byte[] sha256(byte[] bytesToHash){
19 | try {
20 | MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
21 | sha256.update(bytesToHash);
22 | return sha256.digest();
23 | } catch (Exception e){
24 | Log.e("Sha256Helper", "sha256");
25 | Log.e("StackTrace", Log.getStackTraceString(e));
26 | return null;
27 | }
28 | }
29 |
30 | public static byte[] sha256(byte[] bytesToHash, byte[] moreBytesToHash){
31 | try {
32 | MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
33 | sha256.update(bytesToHash);
34 | sha256.update(moreBytesToHash);
35 | return sha256.digest();
36 | } catch (Exception e){
37 | Log.e("Sha256Helper", "sha256");
38 | Log.e("StackTrace", Log.getStackTraceString(e));
39 | return null;
40 | }
41 | }
42 |
43 | public static String getFourLineHexString(byte[] sha256Hash){
44 | Formatter formatter = new Formatter();
45 | for (int i = 0; i < 32; i++) {
46 | formatter.format("%02X", sha256Hash[i]);
47 | if (i == 7 || i == 15 || i == 23) {
48 | formatter.format("\n");
49 | } else if (i != 31) {
50 | formatter.format(" ");
51 | }
52 | }
53 | return formatter.toString();
54 | }
55 |
56 | public static String getFourLineHexString(String hexString){
57 | Formatter formatter = new Formatter();
58 | for (int i = 0; i < 64; i+=2) {
59 | formatter.format(hexString.substring(i, i+2).toUpperCase());
60 | if (i == 14 || i == 30 || i == 46) {
61 | formatter.format("\n");
62 | } else if (i != 62) {
63 | formatter.format(" ");
64 | }
65 | }
66 | return formatter.toString();
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/data/MobileServer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.data;
10 |
11 | import java.security.cert.Certificate;
12 |
13 | public class MobileServer extends TcpServer {
14 |
15 | private boolean roamingAllowed;
16 |
17 | MobileServer(){
18 | }
19 |
20 | /**Add server to database existing certificate*/
21 | public MobileServer(String ipOrHostname,
22 | int portNumber,
23 | boolean roamingAllowed){
24 | this.ipOrHostname = ipOrHostname;
25 | this.portNumber = portNumber;
26 | this.roamingAllowed = roamingAllowed;
27 | }
28 |
29 | /**Add server to database new certificate*/
30 | public MobileServer(Certificate certificate,
31 | String ipOrHostname,
32 | int portNumber,
33 | boolean roamingAllowed){
34 | this.certificate = certificate;
35 | this.ipOrHostname = ipOrHostname;
36 | this.portNumber = portNumber;
37 | this.roamingAllowed = roamingAllowed;
38 | }
39 |
40 | /**Update server in database existing certificate*/
41 | public MobileServer(long id,
42 | String ipOrHostname,
43 | int portNumber,
44 | boolean roamingAllowed){
45 | this.id = id;
46 | this.ipOrHostname = ipOrHostname;
47 | this.portNumber = portNumber;
48 | this.roamingAllowed = roamingAllowed;
49 | }
50 |
51 | /**Update server in database new certificate*/
52 | public MobileServer(long id,
53 | Certificate certificate,
54 | String ipOrHostname,
55 | int portNumber,
56 | boolean roamingAllowed){
57 | this.id = id;
58 | this.certificate = certificate;
59 | this.ipOrHostname = ipOrHostname;
60 | this.portNumber = portNumber;
61 | this.roamingAllowed = roamingAllowed;
62 | }
63 |
64 | void setRoamingAllowed(boolean roamingAllowed) {
65 | this.roamingAllowed = roamingAllowed;
66 | }
67 |
68 | public boolean isRoamingAllowed() {
69 | return this.roamingAllowed;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/crypto/KeyGeneratorService.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.crypto;
10 |
11 | import android.app.IntentService;
12 | import android.app.Notification;
13 | import android.app.PendingIntent;
14 | import android.content.Context;
15 | import android.content.Intent;
16 |
17 | import androidx.core.app.NotificationCompat;
18 | import androidx.localbroadcastmanager.content.LocalBroadcastManager;
19 |
20 | import kiwi.root.an2linuxclient.R;
21 | import kiwi.root.an2linuxclient.activities.ClientCertificateActivity;
22 |
23 | import static kiwi.root.an2linuxclient.App.CHANNEL_ID_GEN;
24 | import static kiwi.root.an2linuxclient.App.NOTIFICATION_ID_GEN;
25 |
26 | public class KeyGeneratorService extends IntentService {
27 |
28 |
29 | public static String BROADCAST_ACTION = "kiwi.root.an2linuxclient.crypto.KEY_GENERATOR_COMPLETED";
30 | public static boolean currentlyGenerating;
31 |
32 | public KeyGeneratorService() {
33 | super("KeyGeneratorService");
34 | }
35 |
36 | @Override
37 | protected void onHandleIntent(Intent workIntent) {
38 | Intent notificationIntent = new Intent(this, ClientCertificateActivity.class);
39 | PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
40 | Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID_GEN)
41 | .setSmallIcon(R.mipmap.ic_launcher)
42 | .setContentTitle(getString(R.string.generate_key_working))
43 | .setContentTitle(getString(R.string.generate_key_working_notification))
44 | .setPriority(NotificationCompat.PRIORITY_LOW)
45 | .setContentIntent(pendingIntent)
46 | .build();
47 | startForeground(NOTIFICATION_ID_GEN, notification);
48 |
49 | RsaHelper.initialiseRsaKeyAndCert(getApplicationContext());
50 | currentlyGenerating = false;
51 |
52 | stopForeground(true);
53 | LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(BROADCAST_ACTION));
54 | }
55 |
56 | public static void startGenerate(Context c) {
57 | currentlyGenerating = true;
58 | c.startService(new Intent(c, KeyGeneratorService.class));
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/preferences/NumberPickerPreferenceDialog.java:
--------------------------------------------------------------------------------
1 | package kiwi.root.an2linuxclient.preferences;
2 |
3 | import android.content.res.Resources;
4 | import android.os.Bundle;
5 | import android.view.View;
6 | import android.view.Window;
7 | import android.widget.Button;
8 | import android.widget.NumberPicker;
9 |
10 | import androidx.preference.PreferenceDialogFragmentCompat;
11 |
12 | import kiwi.root.an2linuxclient.R;
13 |
14 | public class NumberPickerPreferenceDialog extends PreferenceDialogFragmentCompat {
15 |
16 | private NumberPicker numberPicker;
17 |
18 | public static NumberPickerPreferenceDialog newInstance(String prefKey) {
19 | NumberPickerPreferenceDialog fragment = new NumberPickerPreferenceDialog();
20 | Bundle bundle = new Bundle(1);
21 | bundle.putString("key", prefKey);
22 | fragment.setArguments(bundle);
23 | return fragment;
24 | }
25 |
26 | @Override
27 | public void onStart() {
28 | super.onStart();
29 | // Need to do this here, since getDialog() returns null in for example onBindDialogView()
30 | final Resources res = getContext().getResources();
31 | final Window window = getDialog().getWindow();
32 | Button button1 = window.findViewById(android.R.id.button1);
33 | Button button2 = window.findViewById(android.R.id.button2);
34 | button1.setTextColor(res.getColor(R.color.black));
35 | button2.setTextColor(res.getColor(R.color.black));
36 | }
37 |
38 | @Override
39 | protected void onBindDialogView(View view) {
40 | super.onBindDialogView(view);
41 | NumberPickerPreference npp = getNumberPickerPreference();
42 | numberPicker = view.findViewById(R.id.numberPicker);
43 | numberPicker.setMinValue(npp.getMinValue());
44 | numberPicker.setMaxValue(npp.getMaxValue());
45 | numberPicker.setValue(npp.getValue());
46 | }
47 |
48 | @Override
49 | public void onDialogClosed(boolean positiveResult) {
50 | if (positiveResult) {
51 | getNumberPickerPreference().saveValue(numberPicker.getValue());
52 | }
53 | }
54 |
55 | @Override
56 | public void onPause() {
57 | super.onPause();
58 | dismiss();
59 | }
60 |
61 | private NumberPickerPreference getNumberPickerPreference() {
62 | return (NumberPickerPreference) getPreference();
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/adapters/BluetoothPairedDevicesAdapter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.adapters;
10 |
11 | import android.app.Activity;
12 | import android.app.FragmentManager;
13 | import android.bluetooth.BluetoothDevice;
14 | import android.content.Context;
15 | import android.view.LayoutInflater;
16 | import android.view.View;
17 | import android.view.ViewGroup;
18 | import android.widget.ArrayAdapter;
19 | import android.widget.Button;
20 | import android.widget.TextView;
21 |
22 | import java.util.ArrayList;
23 |
24 | import kiwi.root.an2linuxclient.R;
25 | import kiwi.root.an2linuxclient.views.BluetoothDialogNew;
26 | import kiwi.root.an2linuxclient.views.BluetoothPairedListDialog;
27 |
28 |
29 | public class BluetoothPairedDevicesAdapter extends ArrayAdapter {
30 | private BluetoothPairedListDialog dialog;
31 |
32 | public BluetoothPairedDevicesAdapter(Context context, ArrayList pairedBluetoothList, BluetoothPairedListDialog dialog) {
33 | super(context, 0, pairedBluetoothList);
34 | this.dialog = dialog;
35 | }
36 |
37 | @Override
38 | public View getView(final int position, View convertView, ViewGroup parent) {
39 | final BluetoothDevice device = getItem(position);
40 | // Check if an existing view is being reused, otherwise inflate the view
41 | if (convertView == null) {
42 | convertView = LayoutInflater.from(getContext()).inflate(R.layout.view_bluetooth_item, parent, false);
43 | }
44 |
45 | Button bluetoothEditBtn = (Button) convertView.findViewById(R.id.bluetoothEditBtn);
46 | TextView btDeviceNameText = (TextView) convertView.findViewById(R.id.btDeviceNameText);
47 | TextView btMacText = (TextView) convertView.findViewById(R.id.btMacText);
48 |
49 | btDeviceNameText.setText(device.getName());
50 | btMacText.setText(device.getAddress());
51 |
52 | bluetoothEditBtn.setOnClickListener(v -> {
53 | FragmentManager manager = ((Activity) getContext()).getFragmentManager();
54 | BluetoothDialogNew myDialog = BluetoothDialogNew.newInstance(device.getName(), device.getAddress());
55 | myDialog.setCancelable(false);
56 | myDialog.show(manager, "bluetooth");
57 | dialog.dismiss();
58 | });
59 |
60 | return convertView;
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/views/BluetoothPairedListDialog.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.views;
10 |
11 | import android.app.DialogFragment;
12 | import android.bluetooth.BluetoothAdapter;
13 | import android.bluetooth.BluetoothClass;
14 | import android.bluetooth.BluetoothDevice;
15 | import android.os.Bundle;
16 | import android.view.LayoutInflater;
17 | import android.view.View;
18 | import android.view.ViewGroup;
19 | import android.view.Window;
20 | import android.widget.ListView;
21 | import android.widget.Toast;
22 |
23 | import java.util.ArrayList;
24 | import java.util.Set;
25 |
26 | import kiwi.root.an2linuxclient.R;
27 | import kiwi.root.an2linuxclient.adapters.BluetoothPairedDevicesAdapter;
28 |
29 | public class BluetoothPairedListDialog extends DialogFragment {
30 |
31 | @Override
32 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
33 | getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
34 |
35 | View view = inflater.inflate(R.layout.view_add_bluetooth_server, container);
36 |
37 | ListView listViewBtPairedPCs = (ListView) view.findViewById(R.id.listViewBtPairedPCs);
38 |
39 | ArrayList pairedBluetoothList = new ArrayList<>();
40 |
41 | BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
42 | Set pairedDevices = bluetoothAdapter.getBondedDevices();
43 |
44 | if (pairedDevices.size() > 0) {
45 | for (BluetoothDevice device : pairedDevices) {
46 | if(device.getBluetoothClass().getMajorDeviceClass() == BluetoothClass.Device.Major.COMPUTER) {
47 | pairedBluetoothList.add(device);
48 | }
49 | }
50 | if (pairedBluetoothList.size() == 0) {
51 | Toast.makeText(getActivity().getApplicationContext(), R.string.bluetooth_no_paired_found, Toast.LENGTH_LONG).show();
52 | return null;
53 | }
54 | } else {
55 | Toast.makeText(getActivity().getApplicationContext(), R.string.bluetooth_no_paired_found, Toast.LENGTH_LONG).show();
56 | return null;
57 | }
58 | BluetoothPairedDevicesAdapter adapter = new BluetoothPairedDevicesAdapter(getActivity(), pairedBluetoothList, this);
59 | listViewBtPairedPCs.setAdapter(adapter);
60 | return view;
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/views/TcpServerDialog.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.views;
10 |
11 | import android.os.Bundle;
12 | import android.view.View;
13 | import android.widget.EditText;
14 |
15 | import kiwi.root.an2linuxclient.R;
16 | import kiwi.root.an2linuxclient.data.Server;
17 | import kiwi.root.an2linuxclient.data.TcpServer;
18 |
19 | abstract class TcpServerDialog extends ServerDialog {
20 |
21 | EditText ipOrHostnameEditText;
22 | EditText portNumberEditText;
23 |
24 | String ipOrHostname;
25 | int portNumber;
26 |
27 | @Override
28 | public void onSaveInstanceState(Bundle outState) {
29 | outState.putBoolean("ipOrHostnameEditTextIsEnabled", ipOrHostnameEditText.isEnabled());
30 | outState.putBoolean("portNumberEditTextIsEnabled", portNumberEditText.isEnabled());
31 | super.onSaveInstanceState(outState);
32 | }
33 |
34 | void resetAfterFailedPairingConnection(){
35 | getActivity().runOnUiThread(() -> {
36 | ipOrHostnameEditText.setEnabled(true);
37 | portNumberEditText.setEnabled(true);
38 | initiatePairingButton.setVisibility(View.VISIBLE);
39 | initiatePairingButton.setText(R.string.try_again);
40 | if (certificateSpinner != null){
41 | certificateSpinner.setVisibility(View.VISIBLE);
42 | }
43 | saveServerBtn.setEnabled(true);
44 |
45 | if (connectionHandler != null){
46 | connectionHandler.cancel();
47 | }
48 | });
49 | }
50 |
51 | @Override
52 | void initViews(View v){
53 | super.initViews(v);
54 | ipOrHostnameEditText = (EditText) v.findViewById(R.id.ipOrHostname);
55 | portNumberEditText = (EditText) v.findViewById(R.id.portNumber);
56 | }
57 |
58 | @Override
59 | void initViewsDialogEdit(View v, Server tcpServer, int serverListPosition) {
60 | super.initViewsDialogEdit(v, tcpServer, serverListPosition);
61 | ipOrHostnameEditText.setText(((TcpServer)tcpServer).getIpOrHostname());
62 | portNumberEditText.setText(String.valueOf(((TcpServer)tcpServer).getPortNumber()));
63 | }
64 |
65 | void initViewsRetainedInstance(Bundle savedInstanceState){
66 | super.initViewsRetainedInstance(savedInstanceState);
67 | if (savedInstanceState != null){
68 | ipOrHostnameEditText.setEnabled(savedInstanceState.getBoolean("ipOrHostnameEditTextIsEnabled"));
69 | portNumberEditText.setEnabled(savedInstanceState.getBoolean("portNumberEditTextIsEnabled"));
70 | }
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/App.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient;
10 |
11 | import android.app.Application;
12 | import android.app.Notification;
13 | import android.app.NotificationChannel;
14 | import android.app.NotificationManager;
15 | import android.graphics.Color;
16 | import android.os.Build;
17 | import androidx.annotation.RequiresApi;
18 |
19 | public class App extends Application {
20 |
21 | public final static String CHANNEL_ID_FOREGROUND_SERVICE = "AN2LinuxForegroundServiceChannel";
22 | public final static int NOTIFICATION_ID_FOREGROUND_SERVICE = 1;
23 |
24 | public final static String CHANNEL_ID_INFORMATION = "AN2LinuxInformationChannel";
25 | public final static int NOTIFICATION_ID_HIDE_FOREGROUND_NOTIF = 2;
26 | public static final int NOTIFICATION_ID_TEST_NOTIF = 3;
27 |
28 | public static final String CHANNEL_ID_GEN = "AN2LinuxKeyGenChannel";
29 | public static final int NOTIFICATION_ID_GEN = 4;
30 |
31 | @Override
32 | public void onCreate() {
33 | super.onCreate();
34 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
35 | createNotificationChannels();
36 | }
37 | }
38 |
39 | @RequiresApi(Build.VERSION_CODES.O)
40 | private void createNotificationChannels() {
41 | NotificationChannel foregroundServiceChan = new NotificationChannel(
42 | CHANNEL_ID_FOREGROUND_SERVICE,
43 | getString(R.string.main_enable_service_notification_channel_name),
44 | NotificationManager.IMPORTANCE_MIN
45 | );
46 | foregroundServiceChan.setLightColor(Color.GREEN);
47 | foregroundServiceChan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
48 |
49 | NotificationChannel infoChan = new NotificationChannel(CHANNEL_ID_INFORMATION,
50 | getString(R.string.main_enable_service_information_notification_channel_name), NotificationManager.IMPORTANCE_LOW);
51 | infoChan.setLightColor(Color.GREEN);
52 | infoChan.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
53 |
54 | NotificationChannel keyGenChannel = new NotificationChannel(
55 | CHANNEL_ID_GEN,
56 | getString(R.string.generate_key_notification_channel_name),
57 | NotificationManager.IMPORTANCE_LOW
58 | );
59 |
60 | NotificationManager notificationManager = getSystemService(NotificationManager.class);
61 | notificationManager.createNotificationChannel(foregroundServiceChan);
62 | notificationManager.createNotificationChannel(infoChan);
63 | notificationManager.createNotificationChannel(keyGenChannel);
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_custom_notification_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
29 |
30 |
41 |
42 |
54 |
55 |
56 |
57 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/adapters/CustomNotificationSettingsAdapter.java:
--------------------------------------------------------------------------------
1 | package kiwi.root.an2linuxclient.adapters;
2 |
3 | import android.view.LayoutInflater;
4 | import android.view.View;
5 | import android.view.ViewGroup;
6 | import android.widget.ImageView;
7 | import android.widget.TextView;
8 |
9 | import androidx.annotation.NonNull;
10 | import androidx.recyclerview.widget.RecyclerView;
11 |
12 | import java.util.List;
13 |
14 | import kiwi.root.an2linuxclient.R;
15 | import kiwi.root.an2linuxclient.data.CustomSettingsAppData;
16 | import kiwi.root.an2linuxclient.interfaces.OnItemClickListener;
17 |
18 | public class CustomNotificationSettingsAdapter extends RecyclerView.Adapter {
19 |
20 | private List appDataList;
21 |
22 | class AppDataViewHolder extends RecyclerView.ViewHolder {
23 | private ImageView appIcon;
24 | private TextView appLabelTextView;
25 | private TextView usingCustomTextView;
26 | private String usingCustomText;
27 |
28 | private AppDataViewHolder(@NonNull View itemView) {
29 | super(itemView);
30 | appIcon = itemView.findViewById(R.id.appIcon);
31 | appLabelTextView = itemView.findViewById(R.id.appLabelTextView);
32 | usingCustomTextView = itemView.findViewById(R.id.usingCustomTextView);
33 | usingCustomText = itemView.getContext().getString(R.string.notif_custom_using_custom_settings);
34 | }
35 |
36 | private void bind(final CustomSettingsAppData appData, final OnItemClickListener onItemClickListener) {
37 | appIcon.setImageDrawable(appData.appIcon);
38 | appLabelTextView.setText(appData.appName);
39 | if (appData.isUsingCustomSettings) {
40 | usingCustomTextView.setText(usingCustomText);
41 | } else {
42 | usingCustomTextView.setText("");
43 | }
44 |
45 | itemView.setOnClickListener(view -> onItemClickListener.onItemClick(appData));
46 | }
47 | }
48 |
49 | private final OnItemClickListener onItemClickListener;
50 |
51 | public CustomNotificationSettingsAdapter(OnItemClickListener onItemClickListener) {
52 | this.onItemClickListener = onItemClickListener;
53 | }
54 |
55 | @NonNull
56 | @Override
57 | public AppDataViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
58 |
59 | View itemView = LayoutInflater.from(parent.getContext())
60 | .inflate(R.layout.custom_notification_settings_recyclerview_item, parent, false);
61 | return new AppDataViewHolder(itemView);
62 | }
63 |
64 | @Override
65 | public void onBindViewHolder(@NonNull AppDataViewHolder holder, int position) {
66 | holder.bind(appDataList.get(position), onItemClickListener);
67 | }
68 |
69 | @Override
70 | public int getItemCount() {
71 | if (appDataList == null) {
72 | return 0;
73 | }
74 |
75 | return appDataList.size();
76 | }
77 |
78 | public void setAppDataList(List appDataList) {
79 | this.appDataList = appDataList;
80 | notifyDataSetChanged();
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/network/NotificationConnectionHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.network;
10 |
11 | import android.bluetooth.BluetoothAdapter;
12 | import android.content.Context;
13 | import android.net.ConnectivityManager;
14 | import android.net.NetworkInfo;
15 |
16 | import java.util.List;
17 |
18 | import kiwi.root.an2linuxclient.data.BluetoothServer;
19 | import kiwi.root.an2linuxclient.data.Notification;
20 | import kiwi.root.an2linuxclient.data.MobileServer;
21 | import kiwi.root.an2linuxclient.data.WifiServer;
22 | import kiwi.root.an2linuxclient.utils.ConnectionHelper;
23 |
24 | class NotificationConnectionHandler {
25 |
26 | static void sendToAllEnabledWifiServers(Notification n, Context c, List enabledWifiServers){
27 | ConnectivityManager connMgr = (ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE);
28 | NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
29 | if (networkInfo != null && networkInfo.isConnected() && networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
30 | for(WifiServer wifiServer : enabledWifiServers) {
31 | if (ConnectionHelper.checkIfSsidIsAllowed(wifiServer.getSsidWhitelist(), c)){
32 | ThreadPoolHandler.enqueueRunnable(new TcpNotificationConnection(c, n,
33 | wifiServer.getCertificate(),
34 | wifiServer.getIpOrHostname(),
35 | wifiServer.getPortNumber()));
36 | }
37 | }
38 | }
39 | }
40 |
41 | static void sendToAllEnabledMobileServers(Notification n, Context c, List enabledMobileServers){
42 | ConnectivityManager connMgr = (ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE);
43 | NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
44 | if (networkInfo != null && networkInfo.isConnected() && networkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
45 | for(MobileServer mobileServer : enabledMobileServers){
46 | if (!networkInfo.isRoaming() || mobileServer.isRoamingAllowed()){
47 | ThreadPoolHandler.enqueueRunnable(new TcpNotificationConnection(c, n,
48 | mobileServer.getCertificate(),
49 | mobileServer.getIpOrHostname(),
50 | mobileServer.getPortNumber()));
51 | }
52 | }
53 | }
54 | }
55 |
56 | static void sendToAllEnabledBluetoothServers(Notification n, Context c, List enabledBluetoothServers){
57 | if (BluetoothAdapter.getDefaultAdapter() != null && BluetoothAdapter.getDefaultAdapter().isEnabled()){
58 | for(BluetoothServer bluetoothServer : enabledBluetoothServers){
59 | ThreadPoolHandler.enqueueBtConn(new BluetoothNotificationConnection(c, n,
60 | bluetoothServer.getCertificate(),
61 | bluetoothServer.getBluetoothMacAddress()));
62 | }
63 | }
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.gitignore.io/api/androidstudio
2 | # Edit at https://www.gitignore.io/?templates=androidstudio
3 |
4 | ### AndroidStudio ###
5 | # Covers files to be ignored for android development using Android Studio.
6 |
7 | # Built application files
8 | *.apk
9 | *.ap_
10 |
11 | # Files for the ART/Dalvik VM
12 | *.dex
13 |
14 | # Java class files
15 | *.class
16 |
17 | # Generated files
18 | bin/
19 | gen/
20 | out/
21 |
22 | # Gradle files
23 | .gradle
24 | .gradle/
25 | build/
26 |
27 | # Signing files
28 | .signing/
29 |
30 | # Local configuration file (sdk path, etc)
31 | local.properties
32 |
33 | # Proguard folder generated by Eclipse
34 | proguard/
35 |
36 | # Log Files
37 | *.log
38 |
39 | # Android Studio
40 | /*/build/
41 | /*/local.properties
42 | /*/out
43 | /*/*/build
44 | /*/*/production
45 | captures/
46 | .navigation/
47 | *.ipr
48 | *~
49 | *.swp
50 |
51 | # Android Patch
52 | gen-external-apklibs
53 |
54 | # External native build folder generated in Android Studio 2.2 and later
55 | .externalNativeBuild
56 |
57 | # NDK
58 | obj/
59 |
60 | # IntelliJ IDEA
61 | *.iml
62 | *.iws
63 | /out/
64 |
65 | # User-specific configurations
66 | .idea/caches/
67 | .idea/libraries/
68 | .idea/shelf/
69 | .idea/workspace.xml
70 | .idea/tasks.xml
71 | .idea/.name
72 | .idea/compiler.xml
73 | .idea/copyright/profiles_settings.xml
74 | .idea/encodings.xml
75 | .idea/misc.xml
76 | .idea/modules.xml
77 | .idea/scopes/scope_settings.xml
78 | .idea/dictionaries
79 | .idea/vcs.xml
80 | .idea/jsLibraryMappings.xml
81 | .idea/datasources.xml
82 | .idea/dataSources.ids
83 | .idea/sqlDataSources.xml
84 | .idea/dynamic.xml
85 | .idea/uiDesigner.xml
86 | .idea/assetWizardSettings.xml
87 |
88 | # OS-specific files
89 | .DS_Store
90 | .DS_Store?
91 | ._*
92 | .Spotlight-V100
93 | .Trashes
94 | ehthumbs.db
95 | Thumbs.db
96 |
97 | # Legacy Eclipse project files
98 | .classpath
99 | .project
100 | .cproject
101 | .settings/
102 |
103 | # Mobile Tools for Java (J2ME)
104 | .mtj.tmp/
105 |
106 | # Package Files #
107 | *.war
108 | *.ear
109 |
110 | # virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml)
111 | hs_err_pid*
112 |
113 | ## Plugin-specific files:
114 |
115 | # mpeltonen/sbt-idea plugin
116 | .idea_modules/
117 |
118 | # JIRA plugin
119 | atlassian-ide-plugin.xml
120 |
121 | # Mongo Explorer plugin
122 | .idea/mongoSettings.xml
123 |
124 | # Crashlytics plugin (for Android Studio and IntelliJ)
125 | com_crashlytics_export_strings.xml
126 | crashlytics.properties
127 | crashlytics-build.properties
128 | fabric.properties
129 |
130 | ### AndroidStudio Patch ###
131 |
132 | !/gradle/wrapper/gradle-wrapper.jar
133 |
134 | # End of https://www.gitignore.io/api/androidstudio
135 |
136 | # Keystore files
137 | *.jks
138 |
139 | # Statistic plugin
140 | .idea/statistic.xml
141 |
142 | .idea/gradle.xml
143 |
144 |
145 | # fastlane specific
146 | **/fastlane/report.xml
147 |
148 | # deliver temporary files
149 | **/fastlane/Preview.html
150 |
151 | # snapshot generated screenshots
152 | **/fastlane/screenshots
153 |
154 | # scan temporary files
155 | **/fastlane/test_output
156 |
157 | fastlane/key.json
158 | fastlane/.env
159 |
160 |
161 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/fragments/ClientCertificateFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.fragments;
10 |
11 | import android.app.Fragment;
12 | import android.content.BroadcastReceiver;
13 | import android.content.Context;
14 | import android.content.Intent;
15 | import android.content.IntentFilter;
16 | import android.os.Bundle;
17 | import androidx.localbroadcastmanager.content.LocalBroadcastManager;
18 | import android.view.LayoutInflater;
19 | import android.view.View;
20 | import android.view.ViewGroup;
21 | import android.widget.Button;
22 | import android.widget.TextView;
23 |
24 | import kiwi.root.an2linuxclient.R;
25 | import kiwi.root.an2linuxclient.crypto.KeyGeneratorService;
26 | import kiwi.root.an2linuxclient.crypto.Sha256Helper;
27 | import kiwi.root.an2linuxclient.crypto.TlsHelper;
28 |
29 | public class ClientCertificateFragment extends Fragment {
30 |
31 | private TextView fingerprintTextView;
32 | private Button generateNewButton;
33 | private GeneratorBroadcastReceiver receiver;
34 |
35 | @Override
36 | public void onCreate(Bundle savedInstanceState) {
37 | super.onCreate(savedInstanceState);
38 | setRetainInstance(true);
39 | }
40 |
41 | @Override
42 | public void onStart() {
43 | super.onStart();
44 | if (KeyGeneratorService.currentlyGenerating){
45 | registerReceiver();
46 | } else {
47 | setFingerprintText();
48 | }
49 | }
50 |
51 | @Override
52 | public void onStop() {
53 | super.onStop();
54 | if (receiver != null){
55 | unregisterReceiver();
56 | }
57 | }
58 |
59 | @Override
60 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
61 | View v = inflater.inflate(R.layout.activity_client_certificate, container, false);
62 | fingerprintTextView = (TextView) v.findViewById(R.id.fingerprintTextView);
63 | generateNewButton = (Button) v.findViewById(R.id.generateNewButton);
64 | generateNewButton.setOnClickListener(v1 -> {
65 | registerReceiver();
66 | KeyGeneratorService.startGenerate(getActivity());
67 | });
68 | return v;
69 | }
70 |
71 | private void setFingerprintText(){
72 | byte[] cert = TlsHelper.getCertificateBytes(getActivity());
73 | byte[] sha256 = Sha256Helper.sha256(cert);
74 | fingerprintTextView.setText(Sha256Helper.getFourLineHexString(sha256));
75 | }
76 |
77 | private void registerReceiver(){
78 | if (receiver == null){
79 | receiver = new GeneratorBroadcastReceiver();
80 | }
81 | LocalBroadcastManager.getInstance(getActivity()).registerReceiver(receiver,
82 | new IntentFilter(KeyGeneratorService.BROADCAST_ACTION));
83 | generateNewButton.setEnabled(false);
84 | fingerprintTextView.setText(R.string.generate_key_working);
85 | }
86 |
87 | private void unregisterReceiver(){
88 | LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(receiver);
89 | }
90 |
91 | private class GeneratorBroadcastReceiver extends BroadcastReceiver {
92 | @Override
93 | public void onReceive(Context context, Intent intent) {
94 | generateNewButton.setEnabled(true);
95 | setFingerprintText();
96 | unregisterReceiver();
97 | }
98 | }
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | xmlns:android
14 |
15 | ^$
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | xmlns:.*
25 |
26 | ^$
27 |
28 |
29 | BY_NAME
30 |
31 |
32 |
33 |
34 |
35 |
36 | .*:id
37 |
38 | http://schemas.android.com/apk/res/android
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | .*:name
48 |
49 | http://schemas.android.com/apk/res/android
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | name
59 |
60 | ^$
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | style
70 |
71 | ^$
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | .*
81 |
82 | ^$
83 |
84 |
85 | BY_NAME
86 |
87 |
88 |
89 |
90 |
91 |
92 | .*
93 |
94 | http://schemas.android.com/apk/res/android
95 |
96 |
97 | ANDROID_ATTRIBUTE_ORDER
98 |
99 |
100 |
101 |
102 |
103 |
104 | .*
105 |
106 | .*
107 |
108 |
109 | BY_NAME
110 |
111 |
112 |
113 |
114 |
115 |
116 |
--------------------------------------------------------------------------------
/fastlane/Fastfile:
--------------------------------------------------------------------------------
1 | # This file contains the fastlane.tools configuration
2 | # You can find the documentation at https://docs.fastlane.tools
3 | #
4 | # For a list of all available actions, check out
5 | #
6 | # https://docs.fastlane.tools/actions
7 | #
8 | # For a list of all available plugins, check out
9 | #
10 | # https://docs.fastlane.tools/plugins/available-plugins
11 | #
12 |
13 | opt_out_usage
14 | skip_docs
15 |
16 | before_all do
17 | ensure_bundle_exec
18 | ensure_git_status_clean
19 | ensure_git_branch(branch: "master")
20 | end
21 |
22 | desc "Deploy a new version to Google Play, GitHub and eventually F-Droid"
23 | lane :deploy do
24 | set_and_check_environment_variables
25 | build_signed_apk_and_aab
26 | deploy_to_play_store
27 | push_to_github_and_create_release
28 | end
29 |
30 | private_lane :set_and_check_environment_variables do
31 | UI.important "-------------------------------------------------------------"
32 | UI.important "--- Checking latest tag version and environment variables ---"
33 | UI.important "-------------------------------------------------------------"
34 |
35 | # Set $VERSION to latest tag name example: v0.9.2
36 | ENV["VERSION"] = sh(command: "git describe --abbrev=0 | tr -d '\n'", log: false)
37 | UI.error ENV["VERSION"]
38 |
39 | if not ENV["KEY_STORE_FILE"]
40 | abort "Error: $KEY_STORE_FILE not set"
41 | end
42 | if not ENV["KEY_STORE_PASSWORD"]
43 | abort "Error: $KEY_STORE_PASSWORD not set"
44 | end
45 | if not ENV["KEY_ALIAS"]
46 | abort "Error: $KEY_ALIAS not set"
47 | end
48 | if not ENV["KEY_PASSWORD"]
49 | abort "Error: $KEY_PASSWORD not set"
50 | end
51 | if not ENV["GITHUB_TOKEN"]
52 | abort "Error: $GITHUB_TOKEN not set"
53 | end
54 | if not ENV["VERSION"]
55 | abort "Error: $VERSION not set"
56 | end
57 | UI.success "Environment variables OK!"
58 | end
59 |
60 | private_lane :build_signed_apk_and_aab do
61 | UI.important "-------------------------------------------------------------"
62 | UI.important "--- Deleting the build directory, generated APKs and AABs ---"
63 | UI.important "-------------------------------------------------------------"
64 | gradle(task: "clean")
65 |
66 | UI.important "-----------------------------------"
67 | UI.important "--- Building signed APK and AAB ---"
68 | UI.important "-----------------------------------"
69 | gradle(
70 | task: "bundleRelease assembleRelease",
71 | properties: {
72 | "android.injected.signing.store.file" => ENV["KEY_STORE_FILE"],
73 | "android.injected.signing.store.password" => ENV["KEY_STORE_PASSWORD"],
74 | "android.injected.signing.key.alias" => ENV["KEY_ALIAS"],
75 | "android.injected.signing.key.password" => ENV["KEY_PASSWORD"],
76 | }
77 | )
78 | UI.success "Builds completed successfully!"
79 | end
80 |
81 | private_lane :deploy_to_play_store do
82 | UI.important "-------------------------------"
83 | UI.important "--- Uploading to Play Store ---"
84 | UI.important "-------------------------------"
85 | upload_to_play_store(skip_upload_apk: true)
86 | end
87 |
88 | private_lane :push_to_github_and_create_release do
89 | UI.important "------------------------------------------"
90 | UI.important "--- Pushing to GitHub (including tags) ---"
91 | UI.important "------------------------------------------"
92 | push_to_git_remote(remote: "github", tags: true)
93 |
94 | UI.important "-------------------------------"
95 | UI.important "--- Creating GitHub release ---"
96 | UI.important "-------------------------------"
97 | github_release = set_github_release(
98 | repository_name: "rootkiwi/an2linuxclient",
99 | api_token: ENV["GITHUB_TOKEN"],
100 | name: ENV["VERSION"],
101 | tag_name: ENV["VERSION"],
102 | description: "```\nsha256sum app-release.apk\n" + sh("sha256sum ../app/build/outputs/apk/release/app-release.apk")[0..64] + "\n```",
103 | upload_assets: ["app/build/outputs/apk/release/app-release.apk"]
104 | )
105 | end
106 |
107 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/activities/CustomNotificationSettingsActivity.java:
--------------------------------------------------------------------------------
1 | package kiwi.root.an2linuxclient.activities;
2 |
3 | import androidx.annotation.Nullable;
4 | import androidx.appcompat.app.AppCompatActivity;
5 | import androidx.constraintlayout.widget.ConstraintLayout;
6 | import androidx.lifecycle.Observer;
7 | import androidx.lifecycle.ViewModelProviders;
8 | import androidx.recyclerview.widget.DividerItemDecoration;
9 | import androidx.recyclerview.widget.LinearLayoutManager;
10 | import androidx.recyclerview.widget.RecyclerView;
11 |
12 | import android.content.Intent;
13 | import android.os.Bundle;
14 | import android.view.View;
15 |
16 | import java.util.List;
17 |
18 | import kiwi.root.an2linuxclient.R;
19 | import kiwi.root.an2linuxclient.adapters.CustomNotificationSettingsAdapter;
20 | import kiwi.root.an2linuxclient.data.CustomSettingsAppData;
21 | import kiwi.root.an2linuxclient.interfaces.OnItemClickListener;
22 | import kiwi.root.an2linuxclient.viewmodels.CustomNotificationSettingsViewModel;
23 | import kiwi.root.an2linuxclient.views.CustomProgressDialog;
24 |
25 | public class CustomNotificationSettingsActivity extends AppCompatActivity implements OnItemClickListener {
26 |
27 | private CustomNotificationSettingsViewModel viewModel;
28 |
29 | @Override
30 | protected void onCreate(Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 | setContentView(R.layout.activity_custom_notification_settings);
33 |
34 | final CustomProgressDialog progressDialog = new CustomProgressDialog();
35 | progressDialog.setCancelable(false);
36 | progressDialog.show(getSupportFragmentManager(), "progressDialog");
37 |
38 | final RecyclerView recyclerView = findViewById(R.id.recyclerView);
39 | final ConstraintLayout emptyView = findViewById(R.id.emptyView);
40 | emptyView.setOnClickListener(view -> {
41 | Intent intent = new Intent(CustomNotificationSettingsActivity.this, EnabledApplicationsActivity.class);
42 | startActivityForResult(intent, RETURNED_FROM_ENABLED_APPS_SETTINGS_REQUEST);
43 | });
44 |
45 | recyclerView.setHasFixedSize(true);
46 | recyclerView.setLayoutManager(new LinearLayoutManager(this));
47 |
48 | final CustomNotificationSettingsAdapter adapter = new CustomNotificationSettingsAdapter(this);
49 | recyclerView.setAdapter(adapter);
50 |
51 | recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL));
52 |
53 | viewModel = ViewModelProviders.of(this).get(CustomNotificationSettingsViewModel.class);
54 | viewModel.getAppsDataList().observe(this, customSettingsAppData -> {
55 | adapter.setAppDataList(customSettingsAppData);
56 | progressDialog.dismiss();
57 | if (customSettingsAppData.size() == 0) {
58 | emptyView.setVisibility(View.VISIBLE);
59 | recyclerView.setVisibility(View.GONE);
60 | } else {
61 | emptyView.setVisibility(View.GONE);
62 | recyclerView.setVisibility(View.VISIBLE);
63 | }
64 | });
65 | }
66 |
67 | private static final int RETURNED_FROM_APP_SETTINGS_REQUEST = 1;
68 | private static final int RETURNED_FROM_ENABLED_APPS_SETTINGS_REQUEST = 2;
69 |
70 | @Override
71 | protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
72 | super.onActivityResult(requestCode, resultCode, data);
73 | switch (requestCode) {
74 | case RETURNED_FROM_APP_SETTINGS_REQUEST:
75 | viewModel.maybeUpdateUsingCustom();
76 | break;
77 | case RETURNED_FROM_ENABLED_APPS_SETTINGS_REQUEST:
78 | viewModel.updateAfterEnabledApplicationSettings();
79 | break;
80 | }
81 | }
82 |
83 | @Override
84 | public void onItemClick(CustomSettingsAppData appData) {
85 | Intent intent = new Intent(this, AppNotificationSettingsActivity.class);
86 | intent.putExtra("appName", appData.appName);
87 | intent.putExtra("packageName", appData.packageName);
88 | startActivityForResult(intent, RETURNED_FROM_APP_SETTINGS_REQUEST);
89 | }
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/fragments/EnabledApplicationsPreferenceFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.fragments;
10 |
11 | import android.content.SharedPreferences;
12 | import android.os.Bundle;
13 | import android.view.LayoutInflater;
14 | import android.view.View;
15 | import android.view.ViewGroup;
16 |
17 | import androidx.annotation.Nullable;
18 | import androidx.lifecycle.Observer;
19 | import androidx.lifecycle.ViewModelProviders;
20 | import androidx.preference.CheckBoxPreference;
21 | import androidx.preference.PreferenceFragmentCompat;
22 | import androidx.preference.PreferenceScreen;
23 |
24 | import java.util.List;
25 |
26 | import kiwi.root.an2linuxclient.R;
27 | import kiwi.root.an2linuxclient.preferences.CheckBoxPreferenceData;
28 | import kiwi.root.an2linuxclient.viewmodels.EnabledApplicationsViewModel;
29 |
30 | public class EnabledApplicationsPreferenceFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener {
31 |
32 | @Override
33 | public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
34 | getPreferenceManager().setSharedPreferencesName(getString(R.string.enabled_applications));
35 | setPreferencesFromResource(R.xml.enabled_applications_preferences, null);
36 | }
37 |
38 | @Override
39 | public void onActivityCreated(@Nullable Bundle savedInstanceState) {
40 | super.onActivityCreated(savedInstanceState);
41 | EnabledApplicationsViewModel viewModel = ViewModelProviders.of(getActivity()).get(EnabledApplicationsViewModel.class);
42 | viewModel.getFilteredCheckBoxPrefsData().observe(getViewLifecycleOwner(), checkBoxPreferencesData -> {
43 | setPreferencesFromResource(R.xml.enabled_applications_preferences, null);
44 | PreferenceScreen prefScreen = (PreferenceScreen) findPreference(getString(R.string.enabled_apps_pref_screen));
45 | for (CheckBoxPreferenceData checkBoxPreferenceData : checkBoxPreferencesData) {
46 | CheckBoxPreference c = new CheckBoxPreference(getPreferenceScreen().getContext());
47 | c.setKey(checkBoxPreferenceData.key);
48 | c.setTitle(checkBoxPreferenceData.title);
49 | c.setSummary(checkBoxPreferenceData.summary);
50 | c.setIcon(checkBoxPreferenceData.icon);
51 | prefScreen.addPreference(c);
52 | }
53 | });
54 | }
55 |
56 | @Override
57 | public void onResume() {
58 | super.onResume();
59 | getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
60 | }
61 |
62 | @Override
63 | public void onPause() {
64 | super.onPause();
65 | getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
66 | }
67 |
68 | @Override
69 | public void onSharedPreferenceChanged(SharedPreferences sp, String key) {
70 | boolean newSettingsValue = sp.getBoolean(key, false);
71 | String prefEnableDisableAllKey = getString(R.string.preference_enable_disable_all_applications);
72 | if (key.equals(prefEnableDisableAllKey)) {
73 | final PreferenceScreen prefScreen = findPreference(getString(R.string.enabled_apps_pref_screen));
74 | for (int i = 1; i < prefScreen.getPreferenceCount(); i++) {
75 | ((CheckBoxPreference) (prefScreen.getPreference(i))).setChecked(newSettingsValue);
76 | }
77 | }
78 |
79 | // If newSettingsValue == false, clear it from SharedPreferences file to save up some space.
80 | // Since AN2Linux will default to false if the setting is not found.
81 | if (!newSettingsValue) {
82 | sp.edit().remove(key).apply();
83 | }
84 | }
85 |
86 | @Override
87 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
88 | View view = super.onCreateView(inflater, container, savedInstanceState);
89 | view.setBackgroundColor(getResources().getColor(R.color.gray_dark));
90 | return view;
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/views/MobileDialogNew.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.views;
10 |
11 | import android.view.View;
12 | import android.widget.AdapterView;
13 | import android.widget.Toast;
14 |
15 | import kiwi.root.an2linuxclient.R;
16 | import kiwi.root.an2linuxclient.crypto.TlsHelper;
17 | import kiwi.root.an2linuxclient.data.MobileServer;
18 | import kiwi.root.an2linuxclient.data.ServerDatabaseHandler;
19 | import kiwi.root.an2linuxclient.utils.ConnectionHelper;
20 |
21 | public class MobileDialogNew extends MobileDialog {
22 |
23 | private Long spinnerSelectedCertificateId;
24 |
25 | @Override
26 | void initViews(View v) {
27 | super.initViews(v);
28 | super.initViewsDialogNew(v);
29 | saveServerBtn.setOnClickListener(new SaveServerOnClickListener());
30 | }
31 |
32 | @Override
33 | public void onItemSelected(AdapterView> parent, View view, int position, long id) {
34 | spinnerSelectedCertificateId = onItemSelectedNew(parent.getItemAtPosition(position));
35 | }
36 |
37 | @Override
38 | void saveMobileServerToDatabase(boolean newCertificate){
39 | ServerDatabaseHandler dbHandler = ServerDatabaseHandler.getInstance(getActivity());
40 | long rowId;
41 | if (newCertificate){
42 | long certificateId = dbHandler.getCertificateId(TlsHelper.certificateToBytes(serverCert));
43 | boolean certificateAlreadyInDatabase = certificateId != -1;
44 | if (certificateAlreadyInDatabase){
45 | Toast.makeText(getActivity(), R.string.certificate_already_in_database, Toast.LENGTH_LONG).show();
46 | rowId = dbHandler.addMobileServer(
47 | new MobileServer(ipOrHostname, portNumber, checkBoxRoaming.isChecked()),
48 | certificateId);
49 | } else {
50 | rowId = dbHandler.addMobileServer(
51 | new MobileServer(serverCert, ipOrHostname,
52 | portNumber, checkBoxRoaming.isChecked()));
53 | }
54 | } else {
55 | rowId = dbHandler.addMobileServer(
56 | new MobileServer(ipOrHostname, portNumber, checkBoxRoaming.isChecked()),
57 | spinnerSelectedCertificateId);
58 | }
59 | serverAdapterListCallbacks.addServer(dbHandler.getMobileServer(rowId));
60 | getActivity().getWindow().clearFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
61 | getDialog().cancel();
62 | }
63 |
64 | private class SaveServerOnClickListener implements View.OnClickListener {
65 | @Override
66 | public void onClick(View v) {
67 |
68 | if (spinnerSelectedCertificateId == null){
69 | if (activePairingConnection){
70 |
71 | connectionHandler.acceptPairing(); // let server know you have accepted pair
72 | clientAcceptedPair = true;
73 |
74 | if (serverAcceptedPair){
75 | saveMobileServerToDatabase(true);
76 | } else {
77 | // server have not accepted pair yet, need to wait for that
78 | pairingInfoTextView.setText(getString(R.string.waiting_for_server_to_accept, pairingInfoTextView.getText().toString()));
79 | saveServerBtn.setEnabled(false);
80 | }
81 |
82 | } else {
83 | Toast.makeText(getActivity(), R.string.need_to_pair_first, Toast.LENGTH_SHORT).show();
84 | }
85 | } else {
86 | if (ConnectionHelper.checkIfValidAddressAndPortInput(ipOrHostnameEditText,
87 | portNumberEditText, getActivity().getApplicationContext())) {
88 |
89 | ipOrHostname = ipOrHostnameEditText.getText().toString().trim();
90 | portNumber = Integer.parseInt(portNumberEditText.getText().toString());
91 |
92 | saveMobileServerToDatabase(false);
93 | }
94 | }
95 | }
96 | }
97 |
98 | }
99 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/data/NotificationSettings.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.data;
10 |
11 | import android.content.Context;
12 | import android.content.SharedPreferences;
13 |
14 | import kiwi.root.an2linuxclient.R;
15 | import kiwi.root.an2linuxclient.preferences.IconSizePreference;
16 | import kiwi.root.an2linuxclient.preferences.MaxMessageSizePreference;
17 | import kiwi.root.an2linuxclient.preferences.MaxTitleSizePreference;
18 |
19 | import static android.content.Context.MODE_PRIVATE;
20 |
21 | public class NotificationSettings {
22 |
23 | private boolean prefIncludeTitle;
24 | private boolean prefForceTitle;
25 | private boolean prefIncludeMessage;
26 | private boolean prefIncludeIcon;
27 | private int prefMaxTitleSize;
28 | private int prefMaxMessageSize;
29 | private int prefIconSize;
30 | private byte notificationFlags;
31 |
32 | private final byte FLAG_INCLUDE_ICON = 4;
33 |
34 | private String packageName;
35 | private boolean usingCustomSettings;
36 |
37 | NotificationSettings(Context c, String packageName){
38 | this.packageName = packageName;
39 | initializeSettings(c);
40 | }
41 |
42 | private void initializeSettings(Context c){
43 | SharedPreferences sharedPrefs = c.getSharedPreferences(c.getString(R.string.notification_settings_custom), MODE_PRIVATE);
44 | usingCustomSettings = sharedPrefs.getBoolean(packageName + "_" + c.getString(R.string.preference_use_custom_settings), false);
45 | if (!usingCustomSettings) {
46 | sharedPrefs = c.getSharedPreferences(c.getString(R.string.notification_settings_global), MODE_PRIVATE);
47 | }
48 | prefIncludeTitle = sharedPrefs.getBoolean(getCorrectPrefKey(c.getString(R.string.preference_include_notification_title)), true);
49 | prefIncludeMessage = sharedPrefs.getBoolean(getCorrectPrefKey(c.getString(R.string.preference_include_notification_message)), true);
50 | prefIncludeIcon = sharedPrefs.getBoolean(getCorrectPrefKey(c.getString(R.string.preference_include_notification_icon)), true);
51 | if (prefIncludeTitle){
52 | final byte FLAG_INCLUDE_TITLE = 1;
53 | notificationFlags |= FLAG_INCLUDE_TITLE;
54 | prefForceTitle = sharedPrefs.getBoolean(getCorrectPrefKey(c.getString(R.string.preference_force_title)), false);
55 | prefMaxTitleSize = sharedPrefs.getInt(getCorrectPrefKey(c.getString(R.string.preference_title_max_size)), MaxTitleSizePreference.DEFAULT_VALUE);
56 | }
57 | if (prefIncludeMessage){
58 | final byte FLAG_INCLUDE_MESSAGE = 2;
59 | notificationFlags |= FLAG_INCLUDE_MESSAGE;
60 | prefMaxMessageSize = sharedPrefs.getInt(getCorrectPrefKey(c.getString(R.string.preference_message_max_size)), MaxMessageSizePreference.DEFAULT_VALUE);
61 | }
62 | if (prefIncludeIcon) {
63 | notificationFlags |= FLAG_INCLUDE_ICON;
64 | prefIconSize = sharedPrefs.getInt(getCorrectPrefKey(c.getString(R.string.preference_icon_size)), IconSizePreference.DEFAULT_VALUE);
65 | }
66 | }
67 |
68 | public boolean includeTitle(){
69 | return prefIncludeTitle;
70 | }
71 |
72 | boolean forceTitle(){
73 | return prefForceTitle;
74 | }
75 |
76 | int getTitleMax(){
77 | return prefMaxTitleSize;
78 | }
79 |
80 | public boolean includeMessage(){
81 | return prefIncludeMessage;
82 | }
83 |
84 | int getMessageMax(){
85 | return prefMaxMessageSize;
86 | }
87 |
88 | public boolean includeIcon(){
89 | return prefIncludeIcon;
90 | }
91 |
92 | int getIconSize(){
93 | return prefIconSize;
94 | }
95 |
96 | public byte getNotificationFlags(){
97 | return notificationFlags;
98 | }
99 |
100 | void removeIconFlag(){
101 | notificationFlags &= ~FLAG_INCLUDE_ICON;
102 | }
103 |
104 | private String getCorrectPrefKey(String key) {
105 | return usingCustomSettings ? packageName + "_" + key : key;
106 | }
107 |
108 | }
109 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/main_preferences.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
11 |
12 |
18 |
19 |
23 |
24 |
25 |
28 |
32 |
33 |
34 |
37 |
41 |
42 |
43 |
46 |
47 |
48 |
49 |
51 |
52 |
53 |
57 |
58 |
59 |
60 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
73 |
74 |
78 |
79 |
82 |
85 |
86 |
87 |
90 |
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/views/WifiDialogNew.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.views;
10 |
11 | import android.view.View;
12 | import android.widget.AdapterView;
13 | import android.widget.Toast;
14 |
15 | import kiwi.root.an2linuxclient.R;
16 | import kiwi.root.an2linuxclient.crypto.TlsHelper;
17 | import kiwi.root.an2linuxclient.data.ServerDatabaseHandler;
18 | import kiwi.root.an2linuxclient.data.WifiServer;
19 | import kiwi.root.an2linuxclient.utils.ConnectionHelper;
20 |
21 | public class WifiDialogNew extends WifiDialog {
22 |
23 | private Long spinnerSelectedCertificateId;
24 |
25 | @Override
26 | void initViews(View v) {
27 | super.initViews(v);
28 | super.initViewsDialogNew(v);
29 | saveServerBtn.setOnClickListener(new SaveServerOnClickListener());
30 | }
31 |
32 | @Override
33 | public void onItemSelected(AdapterView> parent, View view, int position, long id) {
34 | spinnerSelectedCertificateId = onItemSelectedNew(parent.getItemAtPosition(position));
35 | }
36 |
37 | @Override
38 | void saveWifiServerToDatabase(boolean newCertificate){
39 | ServerDatabaseHandler dbHandler = ServerDatabaseHandler.getInstance(getActivity());
40 | long rowId;
41 | if (newCertificate){
42 | long certificateId = dbHandler.getCertificateId(TlsHelper.certificateToBytes(serverCert));
43 | boolean certificateAlreadyInDatabase = certificateId != -1;
44 | if (certificateAlreadyInDatabase){
45 | Toast.makeText(getActivity(), R.string.certificate_already_in_database, Toast.LENGTH_LONG).show();
46 | rowId = dbHandler.addWifiServer(
47 | new WifiServer(ipOrHostname, portNumber, ssidWhitelist),
48 | certificateId);
49 | } else {
50 | rowId = dbHandler.addWifiServer(
51 | new WifiServer(serverCert, ipOrHostname,
52 | portNumber, ssidWhitelist));
53 | }
54 | } else {
55 | rowId = dbHandler.addWifiServer(
56 | new WifiServer(ipOrHostname, portNumber, ssidWhitelist),
57 | spinnerSelectedCertificateId);
58 | }
59 | serverAdapterListCallbacks.addServer(dbHandler.getWifiServer(rowId));
60 | getActivity().getWindow().clearFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
61 | getDialog().cancel();
62 | }
63 |
64 | private class SaveServerOnClickListener implements View.OnClickListener {
65 | @Override
66 | public void onClick(View v) {
67 |
68 | if (spinnerSelectedCertificateId == null){
69 | if (activePairingConnection){
70 |
71 | connectionHandler.acceptPairing(); // let server know you have accepted pair
72 | clientAcceptedPair = true;
73 |
74 | if (serverAcceptedPair){
75 | saveWifiServerToDatabase(true);
76 | } else {
77 | // server have not accepted pair yet, need to wait for that
78 | pairingInfoTextView.setText(getString(R.string.waiting_for_server_to_accept, pairingInfoTextView.getText().toString()));
79 | saveServerBtn.setEnabled(false);
80 | }
81 |
82 | } else {
83 | Toast.makeText(getActivity(), R.string.need_to_pair_first, Toast.LENGTH_SHORT).show();
84 | }
85 | } else {
86 | if (ConnectionHelper.checkIfValidAddressAndPortInput(ipOrHostnameEditText,
87 | portNumberEditText, getActivity().getApplicationContext())) {
88 |
89 | ipOrHostname = ipOrHostnameEditText.getText().toString().trim();
90 | portNumber = Integer.parseInt(portNumberEditText.getText().toString());
91 | setSsidWhitelist();
92 |
93 | saveWifiServerToDatabase(false);
94 | }
95 | }
96 | }
97 | }
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/notification_preferences.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
12 |
13 |
18 |
19 |
25 |
26 |
30 |
31 |
37 |
38 |
42 |
43 |
49 |
50 |
58 |
59 |
64 |
65 |
70 |
71 |
75 |
76 |
77 |
78 |
80 |
81 |
84 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/views/BluetoothDialogEdit.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.views;
10 |
11 | import android.os.Bundle;
12 | import android.view.View;
13 | import android.view.WindowManager;
14 | import android.widget.AdapterView;
15 | import android.widget.Toast;
16 |
17 | import kiwi.root.an2linuxclient.R;
18 | import kiwi.root.an2linuxclient.crypto.TlsHelper;
19 | import kiwi.root.an2linuxclient.data.BluetoothServer;
20 | import kiwi.root.an2linuxclient.data.CertificateIdAndFingerprint;
21 | import kiwi.root.an2linuxclient.data.ServerDatabaseHandler;
22 |
23 | public class BluetoothDialogEdit extends BluetoothDialog {
24 |
25 | private long spinnerSelectedCertificateId;
26 |
27 | private long serverId;
28 | private int serverListPosition;
29 |
30 | public static BluetoothDialogEdit newInstance(long serverId, int serverListPosition) {
31 | BluetoothDialogEdit dialog = new BluetoothDialogEdit();
32 | Bundle args = new Bundle();
33 |
34 | args.putLong("serverId", serverId);
35 | args.putInt("serverListPosition", serverListPosition);
36 |
37 | dialog.setArguments(args);
38 | return dialog;
39 | }
40 |
41 | @Override
42 | void initViews(View v) {
43 | super.initViews(v);
44 | super.initViewsDialogEdit(v,
45 | ServerDatabaseHandler.getInstance(getActivity()).getBluetoothServer(serverId),
46 | serverListPosition);
47 | saveServerBtn.setOnClickListener(new SaveServerOnClickListener());
48 | }
49 |
50 | @Override
51 | public void onCreate(Bundle savedInstanceState) {
52 | super.onCreate(savedInstanceState);
53 | serverId = getArguments().getLong("serverId");
54 | serverListPosition = getArguments().getInt("serverListPosition");
55 | }
56 |
57 | @Override
58 | public void onItemSelected(AdapterView> parent, View view, int position, long id) {
59 | spinnerSelectedCertificateId = ((CertificateIdAndFingerprint)
60 | parent.getItemAtPosition(position)).getId();
61 | onItemSelectedEdit();
62 | }
63 |
64 | @Override
65 | void saveBluetoothServerToDatabase(boolean newCertificate){
66 | ServerDatabaseHandler dbHandler = ServerDatabaseHandler.getInstance(getActivity());
67 | String btName = btNameEditText.getText().toString();
68 | if (newCertificate){
69 | long certificateId = dbHandler.getCertificateId(TlsHelper.certificateToBytes(serverCert));
70 | boolean certificateAlreadyInDatabase = certificateId != -1;
71 | if (certificateAlreadyInDatabase){
72 | Toast.makeText(getActivity(), R.string.certificate_already_in_database, Toast.LENGTH_LONG).show();
73 | dbHandler.updateBluetoothServer(new BluetoothServer(serverId, btName), certificateId);
74 |
75 | } else {
76 | dbHandler.updateBluetoothServer(new BluetoothServer(serverId, serverCert, btName));
77 | }
78 | } else {
79 | dbHandler.updateBluetoothServer(new BluetoothServer(serverId, btName), spinnerSelectedCertificateId);
80 | }
81 | serverAdapterListCallbacks.updateServer(dbHandler.getBluetoothServer(serverId), serverListPosition);
82 | getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
83 | getDialog().cancel();
84 | }
85 |
86 | private class SaveServerOnClickListener implements View.OnClickListener {
87 | @Override
88 | public void onClick(View v) {
89 | if (activePairingConnection){
90 | connectionHandler.acceptPairing(); // let server know you have accepted pair
91 | clientAcceptedPair = true;
92 |
93 | if (serverAcceptedPair){
94 | saveBluetoothServerToDatabase(true);
95 | } else {
96 | // server have not accepted pair yet, need to wait for that
97 | pairingInfoTextView.setText(getString(R.string.waiting_for_server_to_accept, pairingInfoTextView.getText().toString()));
98 | saveServerBtn.setEnabled(false);
99 | }
100 | } else {
101 | saveBluetoothServerToDatabase(false);
102 | }
103 | }
104 | }
105 |
106 | }
107 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/network/TcpNotificationConnection.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.network;
10 |
11 | import android.content.Context;
12 | import android.graphics.Bitmap;
13 | import android.os.Build;
14 | import android.util.Log;
15 |
16 | import java.io.BufferedInputStream;
17 | import java.io.ByteArrayInputStream;
18 | import java.io.ByteArrayOutputStream;
19 | import java.io.IOException;
20 | import java.io.OutputStream;
21 | import java.net.InetSocketAddress;
22 | import java.net.Socket;
23 | import java.security.cert.Certificate;
24 |
25 | import javax.net.ssl.SSLSocket;
26 |
27 | import kiwi.root.an2linuxclient.crypto.TlsHelper;
28 | import kiwi.root.an2linuxclient.data.Notification;
29 | import kiwi.root.an2linuxclient.data.NotificationSettings;
30 | import kiwi.root.an2linuxclient.utils.ConnectionHelper;
31 |
32 | class TcpNotificationConnection extends NotificationConnection {
33 |
34 | private String serverAddress;
35 | private int serverPort;
36 |
37 | TcpNotificationConnection(Context c, Notification n, Certificate serverCert, String serverAddress, int serverPort){
38 | super(c, n, serverCert);
39 | this.serverAddress = serverAddress;
40 | this.serverPort = serverPort;
41 | }
42 |
43 | @Override
44 | public void run(){
45 | try {
46 | Socket s = new Socket();
47 | s.connect(new InetSocketAddress(serverAddress, serverPort), 5000);
48 | OutputStream out = s.getOutputStream();
49 |
50 | out.write(NOTIF_CONN);
51 |
52 | SSLSocket tlsSocket = (SSLSocket) TlsHelper.getNotificationTlsContext(c, serverCert).getSocketFactory()
53 | .createSocket(s, serverAddress, serverPort, true);
54 | tlsSocket.setUseClientMode(true);
55 | tlsSocket.setEnabledProtocols(TlsHelper.TLS_VERSIONS);
56 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH){
57 | tlsSocket.setEnabledCipherSuites(TlsHelper.TLS_CIPHERS);
58 | } else {
59 | tlsSocket.setEnabledCipherSuites(TlsHelper.TLS_CIPHERS_COMPAT);
60 | }
61 |
62 | try {
63 | tlsSocket.startHandshake();
64 | } catch (IOException e) {
65 | try {
66 | out.close();
67 | tlsSocket.close();
68 | } catch (IOException e2) {}
69 | return;
70 | }
71 |
72 | out = tlsSocket.getOutputStream();
73 |
74 | NotificationSettings ns = n.getNotificationSettings();
75 |
76 | out.write(ns.getNotificationFlags());
77 |
78 | if (ns.includeTitle() || ns.includeMessage()){
79 | String title = "";
80 | if (ns.includeTitle()){
81 | title = n.getTitle();
82 | }
83 |
84 | String message = "";
85 | if (ns.includeMessage()){
86 | message = "|||" + n.getMessage();
87 | }
88 |
89 | byte[] titleAndOrMessage = (title + message).getBytes();
90 | out.write(ConnectionHelper.intToByteArray(titleAndOrMessage.length));
91 | out.write(titleAndOrMessage);
92 | }
93 |
94 | if (ns.includeIcon()){
95 | ByteArrayOutputStream bos = new ByteArrayOutputStream();
96 | n.getIcon().compress(Bitmap.CompressFormat.PNG, 100, bos);
97 |
98 | byte[] image = bos.toByteArray();
99 | byte[] imageSize = ConnectionHelper.intToByteArray(image.length);
100 | out.write(imageSize);
101 |
102 | BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(image), 8192);
103 |
104 | byte[] buffer = new byte[8192];
105 | int len;
106 |
107 | while ((len = bis.read(buffer)) != -1) {
108 | out.write(buffer, 0, len);
109 | }
110 | bos.close();
111 | bis.close();
112 | }
113 | out.close();
114 | tlsSocket.close();
115 | } catch(IOException e) {
116 | Log.e("TcpNotificationConne...", "run");
117 | Log.e("StackTrace", Log.getStackTraceString(e));
118 | }
119 | }
120 |
121 | }
122 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/views/BluetoothDialogNew.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.views;
10 |
11 | import android.os.Bundle;
12 | import android.view.View;
13 | import android.widget.AdapterView;
14 | import android.widget.Toast;
15 |
16 | import kiwi.root.an2linuxclient.R;
17 | import kiwi.root.an2linuxclient.crypto.TlsHelper;
18 | import kiwi.root.an2linuxclient.data.BluetoothServer;
19 | import kiwi.root.an2linuxclient.data.ServerDatabaseHandler;
20 |
21 | public class BluetoothDialogNew extends BluetoothDialog {
22 |
23 | private Long spinnerSelectedCertificateId;
24 |
25 | private String btNameNewServer;
26 | private String btMacNewServer;
27 |
28 | public static BluetoothDialogNew newInstance(String btNameNewServer, String btMacNewServer) {
29 | BluetoothDialogNew dialog = new BluetoothDialogNew();
30 | Bundle args = new Bundle();
31 |
32 | args.putString("btNameNewServer", btNameNewServer);
33 | args.putString("btMacNewServer", btMacNewServer);
34 |
35 | dialog.setArguments(args);
36 | return dialog;
37 | }
38 |
39 | @Override
40 | void initViews(View v) {
41 | super.initViews(v);
42 | super.initViewsDialogNew(v);
43 | btNameEditText.setText(btNameNewServer);
44 | btMacTextView.setText(btMacNewServer);
45 | saveServerBtn.setOnClickListener(new SaveServerOnClickListener());
46 | }
47 |
48 | @Override
49 | public void onCreate(Bundle savedInstanceState) {
50 | super.onCreate(savedInstanceState);
51 | btNameNewServer = getArguments().getString("btNameNewServer");
52 | btMacNewServer = getArguments().getString("btMacNewServer");
53 | }
54 |
55 | @Override
56 | public void onItemSelected(AdapterView> parent, View view, int position, long id) {
57 | spinnerSelectedCertificateId = onItemSelectedNew(parent.getItemAtPosition(position));
58 | }
59 |
60 | @Override
61 | void saveBluetoothServerToDatabase(boolean newCertificate){
62 | ServerDatabaseHandler dbHandler = ServerDatabaseHandler.getInstance(getActivity());
63 | long rowId;
64 | String btName = btNameEditText.getText().toString();
65 | String btMacAddress = btMacTextView.getText().toString();
66 | if (newCertificate){
67 | long certificateId = dbHandler.getCertificateId(TlsHelper.certificateToBytes(serverCert));
68 | boolean certificateAlreadyInDatabase = certificateId != -1;
69 | if (certificateAlreadyInDatabase){
70 | Toast.makeText(getActivity(), R.string.certificate_already_in_database, Toast.LENGTH_LONG).show();
71 | rowId = dbHandler.addBluetoothServer(
72 | new BluetoothServer(btMacAddress, btName),
73 | certificateId);
74 | } else {
75 | rowId = dbHandler.addBluetoothServer(
76 | new BluetoothServer(serverCert, btMacAddress, btName));
77 | }
78 | } else {
79 | rowId = dbHandler.addBluetoothServer(
80 | new BluetoothServer(btMacAddress, btName),
81 | spinnerSelectedCertificateId);
82 | }
83 | serverAdapterListCallbacks.addServer(dbHandler.getBluetoothServer(rowId));
84 | getActivity().getWindow().clearFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
85 | getDialog().cancel();
86 | }
87 |
88 | private class SaveServerOnClickListener implements View.OnClickListener {
89 | @Override
90 | public void onClick(View v) {
91 |
92 | if (spinnerSelectedCertificateId == null){
93 | if (activePairingConnection){
94 |
95 | connectionHandler.acceptPairing(); // let server know you have accepted pair
96 | clientAcceptedPair = true;
97 |
98 | if (serverAcceptedPair){
99 | saveBluetoothServerToDatabase(true);
100 | } else {
101 | // server have not accepted pair yet, need to wait for that
102 | pairingInfoTextView.setText(getString(R.string.waiting_for_server_to_accept, pairingInfoTextView.getText().toString()));
103 | saveServerBtn.setEnabled(false);
104 | }
105 |
106 | } else {
107 | Toast.makeText(getActivity(), R.string.need_to_pair_first, Toast.LENGTH_SHORT).show();
108 | }
109 | } else {
110 | saveBluetoothServerToDatabase(false);
111 | }
112 | }
113 | }
114 |
115 | }
116 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/utils/ConnectionHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.utils;
10 |
11 | import android.content.Context;
12 | import android.net.wifi.WifiInfo;
13 | import android.net.wifi.WifiManager;
14 | import android.widget.EditText;
15 | import android.widget.Toast;
16 |
17 | import java.io.IOException;
18 | import java.io.InputStream;
19 | import java.net.SocketException;
20 |
21 | import kiwi.root.an2linuxclient.R;
22 |
23 | public class ConnectionHelper {
24 |
25 | public static byte[] intToByteArray(int value){
26 | if (value < 0) {
27 | throw new RuntimeException();
28 | }
29 | return new byte[] {
30 | (byte) (value >>> 24),
31 | (byte) (value >>> 16),
32 | (byte) (value >>> 8),
33 | (byte) value};
34 | }
35 |
36 | public static byte[] readAll(int size, InputStream in) throws IOException {
37 | if (size <= 0) {
38 | throw new RuntimeException();
39 | }
40 | byte[] buf = new byte[size];
41 | int bytesRead = 0;
42 | int tmp;
43 | while (bytesRead < size){
44 | tmp = in.read(buf, bytesRead, size-bytesRead);
45 | if (tmp == -1){
46 | throw new SocketException();
47 | } else {
48 | bytesRead += tmp;
49 | }
50 | }
51 | return buf;
52 | }
53 |
54 | public static boolean checkIfSsidIsAllowed(String ssidWhitelist, Context c){
55 | if (ssidWhitelist == null){
56 | return true;
57 | }
58 | WifiManager wifiManager = (WifiManager) c.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
59 | WifiInfo info = wifiManager.getConnectionInfo();
60 | String connectedToSsid = info.getSSID();
61 | for (String ssid : ssidWhitelist.split("(? 65535) {
89 | sendToast(R.string.port_range, c);
90 | return false;
91 | }
92 | } catch (NumberFormatException e) {
93 | sendToast(R.string.invalid_port, c);
94 | return false;
95 | }
96 | } else {
97 | sendToast(R.string.invalid_address, c);
98 | return false;
99 | }
100 | return true;
101 | }
102 |
103 | private static void sendToast(int msg, Context c){
104 | Toast.makeText(c, msg, Toast.LENGTH_SHORT).show();
105 | }
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/views/WifiDialogEdit.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.views;
10 |
11 | import android.os.Bundle;
12 | import android.view.View;
13 | import android.view.WindowManager;
14 | import android.widget.AdapterView;
15 | import android.widget.Toast;
16 |
17 | import kiwi.root.an2linuxclient.R;
18 | import kiwi.root.an2linuxclient.crypto.TlsHelper;
19 | import kiwi.root.an2linuxclient.data.CertificateIdAndFingerprint;
20 | import kiwi.root.an2linuxclient.data.ServerDatabaseHandler;
21 | import kiwi.root.an2linuxclient.data.WifiServer;
22 | import kiwi.root.an2linuxclient.utils.ConnectionHelper;
23 |
24 | public class WifiDialogEdit extends WifiDialog {
25 |
26 | private long spinnerSelectedCertificateId;
27 |
28 | private long serverId;
29 | private int serverListPosition;
30 |
31 | public static WifiDialogEdit newInstance(long serverId, int serverListPosition) {
32 | WifiDialogEdit dialog = new WifiDialogEdit();
33 | Bundle args = new Bundle();
34 |
35 | args.putLong("serverId", serverId);
36 | args.putInt("serverListPosition", serverListPosition);
37 |
38 | dialog.setArguments(args);
39 | return dialog;
40 | }
41 |
42 | @Override
43 | void initViews(View v) {
44 | super.initViews(v);
45 | super.initViewsDialogEdit(v,
46 | ServerDatabaseHandler.getInstance(getActivity()).getWifiServer(serverId),
47 | serverListPosition);
48 | saveServerBtn.setOnClickListener(new SaveServerOnClickListener());
49 | }
50 |
51 | @Override
52 | public void onCreate(Bundle savedInstanceState) {
53 | super.onCreate(savedInstanceState);
54 | serverId = getArguments().getLong("serverId");
55 | serverListPosition = getArguments().getInt("serverListPosition");
56 | }
57 |
58 | @Override
59 | public void onItemSelected(AdapterView> parent, View view, int position, long id) {
60 | spinnerSelectedCertificateId = ((CertificateIdAndFingerprint)
61 | parent.getItemAtPosition(position)).getId();
62 | onItemSelectedEdit();
63 | }
64 |
65 | @Override
66 | void saveWifiServerToDatabase(boolean newCertificate){
67 | ServerDatabaseHandler dbHandler = ServerDatabaseHandler.getInstance(getActivity());
68 | if (newCertificate){
69 | long certificateId = dbHandler.getCertificateId(TlsHelper.certificateToBytes(serverCert));
70 | boolean certificateAlreadyInDatabase = certificateId != -1;
71 | if (certificateAlreadyInDatabase){
72 | Toast.makeText(getActivity(), R.string.certificate_already_in_database, Toast.LENGTH_LONG).show();
73 | dbHandler.updateWifiServer(new WifiServer(serverId, ipOrHostname, portNumber,
74 | ssidWhitelist), certificateId);
75 | } else {
76 | dbHandler.updateWifiServer(new WifiServer(serverId, serverCert, ipOrHostname,
77 | portNumber, ssidWhitelist));
78 | }
79 | } else {
80 | dbHandler.updateWifiServer(new WifiServer(serverId, ipOrHostname, portNumber,
81 | ssidWhitelist), spinnerSelectedCertificateId);
82 | }
83 | serverAdapterListCallbacks.updateServer(dbHandler.getWifiServer(serverId), serverListPosition);
84 | getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
85 | getDialog().cancel();
86 | }
87 |
88 | private class SaveServerOnClickListener implements View.OnClickListener {
89 | @Override
90 | public void onClick(View v) {
91 | if (activePairingConnection){
92 | connectionHandler.acceptPairing(); // let server know you have accepted pair
93 | clientAcceptedPair = true;
94 |
95 | if (serverAcceptedPair){
96 | saveWifiServerToDatabase(true);
97 | } else {
98 | // server have not accepted pair yet, need to wait for that
99 | pairingInfoTextView.setText(getString(R.string.waiting_for_server_to_accept, pairingInfoTextView.getText().toString()));
100 | saveServerBtn.setEnabled(false);
101 | }
102 | } else {
103 | if (ConnectionHelper.checkIfValidAddressAndPortInput(ipOrHostnameEditText,
104 | portNumberEditText, getActivity().getApplicationContext())) {
105 |
106 | ipOrHostname = ipOrHostnameEditText.getText().toString().trim();
107 | portNumber = Integer.parseInt(portNumberEditText.getText().toString());
108 | setSsidWhitelist();
109 |
110 | saveWifiServerToDatabase(false);
111 | }
112 | }
113 | }
114 | }
115 |
116 | }
117 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/views/MobileDialogEdit.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 rootkiwi
3 | *
4 | * AN2Linux-client is licensed under GNU General Public License 3.
5 | *
6 | * See LICENSE for more details.
7 | */
8 |
9 | package kiwi.root.an2linuxclient.views;
10 |
11 | import android.os.Bundle;
12 | import android.view.View;
13 | import android.view.WindowManager;
14 | import android.widget.AdapterView;
15 | import android.widget.Toast;
16 |
17 | import kiwi.root.an2linuxclient.R;
18 | import kiwi.root.an2linuxclient.crypto.TlsHelper;
19 | import kiwi.root.an2linuxclient.data.CertificateIdAndFingerprint;
20 | import kiwi.root.an2linuxclient.data.MobileServer;
21 | import kiwi.root.an2linuxclient.data.ServerDatabaseHandler;
22 | import kiwi.root.an2linuxclient.utils.ConnectionHelper;
23 |
24 | public class MobileDialogEdit extends MobileDialog {
25 |
26 | private long spinnerSelectedCertificateId;
27 |
28 | private long serverId;
29 | private int serverListPosition;
30 |
31 | public static MobileDialogEdit newInstance(long serverId, int serverListPosition) {
32 | MobileDialogEdit dialog = new MobileDialogEdit();
33 | Bundle args = new Bundle();
34 |
35 | args.putLong("serverId", serverId);
36 | args.putInt("serverListPosition", serverListPosition);
37 |
38 | dialog.setArguments(args);
39 | return dialog;
40 | }
41 |
42 | @Override
43 | void initViews(View v) {
44 | super.initViews(v);
45 | super.initViewsDialogEdit(v,
46 | ServerDatabaseHandler.getInstance(getActivity()).getMobileServer(serverId),
47 | serverListPosition);
48 | saveServerBtn.setOnClickListener(new SaveServerOnClickListener());
49 | }
50 |
51 | @Override
52 | public void onCreate(Bundle savedInstanceState) {
53 | super.onCreate(savedInstanceState);
54 | serverId = getArguments().getLong("serverId");
55 | serverListPosition = getArguments().getInt("serverListPosition");
56 | }
57 |
58 | @Override
59 | public void onItemSelected(AdapterView> parent, View view, int position, long id) {
60 | spinnerSelectedCertificateId = ((CertificateIdAndFingerprint)
61 | parent.getItemAtPosition(position)).getId();
62 | onItemSelectedEdit();
63 | }
64 |
65 | @Override
66 | void saveMobileServerToDatabase(boolean newCertificate){
67 | ServerDatabaseHandler dbHandler = ServerDatabaseHandler.getInstance(getActivity());
68 | if (newCertificate){
69 | long certificateId = dbHandler.getCertificateId(TlsHelper.certificateToBytes(serverCert));
70 | boolean certificateAlreadyInDatabase = certificateId != -1;
71 | if (certificateAlreadyInDatabase){
72 | Toast.makeText(getActivity(), R.string.certificate_already_in_database, Toast.LENGTH_LONG).show();
73 | dbHandler.updateMobileServer(new MobileServer(serverId, ipOrHostname, portNumber,
74 | checkBoxRoaming.isChecked()), certificateId);
75 | } else {
76 | dbHandler.updateMobileServer(new MobileServer(serverId, serverCert, ipOrHostname,
77 | portNumber, checkBoxRoaming.isChecked()));
78 | }
79 | } else {
80 | dbHandler.updateMobileServer(new MobileServer(serverId, ipOrHostname, portNumber,
81 | checkBoxRoaming.isChecked()), spinnerSelectedCertificateId);
82 | }
83 | serverAdapterListCallbacks.updateServer(dbHandler.getMobileServer(serverId), serverListPosition);
84 | getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
85 | getDialog().cancel();
86 | }
87 |
88 | private class SaveServerOnClickListener implements View.OnClickListener {
89 | @Override
90 | public void onClick(View v) {
91 | if (activePairingConnection){
92 | connectionHandler.acceptPairing(); // let server know you have accepted pair
93 | clientAcceptedPair = true;
94 |
95 | if (serverAcceptedPair){
96 | saveMobileServerToDatabase(true);
97 | } else {
98 | // server have not accepted pair yet, need to wait for that
99 | pairingInfoTextView.setText(getString(R.string.waiting_for_server_to_accept, pairingInfoTextView.getText().toString()));
100 | saveServerBtn.setEnabled(false);
101 | }
102 | } else {
103 | if (ConnectionHelper.checkIfValidAddressAndPortInput(ipOrHostnameEditText,
104 | portNumberEditText, getActivity().getApplicationContext())) {
105 |
106 | ipOrHostname = ipOrHostnameEditText.getText().toString().trim();
107 | portNumber = Integer.parseInt(portNumberEditText.getText().toString());
108 |
109 | saveMobileServerToDatabase(false);
110 | }
111 | }
112 | }
113 | }
114 |
115 | }
116 |
--------------------------------------------------------------------------------
/app/src/main/java/kiwi/root/an2linuxclient/viewmodels/CustomNotificationSettingsViewModel.java:
--------------------------------------------------------------------------------
1 | package kiwi.root.an2linuxclient.viewmodels;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 | import android.content.SharedPreferences;
6 | import android.content.pm.ApplicationInfo;
7 | import android.content.pm.PackageManager;
8 |
9 | import androidx.annotation.NonNull;
10 | import androidx.lifecycle.AndroidViewModel;
11 | import androidx.lifecycle.LiveData;
12 | import androidx.lifecycle.MutableLiveData;
13 |
14 | import java.util.ArrayList;
15 | import java.util.Collections;
16 | import java.util.Comparator;
17 | import java.util.HashMap;
18 | import java.util.List;
19 | import java.util.Map;
20 |
21 | import kiwi.root.an2linuxclient.R;
22 | import kiwi.root.an2linuxclient.data.CustomSettingsAppData;
23 |
24 | import static android.content.Context.MODE_PRIVATE;
25 |
26 | public class CustomNotificationSettingsViewModel extends AndroidViewModel {
27 |
28 | private MutableLiveData> appsDataList = new MutableLiveData<>();
29 |
30 | public CustomNotificationSettingsViewModel(@NonNull Application application) {
31 | super(application);
32 | loadAppListFromNewThread();
33 | }
34 |
35 | private void loadAppListFromNewThread() {
36 | new Thread(this::loadAppList).start();
37 | }
38 |
39 | private void loadAppList() {
40 | Context c = getApplication();
41 | PackageManager pm = c.getPackageManager();
42 | SharedPreferences spEnabledApps = c.getSharedPreferences(c.getString(R.string.enabled_applications), MODE_PRIVATE);
43 | final Map enabledAppLabels = new HashMap<>();
44 | List enabledApps = new ArrayList<>();
45 | List allAppsInfo = pm.getInstalledApplications(0);
46 |
47 | // apparently loadLabel() is very slow so it's faster to do it once and store in map
48 | for (ApplicationInfo appInfo : allAppsInfo) {
49 | if (spEnabledApps.getBoolean(appInfo.packageName, false)) {
50 | enabledApps.add(appInfo);
51 | enabledAppLabels.put(appInfo.packageName, appInfo.loadLabel(pm).toString());
52 | }
53 | }
54 |
55 | Collections.sort(enabledApps, (lhs, rhs) -> enabledAppLabels.get(lhs.packageName).compareToIgnoreCase(enabledAppLabels.get(rhs.packageName)));
56 |
57 | List enabledAppsDataList = new ArrayList<>();
58 | SharedPreferences spCustomSettings = c.getSharedPreferences(c.getString(R.string.notification_settings_custom), MODE_PRIVATE);
59 | for (ApplicationInfo appInfo : enabledApps) {
60 | CustomSettingsAppData appData = new CustomSettingsAppData();
61 | appData.appIcon = appInfo.loadIcon(pm);
62 | appData.appName = enabledAppLabels.get(appInfo.packageName);
63 | appData.packageName = appInfo.packageName;
64 | boolean usingCustomSettings = spCustomSettings
65 | .getBoolean(appInfo.packageName + "_" + c.getString(R.string.preference_use_custom_settings), false);
66 | appData.isUsingCustomSettings = usingCustomSettings;
67 | enabledAppsDataList.add(appData);
68 | }
69 | appsDataList.postValue(enabledAppsDataList);
70 | }
71 |
72 | /**
73 | * When a user have entered a specific apps custom settings, the user may have enabled/disabled
74 | * using custom settings for that app. Here we check for that and update if necessary
75 | * so that 'Using custom settings' or not is displayed correctly in the list.
76 | */
77 | public void maybeUpdateUsingCustom() {
78 | Context c = getApplication();
79 | SharedPreferences spCustomSettings = c.getSharedPreferences(c.getString(R.string.notification_settings_custom), MODE_PRIVATE);
80 | List updatedAppsDataList = appsDataList.getValue();
81 | boolean listChanged = false;
82 |
83 | for (int i = 0; i < updatedAppsDataList.size(); i++) {
84 | CustomSettingsAppData appData = updatedAppsDataList.get(i);
85 |
86 | boolean oldAppDataUsingCustomSettings = appData.isUsingCustomSettings;
87 | boolean newAppDataUsingCustomSettings = spCustomSettings
88 | .getBoolean(appData.packageName + "_" + c.getString(R.string.preference_use_custom_settings), false);
89 |
90 | if (oldAppDataUsingCustomSettings != newAppDataUsingCustomSettings) {
91 | listChanged = true;
92 | appData.isUsingCustomSettings = newAppDataUsingCustomSettings;
93 | break;
94 | }
95 | }
96 |
97 | if (listChanged) {
98 | appsDataList.setValue(updatedAppsDataList);
99 | }
100 | }
101 |
102 | public void updateAfterEnabledApplicationSettings() {
103 | loadAppListFromNewThread();
104 | }
105 |
106 | public LiveData> getAppsDataList() {
107 | return appsDataList;
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------