Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
6be6081f27 | |||
303eed4e3f | |||
f7f28ea807 | |||
75a4874225 | |||
989299cf31 |
@ -1,7 +1,8 @@
|
|||||||
# Bookwyrm-android
|
# Bookwyrm-android
|
||||||
A crappy attempt at creating an Android application for Bookwyrm. Basically, it is just bookwyrm put into a 'webview' element.
|
An Android application for Bookwyrm. Basically, it is just bookwyrm put into a 'webview' element.
|
||||||
What it does? It enables you to use BookWyrm on your Android phone without having to use a browser to go to it every time.
|
What it does? It enables you to use BookWyrm on your Android phone without having to use a browser to go to it every time.
|
||||||
It can also open links to userpages of Bookwyrm users.
|
It can also open links to userpages of Bookwyrm users.
|
||||||
|
|
||||||
This application works on: Android 6 and above.
|
This application works on: Android 6 and above.
|
||||||
|
|
||||||
|
And if you want to know, I am `@StoryDragon@wyrms.de` on BookWyrm.
|
||||||
|
@ -9,8 +9,8 @@ android {
|
|||||||
applicationId "nl.privacydragon.bookwyrm"
|
applicationId "nl.privacydragon.bookwyrm"
|
||||||
minSdk 23
|
minSdk 23
|
||||||
targetSdk 31
|
targetSdk 31
|
||||||
versionCode 3
|
versionCode 6
|
||||||
versionName "1.2.0"
|
versionName "1.2.3"
|
||||||
|
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
@ -11,8 +11,8 @@
|
|||||||
"type": "SINGLE",
|
"type": "SINGLE",
|
||||||
"filters": [],
|
"filters": [],
|
||||||
"attributes": [],
|
"attributes": [],
|
||||||
"versionCode": 3,
|
"versionCode": 6,
|
||||||
"versionName": "1.2.0",
|
"versionName": "1.2.3",
|
||||||
"outputFile": "app-release.apk"
|
"outputFile": "app-release.apk"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -192,6 +192,50 @@
|
|||||||
android:host="bookwyrm.tardis.pw"
|
android:host="bookwyrm.tardis.pw"
|
||||||
android:pathPrefix="/user/" />
|
android:pathPrefix="/user/" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
|
||||||
|
<data
|
||||||
|
android:scheme="https"
|
||||||
|
android:host="tankie.ml"
|
||||||
|
android:pathPrefix="/user/" />
|
||||||
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
|
||||||
|
<data
|
||||||
|
android:scheme="https"
|
||||||
|
android:host="masstoc.io"
|
||||||
|
android:pathPrefix="/user/" />
|
||||||
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
|
||||||
|
<data
|
||||||
|
android:scheme="https"
|
||||||
|
android:host="books.mennisch.net"
|
||||||
|
android:pathPrefix="/user/" />
|
||||||
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
|
||||||
|
<data
|
||||||
|
android:scheme="https"
|
||||||
|
android:host="bookwyrm.pt"
|
||||||
|
android:pathPrefix="/user/" />
|
||||||
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".StartActivity"
|
android:name=".StartActivity"
|
||||||
|
@ -8,6 +8,7 @@ import android.net.Uri;
|
|||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
|
import android.view.KeyEvent;
|
||||||
import android.webkit.WebResourceRequest;
|
import android.webkit.WebResourceRequest;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
import android.webkit.WebViewClient;
|
import android.webkit.WebViewClient;
|
||||||
@ -31,6 +32,7 @@ import javax.crypto.spec.GCMParameterSpec;
|
|||||||
|
|
||||||
public class HandlerActivity extends AppCompatActivity {
|
public class HandlerActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
WebView myWebView;
|
||||||
@SuppressLint("SetJavaScriptEnabled")
|
@SuppressLint("SetJavaScriptEnabled")
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@ -41,7 +43,7 @@ public class HandlerActivity extends AppCompatActivity {
|
|||||||
String appLinkAction = appLinkIntent.getAction();
|
String appLinkAction = appLinkIntent.getAction();
|
||||||
Uri appLinkData = appLinkIntent.getData();
|
Uri appLinkData = appLinkIntent.getData();
|
||||||
// End of auto-generated stuff
|
// End of auto-generated stuff
|
||||||
WebView myWebView = (WebView) findViewById(R.id.webview);
|
myWebView = (WebView) findViewById(R.id.webview);
|
||||||
myWebView.getSettings().setJavaScriptEnabled(true);
|
myWebView.getSettings().setJavaScriptEnabled(true);
|
||||||
//The user credentials are stored in the shared preferences, so first they have to be read from there.
|
//The user credentials are stored in the shared preferences, so first they have to be read from there.
|
||||||
String defaultValue = "none";
|
String defaultValue = "none";
|
||||||
@ -60,10 +62,15 @@ public class HandlerActivity extends AppCompatActivity {
|
|||||||
String pathMaybe = appLinkData.getPath();
|
String pathMaybe = appLinkData.getPath();
|
||||||
String toGoServer = "bla";
|
String toGoServer = "bla";
|
||||||
if (pathMaybe.contains("user")) {
|
if (pathMaybe.contains("user")) {
|
||||||
//If the path contains 'user', it is a user profile.
|
//If the path contains 'user', it is a user profile, unless it is followed by something like 'review'.
|
||||||
String notAtUser = pathMaybe.substring(pathMaybe.indexOf("user") + 5); //This line gets the username.
|
if (pathMaybe.contains("review") || pathMaybe.contains("generatednote") || pathMaybe.contains("quotation") || pathMaybe.contains("comment") ) {
|
||||||
String atUser = notAtUser + "@" + appLinkData.getHost(); //This appends @[HOST] to the string, so we have the full username thing needed.
|
toGoServer = "https://" + appLinkData.getHost() + pathMaybe;
|
||||||
toGoServer = "https://" + server + "/user/" + atUser;
|
}
|
||||||
|
else {
|
||||||
|
String notAtUser = pathMaybe.substring(pathMaybe.indexOf("user") + 5); //This line gets the username.
|
||||||
|
String atUser = notAtUser + "@" + appLinkData.getHost(); //This appends @[HOST] to the string, so we have the full username thing needed.
|
||||||
|
toGoServer = "https://" + server + "/user/" + atUser;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
startActivity(new Intent(HandlerActivity.this, nl.privacydragon.bookwyrm.StartActivity.class));
|
startActivity(new Intent(HandlerActivity.this, nl.privacydragon.bookwyrm.StartActivity.class));
|
||||||
}
|
}
|
||||||
@ -132,24 +139,48 @@ public class HandlerActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
view.loadUrl("javascript:(function() { document.getElementById('id_password').value = '" + passw + "'; ;})()");
|
view.loadUrl("javascript:(function() { document.getElementById('id_password').value = '" + passw + "'; ;})()");
|
||||||
view.loadUrl("javascript:(function() { document.getElementById('id_localname').value = '" + name + "'; ;})()");
|
view.loadUrl("javascript:(function() { document.getElementById('id_localname').value = '" + name + "'; ;})()");
|
||||||
view.loadUrl("javascript:(function() { if (window.location.href == '" + finalToGoServer + "') { document.getElementsByName(\"login\")[0].submit();} ;})()");
|
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)) { document.getElementsByClassName(\"block\")[0].innerHTML = ` <a href=\"https://"+ server +"\" class=\"button\" data-back=\"\">\n" +
|
||||||
|
" <span class=\"icon icon-arrow-left\" aria-hidden=\"true\"></span>\n" +
|
||||||
|
" <span><b>Back to homeserver</b></span>\n" +
|
||||||
|
" </a>`;} ;})()");
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
//Here, load the login page of the server. That actually does all that is needed.
|
//Here, load the login page of the server. That actually does all that is needed.
|
||||||
myWebView.loadUrl(toGoServer);
|
myWebView.loadUrl(toGoServer);
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
public boolean onKeyDown(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();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
//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.
|
//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.
|
||||||
//Yes, I used the web for this too.
|
//Yes, I used the web for this too.
|
||||||
private class MyWebViewClient extends WebViewClient {
|
private class MyWebViewClient extends WebViewClient {
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
|
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
|
||||||
|
// ATTENTION: This was auto-generated to handle app links.
|
||||||
|
Intent appLinkIntent = getIntent();
|
||||||
|
String appLinkAction = appLinkIntent.getAction();
|
||||||
|
Uri appLinkData = appLinkIntent.getData();
|
||||||
|
// End of auto-generated stuff
|
||||||
|
String strangeHost = appLinkData.getHost();
|
||||||
SharedPreferences sharedPref = HandlerActivity.this.getSharedPreferences(getString(R.string.server), Context.MODE_PRIVATE);
|
SharedPreferences sharedPref = HandlerActivity.this.getSharedPreferences(getString(R.string.server), Context.MODE_PRIVATE);
|
||||||
String defaultValue = "none";
|
String defaultValue = "none";
|
||||||
String server = sharedPref.getString(getString(R.string.server), defaultValue);
|
String server = sharedPref.getString(getString(R.string.server), defaultValue);
|
||||||
if (server.equals(request.getUrl().getHost())) {
|
if (server.equals(request.getUrl().getHost())) {
|
||||||
//If the server is the same as the bookwyrm, load it in the webview.
|
//If the server is the same as the bookwyrm, load it in the webview.
|
||||||
return false;
|
return false;
|
||||||
|
} else if (strangeHost.equals(request.getUrl().getHost())) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
// Otherwise, it should go to the default browser instead.
|
// Otherwise, it should go to the default browser instead.
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW, request.getUrl());
|
Intent intent = new Intent(Intent.ACTION_VIEW, request.getUrl());
|
||||||
|
@ -7,6 +7,7 @@ import android.content.SharedPreferences;
|
|||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
|
import android.view.KeyEvent;
|
||||||
import android.webkit.WebResourceRequest;
|
import android.webkit.WebResourceRequest;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
import android.webkit.WebViewClient;
|
import android.webkit.WebViewClient;
|
||||||
@ -29,13 +30,13 @@ import javax.crypto.NoSuchPaddingException;
|
|||||||
import javax.crypto.spec.GCMParameterSpec;
|
import javax.crypto.spec.GCMParameterSpec;
|
||||||
|
|
||||||
public class StartActivity extends AppCompatActivity {
|
public class StartActivity extends AppCompatActivity {
|
||||||
|
WebView myWebView;
|
||||||
@SuppressLint("SetJavaScriptEnabled")
|
@SuppressLint("SetJavaScriptEnabled")
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_start);
|
setContentView(R.layout.activity_start);
|
||||||
WebView myWebView = (WebView) findViewById(R.id.webview);
|
myWebView = (WebView) findViewById(R.id.webview);
|
||||||
myWebView.getSettings().setJavaScriptEnabled(true);
|
myWebView.getSettings().setJavaScriptEnabled(true);
|
||||||
//The user credentials are stored in the shared preferences, so first they have to be read from there.
|
//The user credentials are stored in the shared preferences, so first they have to be read from there.
|
||||||
String defaultValue = "none";
|
String defaultValue = "none";
|
||||||
@ -118,6 +119,17 @@ public class StartActivity extends AppCompatActivity {
|
|||||||
//Here, load the login page of the server. That actually does all that is needed.
|
//Here, load the login page of the server. That actually does all that is needed.
|
||||||
myWebView.loadUrl("https://" + server + "/login");
|
myWebView.loadUrl("https://" + server + "/login");
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
public boolean onKeyDown(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();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
//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.
|
//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.
|
||||||
//Yes, I used the web for this too.
|
//Yes, I used the web for this too.
|
||||||
private class MyWebViewClient extends WebViewClient {
|
private class MyWebViewClient extends WebViewClient {
|
||||||
|
3
fastlane/metadata/android/en-US/changelogs/6.txt
Normal file
3
fastlane/metadata/android/en-US/changelogs/6.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Initial release for F-Droid.
|
||||||
|
|
||||||
|
* Added support for four more BookWyrm instances.
|
@ -1,2 +1,3 @@
|
|||||||
This is a, probably crappy, Android client for BookWyrm.
|
This is an Android client for BookWyrm.
|
||||||
It is just BookWyrm put into a webview element, nothing special.
|
It is just BookWyrm put into a webview element, nothing special.
|
||||||
|
<b>This application is <u>not</u> an official client!</b> (An official client does not exist yet, as far as I know)
|
||||||
|
Before Width: | Height: | Size: 302 KiB After Width: | Height: | Size: 302 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/2.png
Normal file
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 247 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/3.png
Normal file
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 204 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/4.png
Normal file
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/4.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 46 KiB |
Reference in New Issue
Block a user