1
0
Fork 0
mirror of https://github.com/syncthing/syncthing-android.git synced 2024-12-22 19:01:30 +00:00

Merge branch 'develop'

This commit is contained in:
Felix Ableitner 2017-11-13 09:31:37 +09:00
commit d9a48de886
447 changed files with 912 additions and 736 deletions

23
.gitignore vendored
View file

@ -12,7 +12,6 @@
bin/
build/
gen/
src/main/jniLibs/
obj/
.gradle/
@ -20,14 +19,6 @@ obj/
local.properties
project.properties
# Eclipse project files
.settings/
.classpath
.project
# Proguard folder generated by Eclipse
proguard/
# Intellij project files
*.iml
*.ipr
@ -37,17 +28,3 @@ proguard/
# Gradle wrapper
gradle/wrapper/gradle/
gradle/wrapper/gradlew*
# Go native dependencies
ext/golang/dist
# Syncthing native dependencies
ext/syncthing/pkg/
ext/syncthing/src/code.google.com/
ext/syncthing/src/github.com/kr/
ext/syncthing/src/github.com/mattn/
ext/syncthing/src/github.com/tools/
ext/syncthing/src/golang.org/
# gradle-play-publisher
keys.json

13
.gitmodules vendored
View file

@ -1,12 +1,3 @@
[submodule "ext/syncthing/src/github.com/syncthing/syncthing"]
path = ext/syncthing/src/github.com/syncthing/syncthing
[submodule "syncthing"]
path = syncthing/src/github.com/syncthing/syncthing
url = https://github.com/syncthing/syncthing.git
ignore = dirty
[submodule "ext/golang/go"]
path = ext/golang/go
url = https://github.com/golang/go.git
ignore = dirty
[submodule "ext/golang/go1.4"]
path = ext/golang/go1.4
url = https://github.com/golang/go.git
ignore = dirty

View file

@ -1,6 +1,7 @@
sudo: required
language: android
jdk: oraclejdk8
dist: trusty
# Install Android SDK
android:
@ -13,10 +14,18 @@ android:
- android-26
- extra-android-m2repository
# Install Android NDK (apparently there is no easier way to do this)
# https://github.com/travis-ci/travis-ci/issues/5395
before_script:
- curl -L https://dl.google.com/android/repository/android-ndk-r15c-linux-x86_64.zip -O
- unzip -q android-ndk-r15c-linux-x86_64.zip
- export ANDROID_NDK_HOME=`pwd`/android-ndk-r15c
# Install Golang
before_install:
- sudo add-apt-repository ppa:gophers/archive -y
- sudo apt-get update -qq
- sudo apt-get install golang -y
- sudo apt-get install golang-1.9-go -y
# Cache gradle dependencies
# https://docs.travis-ci.com/user/languages/android/#Caching
@ -29,5 +38,5 @@ cache:
- $HOME/.gradle/wrapper/
script:
- ./gradlew clean lint
- ./gradlew lintVitalRelease
- ./gradlew buildNative assembleDebug

View file

@ -2,29 +2,29 @@
host = https://www.transifex.com
[syncthing-android.stringsxml]
file_filter = src/main/res/values-<lang>/strings.xml
source_file = src/main/res/values/strings.xml
file_filter = app/src/main/res/values-<lang>/strings.xml
source_file = app/src/main/res/values/strings.xml
source_lang = en
type = ANDROID
lang_map = af_ZA: af-rZA, am_ET: am-rET, ar_AE: ar-rAE, ar_BH: ar-rBH, ar_DZ: ar-rDZ, ar_EG: ar-rEG, ar_IQ: ar-rIQ, ar_JO: ar-rJO, ar_KW: ar-rKW, ar_LB: ar-rLB, ar_LY: ar-rLY, ar_MA: ar-rMA, ar_OM: ar-rOM, ar_QA: ar-rQA, ar_SA: ar-rSA, ar_SY: ar-rSY, ar_TN: ar-rTN, ar_YE: ar-rYE, arn_CL: arn-rCL, as_IN: as-rIN, az_AZ: az-rAZ, ba_RU: ba-rRU, be_BY: be-rBY, bg_BG: bg-rBG, bn_BD: bn-rBD, bn_IN: bn-rIN, bo_CN: bo-rCN, br_FR: br-rFR, bs_BA: bs-rBA, ca_ES: ca-rES, co_FR: co-rFR, cs_CZ: cs-rCZ, cy_GB: cy-rGB, da_DK: da-rDK, de_AT: de-rAT, de_CH: de-rCH, de_DE: de-rDE, de_LI: de-rLI, de_LU: de-rLU, dsb_DE: dsb-rDE, dv_MV: dv-rMV, el_GR: el-rGR, en_AU: en-rAU, en_BZ: en-rBZ, en_CA: en-rCA, en_GB: en-rGB, en_IE: en-rIE, en_IN: en-rIN, en_JM: en-rJM, en_MY: en-rMY, en_NZ: en-rNZ, en_PH: en-rPH, en_SG: en-rSG, en_TT: en-rTT, en_US: en-rUS, en_ZA: en-rZA, en_ZW: en-rZW, es_AR: es-rAR, es_BO: es-rBO, es_CL: es-rCL, es_CO: es-rCO, es_CR: es-rCR, es_DO: es-rDO, es_EC: es-rEC, es_ES: es-rES, es_GT: es-rGT, es_HN: es-rHN, es_MX: es-rMX, es_NI: es-rNI, es_PA: es-rPA, es_PE: es-rPE, es_PR: es-rPR, es_PY: es-rPY, es_SV: es-rSV, es_US: es-rUS, es_UY: es-rUY, es_VE: es-rVE, et_EE: et-rEE, eu_ES: eu-rES, fa_IR: fa-rIR, fi_FI: fi-rFI, fil_PH: fil-rPH, fo_FO: fo-rFO, fr_BE: fr-rBE, fr_CA: fr-rCA, fr_CH: fr-rCH, fr_FR: fr-rFR, fr_LU: fr-rLU, fr_MC: fr-rMC, fy_NL: fy-rNL, ga_IE: ga-rIE, gd_GB: gd-rGB, gl_ES: gl-rES, gsw_FR: gsw-rFR, gu_IN: gu-rIN, ha_NG: ha-rNG, hi_IN: hi-rIN, hr_BA: hr-rBA, hr_HR: hr-rHR, hsb_DE: hsb-rDE, hu_HU: hu-rHU, hy_AM: hy-rAM, id_ID: id-rID, ig_NG: ig-rNG, ii_CN: ii-rCN, is_IS: is-rIS, it_CH: it-rCH, it_IT: it-rIT, iu_CA: iu-rCA, ja_JP: ja-rJP, ka_GE: ka-rGE, kk_KZ: kk-rKZ, kl_GL: kl-rGL, km_KH: km-rKH, kn_IN: kn-rIN, ko_KR: ko-rKR, kok_IN: kok-rIN, ky_KG: ky-rKG, lb_LU: lb-rLU, lo_LA: lo-rLA, lt_LT: lt-rLT, lv_LV: lv-rLV, mi_NZ: mi-rNZ, mk_MK: mk-rMK, ml_IN: ml-rIN, mn_CN: mn-rCN, mn_MN: mn-rMN, moh_CA: moh-rCA, mr_IN: mr-rIN, ms_BN: ms-rBN, ms_MY: ms-rMY, mt_MT: mt-rMT, nb_NO: nb-rNO, ne_NP: ne-rNP, nl_BE: nl-rBE, nl_NL: nl-rNL, nn_NO: nn-rNO, nso_ZA: nso-rZA, oc_FR: oc-rFR, or_IN: or-rIN, pa_IN: pa-rIN, pl_PL: pl-rPL, prs_AF: prs-rAF, ps_AF: ps-rAF, pt_BR: pt-rBR, pt_PT: pt-rPT, qut_GT: qut-rGT, quz_BO: quz-rBO, quz_EC: quz-rEC, quz_PE: quz-rPE, rm_CH: rm-rCH, ro_RO: ro-rRO, ru_RU: ru-rRU, rw_RW: rw-rRW, sa_IN: sa-rIN, sah_RU: sah-rRU, se_FI: se-rFI, se_NO: se-rNO, se_SE: se-rSE, si_LK: si-rLK, sk_SK: sk-rSK, sl_SI: sl-rSI, sma_NO: sma-rNO, sma_SE: sma-rSE, smj_NO: smj-rNO, smj_SE: smj-rSE, smn_FI: smn-rFI, sms_FI: sms-rFI, sq_AL: sq-rAL, sr_BA: sr-rBA, sr_CS: sr-rCS, sr_ME: sr-rME, sr_RS: sr-rRS, sv_FI: sv-rFI, sv_SE: sv-rSE, sw_KE: sw-rKE, syr_SY: syr-rSY, ta_IN: ta-rIN, te_IN: te-rIN, tg_TJ: tg-rTJ, th_TH: th-rTH, tk_TM: tk-rTM, tn_ZA: tn-rZA, tr_TR: tr-rTR, tt_RU: tt-rRU, tzm_DZ: tzm-rDZ, ug_CN: ug-rCN, uk_UA: uk-rUA, ur_PK: ur-rPK, uz_UZ: uz-rUZ, vi_VN: vi-rVN, wo_SN: wo-rSN, xh_ZA: xh-rZA, yo_NG: yo-rNG, zh_CN: zh-rCN, zh_HK: zh-rHK, zh_MO: zh-rMO, zh_SG: zh-rSG, zh_TW: zh-rTW, zu_ZA: zu-rZA, no_NO: no-rNO, he_IL: iw-rIL, he: iw, id:in
[syncthing-android.description_fulltxt]
file_filter = src/main/play/<lang>/listing/fulldescription
source_file = src/main/play/en-GB/listing/fulldescription
file_filter = app/src/main/play/<lang>/listing/fulldescription
source_file = app/src/main/play/en-GB/listing/fulldescription
source_lang = en_GB
type = TXT
lang_map = ja: ja-JP, sv: sv-SE, da: da-DK, de: de-DE, el: el-EL, es: es-ES, fi: fi-FI, it: it-IT, pl: pl-PL, nl: nl-NL, ru: ru-RU, no: no-NO, pt: pt-PT, ko: ko-KR, cs: cs-CZ, hu: hu-HU, fr: fr-FR, tr: tr-TR
[syncthing-android.description_shorttxt]
file_filter = src/main/play/<lang>/listing/shortdescription
source_file = src/main/play/en-GB/listing/shortdescription
file_filter = app/src/main/play/<lang>/listing/shortdescription
source_file = app/src/main/play/en-GB/listing/shortdescription
source_lang = en_GB
type = TXT
lang_map = ja: ja-JP, sv: sv-SE, da: da-DK, de: de-DE, el: el-EL, es: es-ES, fi: fi-FI, it: it-IT, pl: pl-PL, nl: nl-NL, ru: ru-RU, no: no-NO, pt: pt-PT, ko: ko-KR, cs: cs-CZ, hu: hu-HU, fr: fr-FR, tr: tr-TR
[syncthing-android.titletxt]
file_filter = src/main/play/<lang>/listing/title
source_file = src/main/play/en-GB/listing/title
file_filter = app/src/main/play/<lang>/listing/title
source_file = app/src/main/play/en-GB/listing/title
source_lang = en_GB
type = TXT
lang_map = ja: ja-JP, sv: sv-SE, da: da-DK, de: de-DE, el: el-EL, es: es-ES, fi: fi-FI, it: it-IT, pl: pl-PL, nl: nl-NL, ru: ru-RU, no: no-NO, pt: pt-PT, ko: ko-KR, cs: cs-CZ, hu: hu-HU, fr: fr-FR, tr: tr-TR

View file

@ -16,37 +16,30 @@ A wrapper of [Syncthing](https://github.com/syncthing/syncthing) for Android.
The project is translated on [Transifex](https://www.transifex.com/projects/p/syncthing-android/).
Translations can be updated using the [Transifex client](http://docs.transifex.com/developer/client/), using commands `tx push -s` and `tx pull -a`.
# Building
### Requirements
- Android SDK Platform (for the `compileSdkVersion` specified in [build.gradle](build.gradle))
- Android NDK Platform
- Android Support Repository
### Dependencies
- Android SDK (you can skip this if you are using Android Studio)
- Android NDK (`$ANDROID_NDK_HOME` should point at the root directory of your NDK)
- Go (see [here](https://docs.syncthing.net/dev/building.html#prerequisites) for the required version)
### Build instructions
This repository is using external dependencies so you have to initialize all submodules with --recursive option first time: `git clone https://github.com/syncthing/syncthing-android.git --recursive`.
Set the `ANDROID_NDK` environment variable to the Android NDK folder (e.g. `export ANDROID_NDK=/opt/android_ndk`).
Build Go and Syncthing using `./make-all.bash`.
Use `./gradlew assembleDebug` in the project directory to compile the APK.
To prepare a new release, execute `./prepare-release.bash`, and follow the instructions.
To check for updated gradle dependencies, run `gradle dependencyUpdates`. Additionally, the git submodule in `ext/syncthing/src/github.com/syncthing/syncthing` may need to be updated.
Make sure you clone the project with
`git clone https://github.com/syncthing/syncthing-android.git --recursive`. Alternatively, run
`git submodule init && git submodule update` in the project folder.
Build Syncthing using `./syncthing/build-syncthing.bash`. Then use `./gradlew assembleDebug` or
Android Studio to build the apk.
### Building on Windows
To build the Syncthing app on Windows we need to have cygwin installed.
From a cygwin shell in the project directory, build Go using `./make-go.bash [arch]`
After Go is built, compile syncthing using `./make-syncthing.bash [arch]`
From a cygwin shell in the project directory, build Syncthing using `./syncthing/build-syncthing.bash`
Lastly, use `./gradlew assembleDebug` in the project directory to compile the APK,
or use Android Studio to build/deploy the APK.
Lastly, use `./gradlew assembleDebug` in the project directory to compile the APK, or use Android
Studio to build/deploy the APK.
# License

6
app/.gitignore vendored Normal file
View file

@ -0,0 +1,6 @@
# generated files
/build
/src/main/jniLibs
# gradle-play-publisher
keys.json

78
app/build.gradle Normal file
View file

@ -0,0 +1,78 @@
apply plugin: 'com.android.application'
apply plugin: 'com.github.ben-manes.versions'
apply plugin: 'com.github.triplet.play'
apply plugin: 'me.tatarka.retrolambda'
dependencies {
compile 'eu.chainfire:libsuperuser:1.0.0.201704021214'
compile 'com.android.support:design:26.1.0'
compile 'com.google.zxing:android-integration:3.3.0'
compile 'com.google.code.gson:gson:2.8.2'
compile 'org.mindrot:jbcrypt:0.4'
compile 'com.google.guava:guava:20.0'
compile 'com.annimon:stream:1.1.9'
compile 'com.android.volley:volley:1.0.0'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile "com.google.dagger:dagger:2.11"
annotationProcessor "com.google.dagger:dagger-compiler:2.11"
androidTestCompile 'com.android.support.test:rules:1.0.1'
androidTestCompile 'com.android.support:support-annotations:26.1.0'
}
android {
compileSdkVersion 26
buildToolsVersion "26.0.2"
buildTypes.debug.applicationIdSuffix ".debug"
dataBinding.enabled = true
playAccountConfigs {
defaultAccountConfig {
jsonFile = file('keys.json')
}
}
defaultConfig {
applicationId "com.nutomic.syncthingandroid"
minSdkVersion 14
targetSdkVersion 26
versionCode 4132
versionName "0.10.0-beta4"
testApplicationId 'com.nutomic.syncthingandroid.test'
testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner'
playAccountConfig = playAccountConfigs.defaultAccountConfig
}
signingConfigs {
release {
storeFile file(RELEASE_STORE_FILE)
storePassword System.getenv("SIGNING_PASSWORD") ?: ""
keyAlias RELEASE_KEY_ALIAS
keyPassword System.getenv("SIGNING_PASSWORD") ?: ""
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
play {
jsonFile = file('keys.json')
uploadImages = false
track = 'production'
}
/**
* Some languages are not supported by Google Play, so we ignore them.
*/
task deleteUnsupportedPlayTranslations(type: Delete) {
delete 'src/main/play/nn'
delete 'src/main/play/el-EL'
delete 'src/main/play/nb'
delete 'src/main/play/en/'
}

View file

@ -109,7 +109,7 @@ public class MainActivity extends StateDialogActivity
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
mDrawerFragment.requestGuiUpdate();
if (new Date().getTime() > getFirstStartTime() + USAGE_REPORTING_DIALOG_DELAY &&
getApi().getOptions().getUsageReportValue() == Options.USAGE_REPORTING_UNDECIDED) {
getApi().getOptions().isUsageReportingAccepted()) {
showUsageReportingDialog();
}
break;
@ -452,7 +452,7 @@ public class MainActivity extends StateDialogActivity
Options options = getApi().getOptions();
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
options.urAccepted = Options.USAGE_REPORTING_ACCEPTED;
options.urAccepted = options.urVersionMax;
break;
case DialogInterface.BUTTON_NEGATIVE:
options.urAccepted = Options.USAGE_REPORTING_DENIED;

View file

@ -234,7 +234,7 @@ public class SettingsActivity extends SyncthingActivity {
mRelaysEnabled.setChecked(mOptions.relaysEnabled);
mGlobalAnnounceServers.setText(joiner.join(mOptions.globalAnnounceServers));
mAddress.setText(mGui.address);
mUrAccepted.setChecked(mOptions.getUsageReportValue() == Options.USAGE_REPORTING_ACCEPTED);
mUrAccepted.setChecked(mOptions.isUsageReportingAccepted());
}
@Override
@ -277,7 +277,7 @@ public class SettingsActivity extends SyncthingActivity {
case "address": mGui.address = (String) o; break;
case "urAccepted":
mOptions.urAccepted = ((boolean) o)
? Options.USAGE_REPORTING_ACCEPTED
? mOptions.urVersionMax
: Options.USAGE_REPORTING_DENIED;
break;
default: throw new InvalidParameterException();

View file

@ -10,6 +10,7 @@ import android.util.Log;
import android.widget.ImageView;
import com.android.volley.AuthFailureError;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.RequestQueue;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HurlStack;
@ -113,6 +114,11 @@ public abstract class ApiRequest {
return Optional.fromNullable(requestBody).transform(String::getBytes).orNull();
}
};
// Some requests seem to be slow or fail, make sure this doesn't break the app
// (eg if an event request fails, new event requests won't be triggered).
request.setRetryPolicy(new DefaultRetryPolicy(5000, 5,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
getVolleyQueue().add(request);
}

View file

@ -18,6 +18,7 @@ public class Options {
public int natRenewalMinutes;
public int natTimeoutSeconds;
public int urAccepted;
public int urVersionMax;
public String urUniqueId;
public String urURL;
public boolean urPostInsecurely;
@ -36,15 +37,9 @@ public class Options {
public int tempIndexMinBlocks;
public static final int USAGE_REPORTING_UNDECIDED = 0;
public static final int USAGE_REPORTING_ACCEPTED = 2;
public static final int USAGE_REPORTING_DENIED = -1;
public int getUsageReportValue() {
if (urAccepted > USAGE_REPORTING_ACCEPTED)
throw new RuntimeException("Inalid usage reporting value");
return (urAccepted == USAGE_REPORTING_ACCEPTED || urAccepted == USAGE_REPORTING_DENIED)
? urAccepted
: USAGE_REPORTING_UNDECIDED;
public boolean isUsageReportingAccepted() {
return urAccepted == urVersionMax;
}
}

View file

@ -1,12 +1,15 @@
package com.nutomic.syncthingandroid.service;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.provider.MediaStore;
import android.util.Log;
import com.annimon.stream.Stream;
@ -144,11 +147,19 @@ public class EventProcessor implements SyncthingService.OnWebGuiAvailableListene
folderPath = f.path;
}
}
File updatedFile = new File(folderPath,
(String) event.data.get("item"));
Log.i(TAG, "Notified media scanner about " + updatedFile.toString());
mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
Uri.fromFile(updatedFile)));
File updatedFile = new File(folderPath, (String) event.data.get("item"));
if (!"delete".equals(event.data.get("action"))) {
Log.i(TAG, "Rescanned file via MediaScanner: " + updatedFile.toString());
MediaScannerConnection.scanFile(mContext, new String[]{updatedFile.getPath()},
null, null);
} else {
// https://stackoverflow.com/a/29881556/1837158
Log.i(TAG, "Deleted file from MediaStore: " + updatedFile.toString());
Uri contentUri = MediaStore.Files.getContentUri("external");
ContentResolver resolver = mContext.getContentResolver();
resolver.delete(contentUri, MediaStore.Images.ImageColumns.DATA + " LIKE ?",
new String[]{updatedFile.getPath()});
}
break;
case "Ping":
// Ignored.

View file

@ -142,9 +142,14 @@ public class ConfigXml {
gui.appendChild(password);
}
String apikey = getApiKey();
boolean passwordOk;
String pw = password.getTextContent();
passwordOk = !TextUtils.isEmpty(pw) && BCrypt.checkpw(apikey, pw);
boolean passwordOk;
try {
passwordOk = !TextUtils.isEmpty(pw) && BCrypt.checkpw(apikey, pw);
} catch (IllegalArgumentException e) {
Log.w(TAG, "Malformed password", e);
passwordOk = false;
}
if (!passwordOk) {
Log.i(TAG, "Updating password");
password.setTextContent(BCrypt.hashpw(apikey, BCrypt.gensalt(4)));

Some files were not shown because too many files have changed in this diff Show more