Compare commits
11 Commits
v1.3.2
...
csrf-fix-h
Author | SHA1 | Date | |
---|---|---|---|
f2eb043e7f | |||
e17daa9e41 | |||
dadaaf2a04 | |||
b2eba70188 | |||
ebb434b1b3 | |||
f79d9300ed | |||
78b7654b8d | |||
e55426bc90 | |||
5c8b038a99 | |||
4cfbee2524 | |||
6b44f589ac |
2
.idea/compiler.xml
generated
2
.idea/compiler.xml
generated
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="11" />
|
||||
<bytecodeTargetLevel target="17" />
|
||||
</component>
|
||||
</project>
|
4
.idea/deploymentTargetDropDown.xml
generated
4
.idea/deploymentTargetDropDown.xml
generated
@ -7,11 +7,11 @@
|
||||
<deviceKey>
|
||||
<Key>
|
||||
<type value="VIRTUAL_DEVICE_PATH" />
|
||||
<value value="$USER_HOME$/.android/avd/Pixel_5_API_26.avd" />
|
||||
<value value="$USER_HOME$/.android/avd/Pixel_2_API_24.avd" />
|
||||
</Key>
|
||||
</deviceKey>
|
||||
</Target>
|
||||
</targetSelectedWithDropDown>
|
||||
<timeTargetWasSelectedWithDropDown value="2022-04-24T09:01:51.756259Z" />
|
||||
<timeTargetWasSelectedWithDropDown value="2023-01-19T17:01:06.009496Z" />
|
||||
</component>
|
||||
</project>
|
10
.idea/deploymentTargetSelector.xml
generated
Normal file
10
.idea/deploymentTargetSelector.xml
generated
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="deploymentTargetSelector">
|
||||
<selectionStates>
|
||||
<SelectionState runConfigName="app">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
</SelectionState>
|
||||
</selectionStates>
|
||||
</component>
|
||||
</project>
|
6
.idea/gradle.xml
generated
6
.idea/gradle.xml
generated
@ -4,16 +4,16 @@
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="testRunner" value="GRADLE" />
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="testRunner" value="CHOOSE_PER_TEST" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
<option name="resolveExternalAnnotations" value="false" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
|
8
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
8
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="ExtractMethodRecommender" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="minLength" value="515" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
10
.idea/migrations.xml
generated
Normal file
10
.idea/migrations.xml
generated
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectMigrations">
|
||||
<option name="MigrateToGradleLocalJavaHome">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
3
.idea/misc.xml
generated
3
.idea/misc.xml
generated
@ -1,4 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DesignSurface">
|
||||
<option name="filePathToZoomLevelMap">
|
||||
@ -11,7 +10,7 @@
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="Android Studio default JDK" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="corretto-17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
17
.idea/runConfigurations.xml
generated
Normal file
17
.idea/runConfigurations.xml
generated
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
|
||||
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
|
||||
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
@ -5,7 +5,13 @@ It can also open links to userpages of Bookwyrm users and it can scan ISBN codes
|
||||
|
||||
This application works on: Android 6 and above.
|
||||
|
||||
And if you want to know, I am [`@StoryDragon@wyrms.de`](https://wyrms.de/user/storydragon) on BookWyrm.
|
||||
And if you want to know, I am [`@StoryDragon@books.storydragon.nl`](https://books.storydragon.nl/user/storydragon) on BookWyrm.
|
||||
|
||||
For the ISBN-scanning I use the library zxing-android-embedded.
|
||||
The barcode icon that is added for instances that do not have ISBN-scanning by default comes from the Remix Icon project.
|
||||
|
||||
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
|
||||
alt="Get it on F-Droid"
|
||||
height="80">](https://f-droid.org/packages/nl.privacydragon.bookwyrm/)
|
||||
|
||||
Or download the latest APK from the [Releases Section](https://github.com/PrivacyDragon/Bookwyrm_Android/releases/latest).
|
||||
|
@ -3,14 +3,14 @@ plugins {
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdk 31
|
||||
compileSdk 34
|
||||
|
||||
defaultConfig {
|
||||
applicationId "nl.privacydragon.bookwyrm"
|
||||
minSdk 23
|
||||
targetSdk 31
|
||||
versionCode 9
|
||||
versionName "1.3.2"
|
||||
targetSdk 34
|
||||
versionCode 13
|
||||
versionName "1.3.6"
|
||||
|
||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||
}
|
||||
@ -18,6 +18,7 @@ android {
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
vcsInfo.include false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
@ -25,18 +26,22 @@ android {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
namespace 'nl.privacydragon.bookwyrm'
|
||||
dependenciesInfo {
|
||||
includeInApk false
|
||||
includeInBundle false
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||
implementation 'androidx.appcompat:appcompat:1.7.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
|
||||
implementation platform('org.jetbrains.kotlin:kotlin-bom:2.1.0')
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
implementation 'com.google.zxing:core:3.3.0'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
|
||||
implementation 'com.google.zxing:core:3.5.3'
|
||||
implementation 'com.journeyapps:zxing-android-embedded:4.3.0@aar'
|
||||
//implementation 'com.github.yuriy-budiyev:code-scanner:2.1.2'
|
||||
|
||||
|
||||
}
|
Binary file not shown.
BIN
app/release/Bookwyrm-v1.3.6.apk
Normal file
BIN
app/release/Bookwyrm-v1.3.6.apk
Normal file
Binary file not shown.
@ -11,10 +11,27 @@
|
||||
"type": "SINGLE",
|
||||
"filters": [],
|
||||
"attributes": [],
|
||||
"versionCode": 9,
|
||||
"versionName": "1.3.2",
|
||||
"versionCode": 13,
|
||||
"versionName": "1.3.6",
|
||||
"outputFile": "app-release.apk"
|
||||
}
|
||||
],
|
||||
"elementType": "File"
|
||||
"elementType": "File",
|
||||
"baselineProfiles": [
|
||||
{
|
||||
"minApi": 28,
|
||||
"maxApi": 30,
|
||||
"baselineProfiles": [
|
||||
"baselineProfiles/1/app-release.dm"
|
||||
]
|
||||
},
|
||||
{
|
||||
"minApi": 31,
|
||||
"maxApi": 2147483647,
|
||||
"baselineProfiles": [
|
||||
"baselineProfiles/0/app-release.dm"
|
||||
]
|
||||
}
|
||||
],
|
||||
"minSdkVersionForDexing": 23
|
||||
}
|
@ -1,7 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="nl.privacydragon.bookwyrm">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
@ -11,7 +9,8 @@
|
||||
<uses-feature android:name="android.hardware.camera" />
|
||||
|
||||
<application
|
||||
android:allowBackup="false"
|
||||
android:fullBackupContent="false"
|
||||
android:dataExtractionRules="@xml/backup_rules"
|
||||
android:icon="@mipmap/ic_launcher_wyrm"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_wyrm_round"
|
||||
@ -20,316 +19,738 @@
|
||||
<meta-data
|
||||
android:name="android.webkit.WebView.MetricsOptOut"
|
||||
android:value="true" />
|
||||
|
||||
<activity
|
||||
android:name=".HandlerActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="wyrms.de"
|
||||
android:pathPrefix="/user/"
|
||||
android:scheme="https" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="wyrms.de" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="bookwyrm.social"
|
||||
android:pathPrefix="/user/"
|
||||
android:scheme="https" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="bookwyrm.social" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="book.dansmonorage.blue"
|
||||
android:pathPrefix="/user/"
|
||||
android:scheme="https" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="book.dansmonorage.blue" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="yyyyy.club"
|
||||
android:pathPrefix="/user/"
|
||||
android:scheme="https" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="yyyyy.club" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="books.mxhdr.net"
|
||||
android:pathPrefix="/user/"
|
||||
android:scheme="https" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="books.mxhdr.net" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="ziurkes.group.lt"
|
||||
android:pathPrefix="/user/"
|
||||
android:scheme="https" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="ziurkes.group.lt" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="books.solarpunk.moe"
|
||||
android:pathPrefix="/user/"
|
||||
android:scheme="https" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="books.solarpunk.moe" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="reading.taks.garden"
|
||||
android:pathPrefix="/user/"
|
||||
android:scheme="https" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="reading.taks.garden" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="bookwyrm.spaceling.sh"
|
||||
android:pathPrefix="/user/"
|
||||
android:scheme="https" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="bookwyrm.spaceling.sh" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="lire.boitam.eu"
|
||||
android:pathPrefix="/user/"
|
||||
android:scheme="https" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="lire.boitam.eu" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="kirja.casa"
|
||||
android:pathPrefix="/user/"
|
||||
android:scheme="https" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="kirja.casa" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="books.badwolfbay.games"
|
||||
android:pathPrefix="/user/"
|
||||
android:scheme="https" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="books.badwolfbay.games" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="books.unexist.dev"
|
||||
android:pathPrefix="/user/"
|
||||
android:scheme="https" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="books.unexist.dev" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="bookwyrm.cincodenada.com"
|
||||
android:pathPrefix="/user/"
|
||||
android:scheme="https" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="bookwyrm.cincodenada.com" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="books.underscore.world"
|
||||
android:pathPrefix="/user/"
|
||||
android:scheme="https" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="books.underscore.world" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="bookwyrm.tardis.pw"
|
||||
android:pathPrefix="/user/"
|
||||
android:scheme="https" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="bookwyrm.tardis.pw" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="tankie.ml"
|
||||
android:pathPrefix="/user/"
|
||||
android:scheme="https" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="masstoc.io" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="masstoc.io"
|
||||
android:pathPrefix="/user/"
|
||||
android:scheme="https" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="tankie.ml" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="books.mennisch.net"
|
||||
android:pathPrefix="/user/"
|
||||
android:scheme="https" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="books.mennisch.net" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="bookwyrm.pt"
|
||||
android:pathPrefix="/user/"
|
||||
android:scheme="https" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="bookwyrm.pt" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:scheme="https"
|
||||
android:host="bookwyrm.lond.com.br"
|
||||
android:pathPrefix="/user/" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="bookwyrm.lond.com.br" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:scheme="https"
|
||||
android:host="good.franv.site"
|
||||
android:pathPrefix="/user/" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="good.franv.site" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:scheme="https"
|
||||
android:host="books.solarpunkanarchism.org"
|
||||
android:pathPrefix="/user/" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="books.solarpunkanarchism.org" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:scheme="https"
|
||||
android:host="shoko.one"
|
||||
android:pathPrefix="/user/" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="shoko.one" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:scheme="https"
|
||||
android:host="bookwyrm.mennisch.net"
|
||||
android:pathPrefix="/user/" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="bookwyrm.mennisch.net" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:scheme="https"
|
||||
android:host="library.southfox.me"
|
||||
android:pathPrefix="/user/" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="bookrastinating.com" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:scheme="https"
|
||||
android:host="bookrastinating.com"
|
||||
android:pathPrefix="/user/" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="library.cybre.city" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:scheme="https"
|
||||
android:host="library.cybre.city"
|
||||
android:pathPrefix="/user/" />
|
||||
<data android:scheme="https" />
|
||||
<data android:host="books.storydragon.nl" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="reading.unbl.ink" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="velhaestante.com.br" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="bookwyrm.gatti.ninja" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="books.theunseen.city" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="lore.livellosegreto.it" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="books.jascha.wtf" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="bw.diaspodon.fr" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="bookwyrm.tilde.zone" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="libros.mistli.net" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="orreadi.com" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="lectura.social" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="bookishbook.club" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="bookwyrm.tech" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="comelibros.club" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="ramblingreaders.org" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="secretbearlibrary.org" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="grimoire.party" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="biblio.thekambattu.rocks" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="buecher.pnpde.social" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="bouquins.zbeul.fr" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="boundcovers.com" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="tomes.tchncs.de" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="bw.heraut.eu" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="bookwyrm.welhaba.mx" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="books.regenpfeifer.net" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="libroj.org" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="bookshelf.hutchie.scot" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="b.skobk.in" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="outside.ofa.dog" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="books.babb.no" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="millefeuilles.cloud" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="grimoire.social" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="bookwyrm.it" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="books.chriswb.dev" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="leselog.de" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="reads.netsphere.pub" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="bookwyrm.world" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="reads.caskey-demaret.se" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="library.southfox.me" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="wyrm.maraval.net" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="sfba.club" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="linguistic.earth" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="wyrmsign.org" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="book.dadalo.pl" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="books.bimbiribase.xyz" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="bolha.review" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="plaerdemavida.cat" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="paperjale.eus" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="books.duck.cafe" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="books.hccp.org" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="library.chatan.cc" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="knowledgehub.social" />
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
<data android:host="alexandria.the1977project.org" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
|
@ -1,63 +1,41 @@
|
||||
package nl.privacydragon.bookwyrm;
|
||||
|
||||
import static androidx.core.content.ContextCompat.startActivity;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
//import android.support.v4.app.ActivityCompat;
|
||||
//import android.support.v4.content.ContextCompat;
|
||||
//import android.support.v7.app.AppCompatActivity;
|
||||
import android.os.Bundle;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.webkit.ConsoleMessage;
|
||||
import android.webkit.JavascriptInterface;
|
||||
import android.webkit.PermissionRequest;
|
||||
import android.webkit.ValueCallback;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebResourceRequest;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.google.zxing.integration.android.IntentIntegrator;
|
||||
import com.google.zxing.integration.android.IntentResult;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Key;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.CertificateException;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.spec.GCMParameterSpec;
|
||||
import com.journeyapps.barcodescanner.ScanContract;
|
||||
import com.journeyapps.barcodescanner.ScanOptions;
|
||||
|
||||
public class HandlerActivity extends AppCompatActivity {
|
||||
|
||||
WebView myWebView;
|
||||
ProgressBar LoadIndicator;
|
||||
public ValueCallback<Uri[]> omhooglader;
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@ -68,11 +46,26 @@ public class HandlerActivity extends AppCompatActivity {
|
||||
String appLinkAction = appLinkIntent.getAction();
|
||||
Uri appLinkData = appLinkIntent.getData();
|
||||
// End of auto-generated stuff
|
||||
ActivityResultLauncher<Intent> voodooLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.StartActivityForResult(),
|
||||
result -> {
|
||||
if (result.getResultCode() == Activity.RESULT_OK) {
|
||||
// There are no request codes
|
||||
Intent data = result.getData();
|
||||
if (omhooglader == null)
|
||||
return;
|
||||
omhooglader.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(result.getResultCode(), data));
|
||||
} else {
|
||||
omhooglader.onReceiveValue(null);
|
||||
}
|
||||
});
|
||||
LoadIndicator = (ProgressBar) findViewById(R.id.progressBar3);
|
||||
myWebView = (WebView) findViewById(R.id.webview);
|
||||
myWebView.setVisibility(View.GONE);
|
||||
myWebView.getSettings().setJavaScriptEnabled(true);
|
||||
myWebView.getSettings().setDomStorageEnabled(true);
|
||||
myWebView.getSettings().setAllowFileAccess(true);
|
||||
myWebView.getSettings().setAllowContentAccess(true);
|
||||
myWebView.addJavascriptInterface(new Object()
|
||||
{
|
||||
@JavascriptInterface // For API 17+
|
||||
@ -84,26 +77,45 @@ public class HandlerActivity extends AppCompatActivity {
|
||||
|
||||
}
|
||||
}, "scan");
|
||||
myWebView.setWebChromeClient(new WebChromeClient() {
|
||||
@Override
|
||||
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
|
||||
if (omhooglader != null) {
|
||||
//omhooglader.onReceiveValue(null);
|
||||
omhooglader = null;
|
||||
}
|
||||
omhooglader = filePathCallback;
|
||||
Intent intent = fileChooserParams.createIntent();
|
||||
try {
|
||||
voodooLauncher.launch(intent);
|
||||
} catch (ActivityNotFoundException grrr){
|
||||
omhooglader = null;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
//myWebView.addJavascriptInterface(new HandlerActivity.WebAppInterface(this), "Android");
|
||||
//The user credentials are stored in the shared preferences, so first they have to be read from there.
|
||||
String defaultValue = "none";
|
||||
SharedPreferences sharedPref = HandlerActivity.this.getSharedPreferences(getString(R.string.server), Context.MODE_PRIVATE);
|
||||
String server = sharedPref.getString(getString(R.string.server), defaultValue);
|
||||
SharedPreferences sharedPrefName = HandlerActivity.this.getSharedPreferences(getString(R.string.name), Context.MODE_PRIVATE);
|
||||
String name = sharedPrefName.getString(getString(R.string.name), defaultValue);
|
||||
SharedPreferences sharedPrefPass = HandlerActivity.this.getSharedPreferences(getString(R.string.pw), Context.MODE_PRIVATE);
|
||||
String pass = sharedPrefPass.getString(getString(R.string.pw), defaultValue);
|
||||
SharedPreferences sharedPrefMagic = HandlerActivity.this.getSharedPreferences(getString(R.string.q), Context.MODE_PRIVATE);
|
||||
String codeMagic = sharedPrefMagic.getString(getString(R.string.q), defaultValue);
|
||||
//SharedPreferences sharedPrefName = HandlerActivity.this.getSharedPreferences(getString(R.string.name), Context.MODE_PRIVATE);
|
||||
//String name = sharedPrefName.getString(getString(R.string.name), defaultValue);
|
||||
//SharedPreferences sharedPrefPass = HandlerActivity.this.getSharedPreferences(getString(R.string.pw), Context.MODE_PRIVATE);
|
||||
//String pass = sharedPrefPass.getString(getString(R.string.pw), defaultValue);
|
||||
//SharedPreferences sharedPrefMagic = HandlerActivity.this.getSharedPreferences(getString(R.string.q), Context.MODE_PRIVATE);
|
||||
//String codeMagic = sharedPrefMagic.getString(getString(R.string.q), defaultValue);
|
||||
//If there is nothing configured yet, the user should be redirected to the main screen for logging in.
|
||||
if (server == "none") {
|
||||
startActivity(new Intent(HandlerActivity.this, nl.privacydragon.bookwyrm.MainActivity.class));
|
||||
}
|
||||
String pathMaybe = appLinkData.getPath();
|
||||
String toGoServer = "bla";
|
||||
if (pathMaybe.contains("user")) {
|
||||
//This bit of code regelt wanneer de webpagina wordt weergegeven. It is quite handig then om dan ook "book" toe te laten, zodat ook boeken in de app bekeken kunnen worden...
|
||||
if (pathMaybe.contains("user") || pathMaybe.contains("book")) {
|
||||
//If the path contains 'user', it is a user profile, unless it is followed by something like 'review'.
|
||||
if (pathMaybe.contains("review") || pathMaybe.contains("generatednote") || pathMaybe.contains("quotation") || pathMaybe.contains("comment") ) {
|
||||
if (pathMaybe.contains("review") || pathMaybe.contains("generatednote") || pathMaybe.contains("quotation") || pathMaybe.contains("comment") || pathMaybe.contains("book")) {
|
||||
toGoServer = "https://" + appLinkData.getHost() + pathMaybe;
|
||||
}
|
||||
else {
|
||||
@ -112,65 +124,70 @@ public class HandlerActivity extends AppCompatActivity {
|
||||
toGoServer = "https://" + server + "/user/" + atUser;
|
||||
}
|
||||
} else {
|
||||
//If the toGoServer string remains "bla", dan zal de user when they teruggaan uitkomen op https://bla/, which is 'not allowed'.
|
||||
//So, maybe here, just to be sure, assign the value of the user's own server to the toGoServer variabele.
|
||||
//After that, since apparently I have decided that the URL the user tried to follow is not valid in my application, redirect them to StartActivity.
|
||||
toGoServer = "https://" + server;
|
||||
startActivity(new Intent(HandlerActivity.this, nl.privacydragon.bookwyrm.StartActivity.class));
|
||||
}
|
||||
//Then all the decryption stuff has to happen. There are a lot of try-catch stuff, because apparently that seems to be needed.
|
||||
//First get the keystore thing.
|
||||
KeyStore keyStore = null;
|
||||
try {
|
||||
keyStore = KeyStore.getInstance("AndroidKeyStore");
|
||||
} catch (KeyStoreException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//Then, load it. or something. To make sure that it can be used.
|
||||
try {
|
||||
keyStore.load(null);
|
||||
} catch (CertificateException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//Next, retrieve the key to be used for the decryption.
|
||||
Key DragonLikeKey = null;
|
||||
try {
|
||||
DragonLikeKey = keyStore.getKey("BookWyrm", null);
|
||||
} catch (KeyStoreException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
} catch (UnrecoverableKeyException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//Do something with getting the/a cipher or something.
|
||||
Cipher c = null;
|
||||
try {
|
||||
c = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchPaddingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//And then initiating the cipher, so it can be used.
|
||||
try {
|
||||
c.init(Cipher.DECRYPT_MODE, DragonLikeKey, new GCMParameterSpec(128, codeMagic.getBytes()));
|
||||
} catch (InvalidAlgorithmParameterException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidKeyException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//Decrypt the password!
|
||||
byte[] truePass = null;
|
||||
try {
|
||||
truePass = c.doFinal(Base64.decode(pass, Base64.DEFAULT));
|
||||
} catch (BadPaddingException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalBlockSizeException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//Convert the decrypted password back to a string.
|
||||
String passw = new String(truePass, StandardCharsets.UTF_8);
|
||||
// KeyStore keyStore = null;
|
||||
// try {
|
||||
// keyStore = KeyStore.getInstance("AndroidKeyStore");
|
||||
// } catch (KeyStoreException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// //Then, load it. or something. To make sure that it can be used.
|
||||
// try {
|
||||
// keyStore.load(null);
|
||||
// } catch (CertificateException e) {
|
||||
// e.printStackTrace();
|
||||
// } catch (IOException e) {
|
||||
// e.printStackTrace();
|
||||
// } catch (NoSuchAlgorithmException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// //Next, retrieve the key to be used for the decryption.
|
||||
// Key DragonLikeKey = null;
|
||||
// try {
|
||||
// DragonLikeKey = keyStore.getKey("BookWyrm", null);
|
||||
// } catch (KeyStoreException e) {
|
||||
// e.printStackTrace();
|
||||
// } catch (NoSuchAlgorithmException e) {
|
||||
// e.printStackTrace();
|
||||
// } catch (UnrecoverableKeyException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// //Do something with getting the/a cipher or something.
|
||||
// Cipher c = null;
|
||||
// try {
|
||||
// c = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
// } catch (NoSuchAlgorithmException e) {
|
||||
// e.printStackTrace();
|
||||
// } catch (NoSuchPaddingException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// //And then initiating the cipher, so it can be used.
|
||||
// try {
|
||||
// c.init(Cipher.DECRYPT_MODE, DragonLikeKey, new GCMParameterSpec(128, codeMagic.getBytes()));
|
||||
// } catch (InvalidAlgorithmParameterException e) {
|
||||
// e.printStackTrace();
|
||||
// } catch (InvalidKeyException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// //Decrypt the password!
|
||||
// byte[] truePass = null;
|
||||
// try {
|
||||
// truePass = c.doFinal(Base64.decode(pass, Base64.DEFAULT));
|
||||
// } catch (BadPaddingException e) {
|
||||
// e.printStackTrace();
|
||||
// } catch (IllegalBlockSizeException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// //Convert the decrypted password back to a string.
|
||||
// String passw = new String(truePass, StandardCharsets.UTF_8);
|
||||
//String wacht = passw.replaceAll("'", "\\\\'");
|
||||
|
||||
//A webviewclient thing is needed for some stuff. To automatically log in, the credentials are put in the form by the javascript that is loaded once the page is fully loaded. Then it is automatically submitted if the current page is the login page.
|
||||
String finalToGoServer = toGoServer;
|
||||
@ -179,11 +196,11 @@ public class HandlerActivity extends AppCompatActivity {
|
||||
LoadIndicator.setVisibility(View.GONE);
|
||||
myWebView.setVisibility(View.VISIBLE);
|
||||
|
||||
view.loadUrl("javascript:(function() { document.getElementById('id_password').value = '" + passw + "'; ;})()");
|
||||
view.loadUrl("javascript:(function() { document.getElementById('id_localname').value = '" + name + "'; ;})()");
|
||||
view.loadUrl("javascript:(function() { if (window.location.href == '" + finalToGoServer + "' && !/(review|generatednote|quotation|comment)/i.test(window.location.href)) { document.getElementsByName(\"login\")[0].submit();} ;})()");
|
||||
view.loadUrl("javascript:(function() { if (window.location.href == 'https://" + server + "') { document.getElementsByName(\"login\")[0].submit();} ;})()");
|
||||
view.loadUrl("javascript:(function() { if (/(review|generatednote|quotation|comment)/i.test(window.location.href)) {" +
|
||||
//view.loadUrl("javascript:(function() { document.getElementById('id_password').value = '" + wacht + "'; ;})()");
|
||||
//view.loadUrl("javascript:(function() { document.getElementById('id_localname').value = '" + name + "'; ;})()");
|
||||
view.loadUrl("javascript:(function() { if (window.location.href == '" + finalToGoServer + "' && !/(review|generatednote|quotation|comment|book)/i.test(window.location.href)) { document.getElementsByName(\"login\")[0].submit();} ;})()");
|
||||
//view.loadUrl("javascript:(function() { if (window.location.href == 'https://" + server + "') { document.getElementsByName(\"login\")[0].submit();} ;})()");
|
||||
view.loadUrl("javascript:(function() { if (/(review|generatednote|quotation|comment|book)/i.test(window.location.href)) {" +
|
||||
"blocks = document.getElementsByClassName('block');" +
|
||||
"for (let element of blocks){" +
|
||||
"if (element.localName == 'header') { " +
|
||||
@ -236,10 +253,27 @@ public class HandlerActivity extends AppCompatActivity {
|
||||
}
|
||||
});*/
|
||||
//Here, load the login page of the server. That actually does all that is needed.
|
||||
//myWebView.loadUrl("https://serratus.github.io/quaggaJS/examples/live_w_locator.html");
|
||||
myWebView.loadUrl(toGoServer);
|
||||
}
|
||||
|
||||
private final ActivityResultLauncher<ScanOptions> barcodeLanceerder = registerForActivityResult(new ScanContract(),
|
||||
result -> {
|
||||
if(result.getContents() == null) {
|
||||
Toast.makeText(HandlerActivity.this, "Cancelled", Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
Toast.makeText(HandlerActivity.this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show();
|
||||
myWebView.loadUrl("Javascript:(function() {" +
|
||||
"try {" +
|
||||
"document.getElementById('tour-search').value = " + result.getContents() + ";" +
|
||||
"} catch {" +
|
||||
"document.getElementById('search_input').value = " + result.getContents() + ";" +
|
||||
"}" +
|
||||
"document.getElementsByTagName('form')[0].submit();" +
|
||||
";})()");
|
||||
LoadIndicator.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
|
||||
public void ScanBarCode() {
|
||||
String permission = Manifest.permission.CAMERA;
|
||||
int grant = ContextCompat.checkSelfPermission(HandlerActivity.this, permission);
|
||||
@ -248,54 +282,19 @@ public class HandlerActivity extends AppCompatActivity {
|
||||
permission_list[0] = permission;
|
||||
ActivityCompat.requestPermissions(HandlerActivity.this, permission_list, 1);
|
||||
}
|
||||
|
||||
IntentIntegrator intentIntegrator = new IntentIntegrator(HandlerActivity.this);
|
||||
intentIntegrator.setDesiredBarcodeFormats(intentIntegrator.EAN_13);
|
||||
intentIntegrator.setBeepEnabled(true);
|
||||
intentIntegrator.setCameraId(0);
|
||||
intentIntegrator.setPrompt("SCAN");
|
||||
intentIntegrator.setBarcodeImageEnabled(false);
|
||||
intentIntegrator.initiateScan();
|
||||
|
||||
ScanOptions eisen = new ScanOptions();
|
||||
eisen.setDesiredBarcodeFormats(ScanOptions.EAN_13);
|
||||
eisen.setBeepEnabled(true);
|
||||
eisen.setCameraId(0);
|
||||
eisen.setPrompt("SCAN ISBN");
|
||||
eisen.setBarcodeImageEnabled(false);
|
||||
barcodeLanceerder.launch(eisen);
|
||||
//return "blup";
|
||||
//return "bla";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
IntentResult Result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
|
||||
if (Result != null) {
|
||||
if (Result.getContents() == null) {
|
||||
Toast.makeText(this, "cancelled", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Log.d("MainActivity", "Scanned");
|
||||
myWebView.loadUrl("Javascript:(function() {document.getElementById('search_input').value = " + Result.getContents() + ";" +
|
||||
"document.getElementsByTagName('form')[0].submit(); ;})()");
|
||||
LoadIndicator.setVisibility(View.VISIBLE);
|
||||
|
||||
}
|
||||
} else {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
/*public class WebAppInterface {
|
||||
Context mContext;
|
||||
|
||||
//Instantiate the interface and set the context
|
||||
WebAppInterface(Context c) {
|
||||
mContext = c;
|
||||
}
|
||||
|
||||
// Show a toast from the web page
|
||||
@JavascriptInterface
|
||||
public void showToast(String toast) {
|
||||
Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}*/
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
// Check if the key event was the Back button and if there's history
|
||||
if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {
|
||||
myWebView.goBack();
|
||||
@ -303,9 +302,17 @@ public class HandlerActivity extends AppCompatActivity {
|
||||
}
|
||||
// If it wasn't the Back key or there's no web page history, bubble up to the default
|
||||
// system behavior (probably exit the activity)
|
||||
return super.onKeyDown(keyCode, event);
|
||||
return super.onKeyUp(keyCode, event);
|
||||
}
|
||||
//Here is code to make sure that links of the bookwyrm server are handled withing the webview client, instead of having it open in the default browser.
|
||||
@Override
|
||||
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
return super.onKeyLongPress(keyCode, event);
|
||||
}
|
||||
//Here is code to make sure that links of the bookwyrm server are handled within the webview client, instead of having it open in the default browser.
|
||||
//Yes, I used the web for this too.
|
||||
private class MyWebViewClient extends WebViewClient {
|
||||
@Override
|
||||
|
@ -6,7 +6,6 @@ import android.content.SharedPreferences;
|
||||
import android.graphics.Color;
|
||||
import android.security.keystore.KeyGenParameterSpec;
|
||||
import android.security.keystore.KeyProperties;
|
||||
//import android.support.v7.app.AppCompatActivity;
|
||||
import android.os.Bundle;
|
||||
import android.util.Base64;
|
||||
import android.view.View;
|
||||
@ -44,7 +43,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
SharedPreferences sharedPref = MainActivity.this.getSharedPreferences(getString(R.string.server), Context.MODE_PRIVATE);
|
||||
String defaultValue = "none";
|
||||
String server = sharedPref.getString(getString(R.string.server), defaultValue);
|
||||
if (server != "none") {
|
||||
if (!"none".equals(server)) {
|
||||
startActivity(new Intent(MainActivity.this, nl.privacydragon.bookwyrm.StartActivity.class));
|
||||
}
|
||||
}
|
||||
@ -54,8 +53,9 @@ public class MainActivity extends AppCompatActivity {
|
||||
String ALLOWED_CHARACTERS ="0123456789qwertyuiopasdfghjklzxcvbnm!@#$%^&*()_+=][{}";
|
||||
final Random random=new Random();
|
||||
final StringBuilder sb=new StringBuilder(12);
|
||||
for(int i = 0; i< 12; ++i)
|
||||
for(int i = 0; i< 12; ++i) {
|
||||
sb.append(ALLOWED_CHARACTERS.charAt(random.nextInt(ALLOWED_CHARACTERS.length())));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@ -70,7 +70,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
//All fields are required, so if one of them is empty, the user should see a warning.
|
||||
if (server.isEmpty() || pass.isEmpty() || name.isEmpty()) {
|
||||
TextView ErrorMessage = (TextView) findViewById(R.id.textView5);
|
||||
ErrorMessage.setTextColor(Color.RED);
|
||||
ErrorMessage.setTextColor(Color.YELLOW);
|
||||
ErrorMessage.setText("ERROR: All fields are required!");
|
||||
} else {
|
||||
//Likely this will be the first time the program is run. So create a new key thing in the android key store happening.
|
||||
@ -81,7 +81,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
keyGenerator.init(
|
||||
new KeyGenParameterSpec.Builder("BookWyrm",
|
||||
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
|
||||
.setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
|
||||
.setBlockModes(KeyProperties.BLOCK_MODE_GCM).setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
|
||||
.setRandomizedEncryptionRequired(false)
|
||||
.build());
|
||||
keyGenerator.generateKey();
|
||||
|
@ -2,32 +2,49 @@ package nl.privacydragon.bookwyrm;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
//import android.support.v7.app.AppCompatActivity;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.webkit.JavascriptInterface;
|
||||
import android.webkit.ValueCallback;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebResourceRequest;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.google.zxing.integration.android.IntentIntegrator;
|
||||
import com.google.zxing.integration.android.IntentResult;
|
||||
import com.journeyapps.barcodescanner.ScanContract;
|
||||
import com.journeyapps.barcodescanner.ScanOptions;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.CookieHandler;
|
||||
import java.net.CookieManager;
|
||||
import java.net.CookieStore;
|
||||
import java.net.HttpCookie;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
@ -37,6 +54,8 @@ import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
@ -47,12 +66,27 @@ import javax.crypto.spec.GCMParameterSpec;
|
||||
public class StartActivity extends AppCompatActivity {
|
||||
WebView myWebView;
|
||||
ProgressBar LoadIndicator;
|
||||
public ValueCallback<Uri[]> omhooglader;
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_start);
|
||||
LoadIndicator = (ProgressBar) findViewById(R.id.progressBar3);
|
||||
ActivityResultLauncher<Intent> voodooLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.StartActivityForResult(),
|
||||
result -> {
|
||||
if (result.getResultCode() == Activity.RESULT_OK) {
|
||||
// There are no request codes
|
||||
Intent data = result.getData();
|
||||
if (omhooglader == null)
|
||||
return;
|
||||
omhooglader.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(result.getResultCode(), data));
|
||||
}
|
||||
else {
|
||||
omhooglader.onReceiveValue(null);
|
||||
}
|
||||
});
|
||||
myWebView = (WebView) findViewById(R.id.webview);
|
||||
myWebView.setVisibility(View.GONE);
|
||||
myWebView.getSettings().setJavaScriptEnabled(true);
|
||||
@ -67,6 +101,31 @@ public class StartActivity extends AppCompatActivity {
|
||||
|
||||
}
|
||||
}, "scan");
|
||||
myWebView.setWebChromeClient(new WebChromeClient() {
|
||||
@Override
|
||||
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
|
||||
if (omhooglader != null) {
|
||||
//omhooglader.onReceiveValue(null);
|
||||
omhooglader = null;
|
||||
}
|
||||
omhooglader = filePathCallback;
|
||||
Intent intent = fileChooserParams.createIntent();
|
||||
try {
|
||||
// String toestemming = Manifest.permission.READ_EXTERNAL_STORAGE;
|
||||
// int grant = ContextCompat.checkSelfPermission(StartActivity.this, toestemming);
|
||||
// if (grant != PackageManager.PERMISSION_GRANTED) {
|
||||
// String[] permission_list = new String[1];
|
||||
// permission_list[0] = toestemming;
|
||||
// ActivityCompat.requestPermissions(StartActivity.this, permission_list, 1);
|
||||
// }
|
||||
voodooLauncher.launch(intent);
|
||||
} catch (ActivityNotFoundException grrr){
|
||||
omhooglader = null;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
//The user credentials are stored in the shared preferences, so first they have to be read from there.
|
||||
String defaultValue = "none";
|
||||
SharedPreferences sharedPref = StartActivity.this.getSharedPreferences(getString(R.string.server), Context.MODE_PRIVATE);
|
||||
@ -88,52 +147,40 @@ public class StartActivity extends AppCompatActivity {
|
||||
//Then, load it. or something. To make sure that it can be used.
|
||||
try {
|
||||
keyStore.load(null);
|
||||
} catch (CertificateException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
} catch (CertificateException | IOException | NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//Next, retrieve the key to be used for the decryption.
|
||||
Key DragonLikeKey = null;
|
||||
try {
|
||||
DragonLikeKey = keyStore.getKey("BookWyrm", null);
|
||||
} catch (KeyStoreException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
} catch (UnrecoverableKeyException e) {
|
||||
} catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//Do something with getting the/a cipher or something.
|
||||
Cipher c = null;
|
||||
try {
|
||||
c = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchPaddingException e) {
|
||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//And then initiating the cipher, so it can be used.
|
||||
try {
|
||||
assert c != null;
|
||||
c.init(Cipher.DECRYPT_MODE, DragonLikeKey, new GCMParameterSpec(128, codeMagic.getBytes()));
|
||||
} catch (InvalidAlgorithmParameterException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidKeyException e) {
|
||||
} catch (InvalidAlgorithmParameterException | InvalidKeyException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//Decrypt the password!
|
||||
byte[] truePass = null;
|
||||
try {
|
||||
truePass = c.doFinal(Base64.decode(pass, Base64.DEFAULT));
|
||||
} catch (BadPaddingException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalBlockSizeException e) {
|
||||
} catch (BadPaddingException | IllegalBlockSizeException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//Convert the decrypted password back to a string.
|
||||
String passw = new String(truePass, StandardCharsets.UTF_8);
|
||||
//String wacht = passw.replaceAll("'", "\\\\'");
|
||||
|
||||
//A webviewclient thing is needed for some stuff. To automatically log in, the credentials are put in the form by the javascript that is loaded once the page is fully loaded. Then it is automatically submitted if the current page is the login page.
|
||||
myWebView.setWebViewClient(new MyWebViewClient(){
|
||||
@ -141,9 +188,10 @@ public class StartActivity extends AppCompatActivity {
|
||||
LoadIndicator.setVisibility(View.GONE);
|
||||
myWebView.setVisibility(View.VISIBLE);
|
||||
|
||||
view.loadUrl("javascript:(function() { document.getElementById('id_password_confirm').value = '" + passw + "'; ;})()");
|
||||
view.loadUrl("javascript:(function() { document.getElementById('id_localname_confirm').value = '" + name + "'; ;})()");
|
||||
view.loadUrl("javascript:(function() { if (window.location.href == 'https://" + server + "/login') { document.getElementsByName(\"login-confirm\")[0].submit();} ;})()");
|
||||
//view.loadUrl("javascript:(function() { document.getElementById('id_password_confirm').value = '" + wacht + "'; ;})()");
|
||||
//view.loadUrl("javascript:(function() { document.getElementById('id_localname_confirm').value = '" + name + "'; ;})()");
|
||||
//view.loadUrl("javascript:(function() { if (window.location.href == 'https://" + server + "/login') { document.getElementsByName(\"login-confirm\")[0].submit();} ;})()");
|
||||
//view.loadUrl("javascript:(function() { if (window.location.href == 'https://" + server + "/login' && document.title != '403 Forbidden') { this.document.location.href = 'source://' + encodeURI(document.documentElement.outerHTML);} ;})()");
|
||||
view.loadUrl("javascript:(function() { " +
|
||||
"if (document.querySelectorAll(\"[data-modal-open]\")[0]) {" +
|
||||
"let ISBN_Button = document.querySelectorAll(\"[data-modal-open]\")[0];" +
|
||||
@ -165,8 +213,203 @@ public class StartActivity extends AppCompatActivity {
|
||||
}
|
||||
});
|
||||
//Here, load the login page of the server. That actually does all that is needed.
|
||||
myWebView.loadUrl("https://" + server + "/login");
|
||||
// try {
|
||||
// getMiddleWareToken(server, name, passw);
|
||||
// } catch (IOException e) {
|
||||
// throw new RuntimeException(e);
|
||||
// }
|
||||
// String geheimeToken = null;
|
||||
// try {
|
||||
// geheimeToken = getMiddleWareToken(server);
|
||||
// } catch (IOException e) {
|
||||
// throw new RuntimeException(e);
|
||||
// }
|
||||
// String gegevens = null;
|
||||
// try {
|
||||
// gegevens = "csrfmiddlewaretoken=" + URLEncoder.encode(geheimeToken, "UTF-8") + "&localname=" + URLEncoder.encode(name, "UTF-8") + "&password=" + URLEncoder.encode(passw, "UTF-8");
|
||||
// } catch (UnsupportedEncodingException e) {
|
||||
// throw new RuntimeException(e);
|
||||
// }
|
||||
// myWebView.postUrl("https://" + server + "/login", gegevens.getBytes());
|
||||
//myWebView.loadUrl("https://" + server + "/login");
|
||||
// myWebView.setVisibility(View.GONE);
|
||||
// LoadIndicator.setVisibility(View.VISIBLE);
|
||||
// android.webkit.CookieManager oven = android.webkit.CookieManager.getInstance();
|
||||
//myWebView.loadUrl("javascript:this.document.location.href = 'source://' + encodeURI(document.documentElement.outerHTML);");
|
||||
try {
|
||||
getMiddleWareTokenAndLogIn(server, name, passw);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
// public void logIn(String lichaam) {
|
||||
// //First, verkrijg the user credentials.
|
||||
// //The user credentials are stored in the shared preferences, so first they have to be read from there.
|
||||
// String defaultValue = "none";
|
||||
// SharedPreferences sharedPref = StartActivity.this.getSharedPreferences(getString(R.string.server), Context.MODE_PRIVATE);
|
||||
// String server = sharedPref.getString(getString(R.string.server), defaultValue);
|
||||
// SharedPreferences sharedPrefName = StartActivity.this.getSharedPreferences(getString(R.string.name), Context.MODE_PRIVATE);
|
||||
// String name = sharedPrefName.getString(getString(R.string.name), defaultValue);
|
||||
// SharedPreferences sharedPrefPass = StartActivity.this.getSharedPreferences(getString(R.string.pw), Context.MODE_PRIVATE);
|
||||
// String pass = sharedPrefPass.getString(getString(R.string.pw), defaultValue);
|
||||
// SharedPreferences sharedPrefMagic = StartActivity.this.getSharedPreferences(getString(R.string.q), Context.MODE_PRIVATE);
|
||||
// String codeMagic = sharedPrefMagic.getString(getString(R.string.q), defaultValue);
|
||||
// //Then all the decryption stuff has to happen. There are a lot of try-catch stuff, because apparently that seems to be needed.
|
||||
// //First get the keystore thing.
|
||||
// KeyStore keyStore = null;
|
||||
// try {
|
||||
// keyStore = KeyStore.getInstance("AndroidKeyStore");
|
||||
// } catch (KeyStoreException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// //Then, load it. or something. To make sure that it can be used.
|
||||
// try {
|
||||
// keyStore.load(null);
|
||||
// } catch (CertificateException | IOException | NoSuchAlgorithmException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// //Next, retrieve the key to be used for the decryption.
|
||||
// Key DragonLikeKey = null;
|
||||
// try {
|
||||
// DragonLikeKey = keyStore.getKey("BookWyrm", null);
|
||||
// } catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// //Do something with getting the/a cipher or something.
|
||||
// Cipher c = null;
|
||||
// try {
|
||||
// c = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
// } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// //And then initiating the cipher, so it can be used.
|
||||
// try {
|
||||
// assert c != null;
|
||||
// c.init(Cipher.DECRYPT_MODE, DragonLikeKey, new GCMParameterSpec(128, codeMagic.getBytes()));
|
||||
// } catch (InvalidAlgorithmParameterException | InvalidKeyException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// //Decrypt the password!
|
||||
// byte[] truePass = null;
|
||||
// try {
|
||||
// truePass = c.doFinal(Base64.decode(pass, Base64.DEFAULT));
|
||||
// } catch (BadPaddingException | IllegalBlockSizeException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// //Convert the decrypted password back to a string.
|
||||
// String passw = new String(truePass, StandardCharsets.UTF_8);
|
||||
// Log.d("body", lichaam);
|
||||
// String[] opgebroken = lichaam.split("name=\"csrfmiddlewaretoken\" value=\"");
|
||||
// String[] breukjes = opgebroken[1].split("\">");
|
||||
// String middelToken = breukjes[0];
|
||||
// String[] splitsing = lichaam.split("var csrf_token = '");
|
||||
// String[] dilemma = splitsing[1].split("';");
|
||||
// String csrf = dilemma[0];
|
||||
// Log.d("tokens", "middel= " + middelToken);
|
||||
// Log.d("tokens", "csrf= " + csrf);
|
||||
// String gegevens = null;
|
||||
// try {
|
||||
// gegevens = "csrfmiddlewaretoken=" + URLEncoder.encode(middelToken, "UTF-8") + "&localname=" + URLEncoder.encode(name, "UTF-8") + "&password=" + URLEncoder.encode(passw, "UTF-8");
|
||||
// } catch (UnsupportedEncodingException e) {
|
||||
// throw new RuntimeException(e);
|
||||
// }
|
||||
//// android.webkit.CookieManager oven = android.webkit.CookieManager.getInstance();
|
||||
//// oven.setCookie("https://" + server, "csrftoken=" + csrf);
|
||||
// myWebView.postUrl("https://" + server + "/login", gegevens.getBytes());
|
||||
// }
|
||||
public void getMiddleWareTokenAndLogIn(String server, String name, String passw) throws IOException {
|
||||
//Het idee is dat deze functie de loginpagina van de server laadt en dan de 'csrfmiddlewaretoken' uit het inlogformulier haalt,
|
||||
//Zodat dat dan gebruikt kan worden bij het inloggen.
|
||||
Thread draadje = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
URL url = new URL("https://" + server + "/login");
|
||||
CookieManager koekManager = new CookieManager();
|
||||
CookieHandler.setDefault(koekManager);
|
||||
CookieStore bakker = koekManager.getCookieStore();
|
||||
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
|
||||
try {
|
||||
InputStream ina = new BufferedInputStream(urlConnection.getInputStream());
|
||||
byte[] pagina = null;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
pagina = ina.readAllBytes();
|
||||
} else {
|
||||
pagina = new byte[30000];
|
||||
ina.read(pagina);
|
||||
}
|
||||
try {
|
||||
ina.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
String zooi = new String(pagina);
|
||||
String[] opgebroken = zooi.split("name=\"csrfmiddlewaretoken\" value=\"");
|
||||
String[] breukjes = opgebroken[1].split("\">");
|
||||
String token = breukjes[0];
|
||||
String gegevens = null;
|
||||
|
||||
String speculaas = "", THT = "";
|
||||
List<HttpCookie> koektrommel = bakker.get(URI.create("https://" + server));
|
||||
//Log.d("koek", koektrommel.toString());
|
||||
for (int i = 0; i < koektrommel.size(); ++i) {
|
||||
HttpCookie koekje = koektrommel.get(i);
|
||||
if (Objects.equals(koekje.getName(), "csrftoken")) {
|
||||
speculaas = koekje.toString();
|
||||
THT = String.valueOf(koekje.getMaxAge());
|
||||
//Log.d("domein", koekje.getDomain());
|
||||
}
|
||||
}
|
||||
try {
|
||||
gegevens = "csrfmiddlewaretoken=" + URLEncoder.encode(token, "UTF-8") + "&localname=" + URLEncoder.encode(name, "UTF-8") + "&password=" + URLEncoder.encode(passw, "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
String finalGegevens = gegevens;
|
||||
//Log.d("token", speculaas);
|
||||
String finalSpeculaas = speculaas;
|
||||
String finalTHT = THT;
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
android.webkit.CookieManager oven = android.webkit.CookieManager.getInstance();
|
||||
oven.setCookie("https://" + server, finalSpeculaas + "; Max-Age=" + finalTHT + "; Path=/; SameSite=Lax; Secure");
|
||||
myWebView.postUrl("https://" + server + "/login?next=/", finalGegevens.getBytes());
|
||||
}
|
||||
});
|
||||
|
||||
} finally {
|
||||
urlConnection.disconnect();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
draadje.start();
|
||||
//return token;
|
||||
}
|
||||
private final ActivityResultLauncher<ScanOptions> barcodeLanceerder = registerForActivityResult(new ScanContract(),
|
||||
result -> {
|
||||
if(result.getContents() == null) {
|
||||
Toast.makeText(StartActivity.this, "Cancelled", Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
Toast.makeText(StartActivity.this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show();
|
||||
myWebView.loadUrl("Javascript:(function() {" +
|
||||
"try {" +
|
||||
"document.getElementById('tour-search').value = " + result.getContents() + ";" +
|
||||
"} catch {" +
|
||||
"document.getElementById('search_input').value = " + result.getContents() + ";" +
|
||||
"}" +
|
||||
"document.getElementsByTagName('form')[0].submit();" +
|
||||
";})()");
|
||||
LoadIndicator.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
|
||||
public void ScanBarCode() {
|
||||
String permission = Manifest.permission.CAMERA;
|
||||
int grant = ContextCompat.checkSelfPermission(StartActivity.this, permission);
|
||||
@ -175,39 +418,19 @@ public class StartActivity extends AppCompatActivity {
|
||||
permission_list[0] = permission;
|
||||
ActivityCompat.requestPermissions(StartActivity.this, permission_list, 1);
|
||||
}
|
||||
|
||||
IntentIntegrator intentIntegrator = new IntentIntegrator(StartActivity.this);
|
||||
intentIntegrator.setDesiredBarcodeFormats(intentIntegrator.EAN_13);
|
||||
intentIntegrator.setBeepEnabled(false);
|
||||
intentIntegrator.setCameraId(0);
|
||||
intentIntegrator.setPrompt("SCAN ISBN");
|
||||
intentIntegrator.setBarcodeImageEnabled(false);
|
||||
intentIntegrator.initiateScan();
|
||||
|
||||
ScanOptions eisen = new ScanOptions();
|
||||
eisen.setDesiredBarcodeFormats(ScanOptions.EAN_13);
|
||||
eisen.setBeepEnabled(true);
|
||||
eisen.setCameraId(0);
|
||||
eisen.setPrompt("SCAN ISBN");
|
||||
eisen.setBarcodeImageEnabled(false);
|
||||
barcodeLanceerder.launch(eisen);
|
||||
//return "blup";
|
||||
//return "bla";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
IntentResult Result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
|
||||
if (Result != null) {
|
||||
if (Result.getContents() == null) {
|
||||
Toast.makeText(this, "cancelled", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Log.d("MainActivity", "Scanned");
|
||||
myWebView.loadUrl("Javascript:(function() {document.getElementById('search_input').value = " + Result.getContents() + ";" +
|
||||
"document.getElementsByTagName('form')[0].submit(); ;})()");
|
||||
LoadIndicator.setVisibility(View.VISIBLE);
|
||||
|
||||
}
|
||||
} else {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
// Check if the key event was the Back button and if there's history
|
||||
if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {
|
||||
myWebView.goBack();
|
||||
@ -215,9 +438,17 @@ public class StartActivity extends AppCompatActivity {
|
||||
}
|
||||
// If it wasn't the Back key or there's no web page history, bubble up to the default
|
||||
// system behavior (probably exit the activity)
|
||||
return super.onKeyDown(keyCode, event);
|
||||
return super.onKeyUp(keyCode, event);
|
||||
}
|
||||
//Here is code to make sure that links of the bookwyrm server are handled withing the webview client, instead of having it open in the default browser.
|
||||
@Override
|
||||
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
return super.onKeyLongPress(keyCode, event);
|
||||
}
|
||||
//Here is code to make sure that links of the bookwyrm server are handled within the webview client, instead of having it open in the default browser.
|
||||
//Yes, I used the web for this too.
|
||||
private class MyWebViewClient extends WebViewClient {
|
||||
@Override
|
||||
|
@ -29,7 +29,7 @@
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="1dp"
|
||||
android:layout_marginBottom="262dp"
|
||||
android:hint="bookwyrm.social"
|
||||
android:hint="e.g. bookwyrm.social"
|
||||
android:inputType="text"
|
||||
android:minHeight="48dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
|
9
app/src/main/res/xml/backup_rules.xml
Normal file
9
app/src/main/res/xml/backup_rules.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<data-extraction-rules>
|
||||
<cloud-backup>
|
||||
<exclude domain="root" path="."/>
|
||||
</cloud-backup>
|
||||
<device-transfer>
|
||||
<exclude domain="root" path="."/>
|
||||
</device-transfer>
|
||||
</data-extraction-rules>
|
@ -1,7 +1,7 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
plugins {
|
||||
id 'com.android.application' version '7.1.1' apply false
|
||||
id 'com.android.library' version '7.1.1' apply false
|
||||
id 'com.android.application' version '8.7.3' apply false
|
||||
id 'com.android.library' version '8.7.3' apply false
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
|
3
fastlane/metadata/android/en-US/changelogs/10.txt
Normal file
3
fastlane/metadata/android/en-US/changelogs/10.txt
Normal file
@ -0,0 +1,3 @@
|
||||
* Fixed a bug with the barcode scanning. Now you can scan barcodes again.
|
||||
* Dependencies have been updated to newest versions.
|
||||
* More Bookwyrm instances have been added.
|
5
fastlane/metadata/android/en-US/changelogs/11.txt
Normal file
5
fastlane/metadata/android/en-US/changelogs/11.txt
Normal file
@ -0,0 +1,5 @@
|
||||
The same as release 1.3.3, but not the one bug is actually fixed for real...
|
||||
* Fixed a bug with the barcode scanning. Now you can scan barcodes again.
|
||||
* Dependencies have been updated to newest versions.
|
||||
* More Bookwyrm instances have been added.
|
||||
|
6
fastlane/metadata/android/en-US/changelogs/12.txt
Normal file
6
fastlane/metadata/android/en-US/changelogs/12.txt
Normal file
@ -0,0 +1,6 @@
|
||||
* It is finally possible to add book covers from your own device storage.
|
||||
* You can now return to the initial log-in screen by long-pressing the 'back' button.
|
||||
* Dependencies have been updated to newest versions.
|
||||
* Compiled for up to Android 14 now.
|
||||
* Deprecated pieces of code have been rewritten.
|
||||
* More Bookwyrm instances have been added.
|
5
fastlane/metadata/android/en-US/changelogs/13.txt
Normal file
5
fastlane/metadata/android/en-US/changelogs/13.txt
Normal file
@ -0,0 +1,5 @@
|
||||
* Fixed some log-in problems.
|
||||
* Changed colour of warning text to be better visible.
|
||||
* Disabled inclusion of dependencies info and VCS info, fixing build problems for F-Droid.
|
||||
* Long-press now actually works.
|
||||
* Other minor changes
|
Binary file not shown.
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 40 KiB |
@ -18,3 +18,5 @@ android.nonTransitiveRClass=true
|
||||
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
android.defaults.buildfeatures.buildconfig=true
|
||||
android.nonFinalResIds=false
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
||||
#Mon Feb 14 18:09:26 CET 2022
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
Reference in New Issue
Block a user