Compare commits

...

41 Commits
v1.2 ... v1.3.2

Author SHA1 Message Date
Ricki Hirner
e558c45139 Version bump to 1.3.2 2016-10-03 20:55:42 +02:00
Ricki Hirner
a2284de509 Fetch translations from Transifex 2016-10-03 20:43:33 +02:00
Ricki Hirner
a61fe817ca Avoid "no transaction" exception 2016-10-03 20:11:18 +02:00
Ricki Hirner
15349b3d23 Use an own ISyncPlugin instance per SyncAdapter 2016-10-03 12:13:00 +02:00
Ricki Hirner
6eea640647 Minimal layout change 2016-10-03 12:12:38 +02:00
Ricki Hirner
91864f76e4 Show progress bar when synchronization is active 2016-09-26 22:57:45 +02:00
Ricki Hirner
3c303ff760 Increase SEQUENCE only when we're ORGANIZER 2016-09-24 22:23:25 +02:00
Ricki Hirner
dec4f81faa Query/use CalDAV email address as account name, if available 2016-09-24 21:33:59 +02:00
Ricki Hirner
3e691e6aef MultiSync for Cloud: one-time payment instead of subscription 2016-09-24 15:53:06 +02:00
Ricki Hirner
66ae1ddc8d Always increase SEQUENCE 2016-09-23 13:55:45 +02:00
Ricki Hirner
d757f45e8b lint: don't keep references to Context in static fields 2016-09-21 21:59:17 +02:00
Ricki Hirner
374acf1c70 Version bump to 1.3.1
* some cert4android tests
2016-09-18 17:37:08 +02:00
Ricki Hirner
b1ab14f311 Import strings from Transifex 2016-09-18 16:51:05 +02:00
Ricki Hirner
d65a021536 Always use PROPFIND instead of REPORT addressbook-query 2016-09-18 16:38:41 +02:00
Ricki Hirner
8e61320225 Add About activity for iCloud flavor 2016-09-18 16:36:11 +02:00
Ricki Hirner
ef698102f1 New icon, show license notification again 2016-09-06 23:07:00 +02:00
Ricki Hirner
47e417158f Reinitialize certificate manager when needed 2016-09-06 21:56:44 +02:00
Ricki Hirner
65d3986257 README changes 2016-09-02 12:21:11 +02:00
Ricki Hirner
c350baa863 Fetch translations from Transifex 2016-09-02 12:15:17 +02:00
Ricki Hirner
4222a5d2c6 lint optimizations
* permissions: declare AUTHENTICATE_ACCOUNTS, GET_ACCOUNTS and MANAGE_ACCOUNTS only until SDK level 22
* minor optimizations and bug fixes
2016-09-02 11:57:16 +02:00
Ricki Hirner
718bcebf20 Version bump to 1.3
* vcard4android: fix bug concerning generated formatted postal addresses
2016-09-02 00:56:06 +02:00
Ricki Hirner
c6d3370dd3 gplay version: remove donation link
Fix icons again
2016-09-02 00:56:00 +02:00
Ricki Hirner
f03e1d7948 New launcher logo
* new launcher logo (contributed by Christoph Scheidl)
2016-09-01 22:48:12 +02:00
Ricki Hirner
cff047c4cb Use cert4android instead of MemorizingTrustManager
* use cert4android instead of MemorizingTrustManager
* new app setting: distrust system certificates
* add network security config to manifest so that user-installed CAs will be accepted in Android 7 again
* update gradle
2016-09-01 22:03:38 +02:00
Ricki Hirner
7a3a9047e6 iCloud: UI and strings 2016-08-14 20:57:31 +02:00
Ricki Hirner
7edd960d47 Navigation drawer, read-only settings 2016-08-14 17:49:18 +02:00
Ricki Hirner
46a5a8a25a White icons for Apple® iCloud®, hallelujah™ 2016-08-14 13:18:45 +02:00
Ricki Hirner
a3f2c23a3c Accept intent extras for LoginActivity 2016-08-13 23:06:28 +02:00
Ricki Hirner
aaee3fbd9b Fetch translations from Transifex 2016-08-06 00:11:40 +02:00
Ricki Hirner
b80608be98 Fix OpenTasks regression bug
* version bump to 1.2.3
* enable OpenTasks sync on Android <6 again
2016-08-05 23:17:55 +02:00
Ricki Hirner
531440d5a9 Improve HTTP authentication
* use preemptive Basic auth automatically for HTTPS connections
* cache auth parameters (Basic/Digest)
2016-08-05 23:17:32 +02:00
Ricki Hirner
be8657433e Fetch translations from Transifex 2016-08-02 19:27:14 +02:00
Ricki Hirner
c5af9a735b Request ignoring battery optimization
* startup dialog: request to ignore battery optimizations
* remove F-Droid donation startup dialog (only useful for davdroid-ose)
* version bump to 1.2.2
2016-08-02 19:27:07 +02:00
Ricki Hirner
3a582c4534 Avoid sync error when OpenTasks is not installed 2016-08-01 21:49:20 +02:00
Ricki Hirner
bd3d27f883 Clean up launcher icon
* clean up launcher icon
* update dependencies
2016-08-01 21:03:21 +02:00
Ricki Hirner
601cfff788 Basic subscription management
* SDK version 24
* Subscription management and GUI
2016-08-01 20:24:32 +02:00
Ricki Hirner
2fec3e3cb8 iCloud: implement free trial 2016-07-29 15:21:17 +02:00
Ricki Hirner
c4725a9b17 Initial iCloud version
* new gradle configField: useMTM
* new gradle source dir: davdroid (for DAVdroid OSE + DAVdroid variants)
* move strings and default login fragment to davdroid source dir
* iCloud AndroidManifest: add billing permission and SubscriptionActivity
* add sync plugins
* iCloud flavor + sync plugin: in-app billing
* iCloud flavor: login credentials fragment + font
* iCloud flavor: new strings
* use account type from string assets instead of hardcoded constant
2016-07-29 14:27:05 +02:00
Ricki Hirner
70bec8e980 Allow large transactions
* version bump to 1.2.1-ose
* upgrade to okhttp 3.4.1
* ical4android/vcard4android: split oversized transactions
2016-07-27 18:24:30 +02:00
Ricki Hirner
0d0341fd62 Minor changes
* MTM: use multi-process activity
* change library repos to private ones
* upgrade Android gradle plugin
2016-07-14 22:57:00 +02:00
Ricki Hirner
b49bdda7e8 Fix NPE, add intent to view FAQ to upgrade notification 2016-07-11 12:55:55 +02:00
122 changed files with 1184 additions and 789 deletions

13
.gitmodules vendored
View File

@@ -1,13 +1,12 @@
[submodule "dav4android"]
path = dav4android
url = https://gitlab.com/bitfireAT/dav4android.git
url = ../dav4android.git
[submodule "ical4android"]
path = ical4android
url = https://gitlab.com/bitfireAT/ical4android.git
url = ../ical4android.git
[submodule "vcard4android"]
path = vcard4android
url = https://gitlab.com/bitfireAT/vcard4android.git
[submodule "MemorizingTrustManager"]
path = MemorizingTrustManager
url = https://github.com/ge0rg/MemorizingTrustManager
ignore = dirty
url = ../vcard4android.git
[submodule "cert4android"]
path = cert4android
url = ../cert4android.git

View File

@@ -13,6 +13,7 @@ Help and discussion: [DAVdroid forums](https://davdroid.bitfire.at/forums)
Parts of DAVdroid have been outsourced into these libraries:
* [cert4android](https://gitlab.com/bitfireAT/cert4android) custom certificate management
* [dav4android](https://gitlab.com/bitfireAT/dav4android) WebDAV/CalDav/CardDAV framework
* [ical4android](https://gitlab.com/bitfireAT/ical4android) iCalendar processing and Calendar Provider access
* [vcard4android](https://gitlab.com/bitfireAT/vcard4android) VCard processing and Contacts Provider access
@@ -28,7 +29,6 @@ Those libraries are used by DAVdroid (alphabetically):
* [dnsjava](http://www.xbill.org/dnsjava/) [BSD License](http://www.xbill.org/dnsjava/dnsjava-current/LICENSE)
* [ez-vcard](https://code.google.com/p/ez-vcard/) [New BSD License](http://opensource.org/licenses/BSD-3-Clause)
* [iCal4j](http://ical4j.sourceforge.net/) [New BSD License](http://sourceforge.net/p/ical4j/ical4j/ci/default/tree/LICENSE)
* [MemorizingTrustManager](https://github.com/ge0rg/MemorizingTrustManager) [MIT License](https://raw.githubusercontent.com/ge0rg/MemorizingTrustManager/master/LICENSE.txt)
* [okhttp](https://square.github.io/okhttp/) [Apache License, Version 2.0](https://square.github.io/okhttp/#license)
* [Project Lombok](http://projectlombok.org/) [MIT License](http://opensource.org/licenses/mit-license.php)
* [SLF4J](http://www.slf4j.org/) [MIT License](http://www.slf4j.org/license.html)

View File

@@ -9,26 +9,50 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
compileSdkVersion 24
buildToolsVersion '24.0.2'
defaultConfig {
applicationId "at.bitfire.davdroid"
minSdkVersion 14
targetSdkVersion 23
versionCode 109
resValue "string", "packageID", applicationId
versionCode 118
buildConfigField "long", "buildTime", System.currentTimeMillis() + "L"
minSdkVersion 14
targetSdkVersion 24
buildConfigField "boolean", "customCerts", "false"
buildConfigField "at.bitfire.vcard4android.GroupMethod", "settingContactGroupMethod", "null"
buildConfigField "Boolean", "settingVCardRFC6868", "null"
}
productFlavors {
standard {
versionName "1.2"
versionName "1.3.2"
buildConfigField "boolean", "customCerts", "true"
}
gplay {
versionName "1.2-gplay"
versionName "1.3.2-gplay"
buildConfigField "boolean", "customCerts", "true"
}
icloud {
applicationId "at.bitfire.cloudsync"
resValue "string", "packageID", applicationId
versionName "1.3.2-cloud"
buildConfigField "at.bitfire.vcard4android.GroupMethod", "settingContactGroupMethod", "at.bitfire.vcard4android.GroupMethod.GROUP_VCARDS"
buildConfigField "Boolean", "settingVCardRFC6868", "true"
}
}
sourceSets {
standard.java.srcDirs = [ "src/davdroid/java" ]
standard.res.srcDirs = [ "src/davdroid/res" ]
gplay.java.srcDirs = [ "src/gplay/java", "src/davdroid/java" ]
gplay.res.srcDirs = [ "src/gplay/res", "src/davdroid/res" ]
}
buildTypes {
@@ -64,25 +88,24 @@ android {
}
dependencies {
compile project(':cert4android')
compile project(':dav4android')
compile project(':ical4android')
compile project(':vcard4android')
compile 'com.android.support:appcompat-v7:23.+'
compile 'com.android.support:cardview-v7:23.+'
compile 'com.android.support:design:23.+'
compile 'com.android.support:preference-v14:23.+'
compile 'com.android.support:appcompat-v7:24.+'
compile 'com.android.support:cardview-v7:24.+'
compile 'com.android.support:design:24.+'
compile 'com.android.support:preference-v14:24.+'
compile 'com.github.yukuku:ambilwarna:2.0.1'
compile project(':MemorizingTrustManager')
compile 'dnsjava:dnsjava:2.1.7'
compile 'org.apache.commons:commons-lang3:3.4'
compile 'org.apache.commons:commons-collections4:4.1'
provided 'org.projectlombok:lombok:1.16.8'
provided 'org.projectlombok:lombok:1.16.10'
// for tests
testCompile 'junit:junit:4.12'
testCompile 'com.squareup.okhttp3:mockwebserver:3.3.1'
androidTestCompile 'com.squareup.okhttp3:mockwebserver:3.3.1'
testCompile 'com.squareup.okhttp3:mockwebserver:3.4.1'
androidTestCompile 'com.squareup.okhttp3:mockwebserver:3.4.1'
}

View File

@@ -16,7 +16,7 @@ import java.net.Socket;
import javax.net.ssl.SSLSocket;
import de.duenndns.ssl.MemorizingTrustManager;
import at.bitfire.cert4android.CustomCertManager;
import okhttp3.mockwebserver.MockWebServer;
public class SSLSocketFactoryCompatTest extends InstrumentationTestCase {
@@ -26,7 +26,7 @@ public class SSLSocketFactoryCompatTest extends InstrumentationTestCase {
@Override
protected void setUp() throws Exception {
factory = new SSLSocketFactoryCompat(new MemorizingTrustManager(getInstrumentation().getTargetContext().getApplicationContext()));
factory = new SSLSocketFactoryCompat(new CustomCertManager(getInstrumentation().getTargetContext().getApplicationContext(), true));
server.start();
}

View File

@@ -42,7 +42,7 @@ public class CollectionInfoTest extends TestCase {
"</response>" +
"</multistatus>"));
DavResource dav = new DavResource(HttpClient.create(), server.url("/"));
DavResource dav = new DavResource(HttpClient.create(null), server.url("/"));
dav.propfind(0, ResourceType.NAME);
CollectionInfo info = CollectionInfo.fromDavResource(dav);
assertEquals(CollectionInfo.Type.ADDRESS_BOOK, info.type);
@@ -66,7 +66,7 @@ public class CollectionInfoTest extends TestCase {
"</response>" +
"</multistatus>"));
dav = new DavResource(HttpClient.create(), server.url("/"));
dav = new DavResource(HttpClient.create(null), server.url("/"));
dav.propfind(0, ResourceType.NAME);
info = CollectionInfo.fromDavResource(dav);
assertEquals(CollectionInfo.Type.CALENDAR, info.type);

View File

@@ -53,11 +53,11 @@ public class DavResourceFinderTest extends InstrumentationTestCase {
server.setDispatcher(new TestDispatcher());
server.start();
credentials = new LoginCredentials(URI.create("/"), "mock", "12345", true);
finder = new DavResourceFinder(getInstrumentation().getContext(), credentials);
credentials = new LoginCredentials(URI.create("/"), "mock", "12345");
finder = new DavResourceFinder(getInstrumentation().getTargetContext(), credentials);
client = HttpClient.create();
client = HttpClient.addAuthentication(client, credentials.userName, credentials.password, credentials.authPreemptive);
client = HttpClient.create(null);
client = HttpClient.addAuthentication(client, credentials.userName, credentials.password);
}
@Override
@@ -129,8 +129,11 @@ public class DavResourceFinderTest extends InstrumentationTestCase {
@Override
public MockResponse dispatch(RecordedRequest rq) throws InterruptedException {
if (!checkAuth(rq))
return new MockResponse().setResponseCode(401);
if (!checkAuth(rq)) {
MockResponse authenticate = new MockResponse().setResponseCode(401);
authenticate.setHeader("WWW-Authenticate", "Basic realm=\"test\"");
return authenticate;
}
String path = rq.getPath();

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -0,0 +1,48 @@
package at.bitfire.davdroid.ui;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.view.MenuItem;
import at.bitfire.davdroid.App;
import at.bitfire.davdroid.BuildConfig;
import at.bitfire.davdroid.Constants;
import at.bitfire.davdroid.R;
public class DefaultAccountsDrawerHandler implements IAccountsDrawerHandler {
@Override
public boolean onNavigationItemSelected(@NonNull Activity activity, MenuItem item) {
switch (item.getItemId()) {
case R.id.nav_about:
activity.startActivity(new Intent(activity, AboutActivity.class));
break;
case R.id.nav_app_settings:
activity.startActivity(new Intent(activity, AppSettingsActivity.class));
break;
case R.id.nav_twitter:
activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://twitter.com/davdroidapp")));
break;
case R.id.nav_website:
activity.startActivity(new Intent(Intent.ACTION_VIEW, Constants.webUri));
break;
case R.id.nav_faq:
activity.startActivity(new Intent(Intent.ACTION_VIEW, Constants.webUri.buildUpon().appendEncodedPath("faq/").build()));
break;
case R.id.nav_forums:
activity.startActivity(new Intent(Intent.ACTION_VIEW, Constants.webUri.buildUpon().appendEncodedPath("forums/").build()));
break;
case R.id.nav_donate:
if (BuildConfig.FLAVOR != App.FLAVOR_GOOGLE_PLAY)
activity.startActivity(new Intent(Intent.ACTION_VIEW, Constants.webUri.buildUpon().appendEncodedPath("donate/").build()));
break;
default:
return false;
}
return true;
}
}

View File

@@ -8,8 +8,11 @@
package at.bitfire.davdroid.ui.setup;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
@@ -32,7 +35,7 @@ import at.bitfire.dav4android.Constants;
import at.bitfire.davdroid.R;
import at.bitfire.davdroid.ui.widget.EditPassword;
public class LoginCredentialsFragment extends Fragment implements CompoundButton.OnCheckedChangeListener {
public class DefaultLoginCredentialsFragment extends Fragment implements CompoundButton.OnCheckedChangeListener {
RadioButton radioUseEmail;
LinearLayout emailDetails;
@@ -43,9 +46,9 @@ public class LoginCredentialsFragment extends Fragment implements CompoundButton
LinearLayout urlDetails;
EditText editBaseURL, editUserName;
EditPassword editUrlPassword;
CheckBox checkPreemptiveAuth;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.login_credentials_fragment, container, false);
@@ -60,13 +63,35 @@ public class LoginCredentialsFragment extends Fragment implements CompoundButton
editBaseURL = (EditText)v.findViewById(R.id.base_url);
editUserName = (EditText)v.findViewById(R.id.user_name);
editUrlPassword = (EditPassword)v.findViewById(R.id.url_password);
checkPreemptiveAuth = (CheckBox)v.findViewById(R.id.preemptive_auth);
radioUseEmail.setOnCheckedChangeListener(this);
radioUseURL.setOnCheckedChangeListener(this);
if (savedInstanceState == null)
radioUseEmail.setChecked(true);
if (savedInstanceState == null) {
// first call
Activity activity = getActivity();
Intent intent = (activity != null) ? activity.getIntent() : null;
if (intent != null) {
// we've got initial login data
String url = intent.getStringExtra(LoginActivity.EXTRA_URL),
username = intent.getStringExtra(LoginActivity.EXTRA_USERNAME),
password = intent.getStringExtra(LoginActivity.EXTRA_PASSWORD);
if (url != null) {
radioUseURL.setChecked(true);
editBaseURL.setText(url);
editUserName.setText(username);
editUrlPassword.setText(password);
} else {
radioUseEmail.setChecked(true);
editEmailAddress.setText(username);
editEmailPassword.setText(password);
}
} else
radioUseEmail.setChecked(true);
}
final Button login = (Button)v.findViewById(R.id.login);
login.setOnClickListener(new View.OnClickListener() {
@@ -114,7 +139,7 @@ public class LoginCredentialsFragment extends Fragment implements CompoundButton
valid = false;
}
return valid ? new LoginCredentials(uri, email, password, true) : null;
return valid ? new LoginCredentials(uri, email, password) : null;
} else if (radioUseURL.isChecked()) {
URI uri = null;
@@ -159,10 +184,20 @@ public class LoginCredentialsFragment extends Fragment implements CompoundButton
valid = false;
}
return valid ? new LoginCredentials(uri, userName, password, checkPreemptiveAuth.isChecked()) : null;
return valid ? new LoginCredentials(uri, userName, password) : null;
}
return null;
}
public static class Factory implements ILoginCredentialsFragment {
@Override
public Fragment getFragment() {
return new DefaultLoginCredentialsFragment();
}
}
}

View File

@@ -0,0 +1,5 @@
<vector android:alpha="0.54" android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M19.43,12.98c0.04,-0.32 0.07,-0.64 0.07,-0.98s-0.03,-0.66 -0.07,-0.98l2.11,-1.65c0.19,-0.15 0.24,-0.42 0.12,-0.64l-2,-3.46c-0.12,-0.22 -0.39,-0.3 -0.61,-0.22l-2.49,1c-0.52,-0.4 -1.08,-0.73 -1.69,-0.98l-0.38,-2.65C14.46,2.18 14.25,2 14,2h-4c-0.25,0 -0.46,0.18 -0.49,0.42l-0.38,2.65c-0.61,0.25 -1.17,0.59 -1.69,0.98l-2.49,-1c-0.23,-0.09 -0.49,0 -0.61,0.22l-2,3.46c-0.13,0.22 -0.07,0.49 0.12,0.64l2.11,1.65c-0.04,0.32 -0.07,0.65 -0.07,0.98s0.03,0.66 0.07,0.98l-2.11,1.65c-0.19,0.15 -0.24,0.42 -0.12,0.64l2,3.46c0.12,0.22 0.39,0.3 0.61,0.22l2.49,-1c0.52,0.4 1.08,0.73 1.69,0.98l0.38,2.65c0.03,0.24 0.24,0.42 0.49,0.42h4c0.25,0 0.46,-0.18 0.49,-0.42l0.38,-2.65c0.61,-0.25 1.17,-0.59 1.69,-0.98l2.49,1c0.23,0.09 0.49,0 0.61,-0.22l2,-3.46c0.12,-0.22 0.07,-0.49 -0.12,-0.64l-2.11,-1.65zM12,15.5c-1.93,0 -3.5,-1.57 -3.5,-3.5s1.57,-3.5 3.5,-3.5 3.5,1.57 3.5,3.5 -1.57,3.5 -3.5,3.5z"/>
</vector>

View File

@@ -94,13 +94,6 @@
android:layout_height="wrap_content"
android:hint="@string/login_password"/>
<CheckBox
android:id="@+id/preemptive_auth"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/login_auth_preemptive"
android:checked="true"/>
</LinearLayout>
</RadioGroup>

View File

@@ -14,9 +14,9 @@
<!--AddAccountActivity-->
<string name="login_type_email">Entra amb una adreça de correu electrònic</string>
<string name="login_type_url">Entra amb una URL i un nom d\'usuari</string>
<string name="login_auth_preemptive">Autentificació preferent (recomanat però incompatible amb l\'autentificació Digest)</string>
<!--AccountSettingsActivity-->
<!--collection management-->
<!--ExceptionInfoFragment-->
<!--sync errors and DebugInfoActivity-->
<!--cert4android-->
</resources>

View File

@@ -7,6 +7,9 @@
<string name="please_wait">Chvíli strpení ...</string>
<string name="send">Odeslat</string>
<!--startup dialogs-->
<string name="startup_battery_optimization">Optimalizace využití baterie</string>
<string name="startup_battery_optimization_message">Android může po několika dnech vypnout/prodloužit interval synchronizování DAVdroid. Chcete-li tomuto zabránit, vypněte optimalizaci baterie.</string>
<string name="startup_battery_optimization_disable">Vypnout pro DAVdroid</string>
<string name="startup_dont_show_again">Již nezobrazovat</string>
<string name="startup_development_version">DAVdroid preview vydání</string>
<string name="startup_development_version_message">Toto je vývojová verze aplikace DAVdroid. Mějte na paměti, že vše nemusí správně fungovat. Budeme rádi za konstruktivní zpětnou vazbu, která pomůže vylepšit DAVdroid.</string>
@@ -54,13 +57,12 @@
<string name="app_settings_reset_hints_summary">Znovu povolí vypnuté texty nápovědy</string>
<string name="app_settings_reset_hints_success">Budou zobrazovány všechny texty nápovědy</string>
<string name="app_settings_security">Zabezpečení</string>
<string name="app_settings_reset_trusted_certificates">Resetovat důvěryhodné certifikáty</string>
<string name="app_settings_reset_trusted_certificates_summary">Zapomene všechny dříve akceptované certifikáty</string>
<plurals name="app_settings_reset_trusted_certificates_success">
<item quantity="one">Znedůvěryhodněn jeden certifikát</item>
<item quantity="few">Znedůvěryhodněny %d certifikáty</item>
<item quantity="other">Znedůvěryhodněno %d certifikátů</item>
</plurals>
<string name="app_settings_distrust_system_certs">Nedůvěřovat systémovým certifikátům</string>
<string name="app_settings_distrust_system_certs_on">Systémovým a uživatelem přidaným CA nebude důvěřováno</string>
<string name="app_settings_distrust_system_certs_off">Systémovým a uživatelem přidaným CA bude důvěřováno (doporučeno)</string>
<string name="app_settings_reset_certificates">Resetovat (ne)důvěryhodné certifikáty</string>
<string name="app_settings_reset_certificates_summary">Resetovat důvěryhodnost všech vlastních certifikátů</string>
<string name="app_settings_reset_certificates_success">Všechny vlastní certifikáty byly resetovány</string>
<string name="app_settings_debug">Ladění</string>
<string name="app_settings_log_to_external_storage">Logovat do externího souboru</string>
<string name="app_settings_log_to_external_storage_on">Logování do externího úložiště (pokud dostupné)</string>
@@ -102,7 +104,6 @@
<string name="login_user_name">Uživatelské jméno</string>
<string name="login_user_name_required">Vyžadováno uživatelské jméno</string>
<string name="login_base_url">Základní URL</string>
<string name="login_auth_preemptive">Preemptivní ověření (doporučeno, ale není kompatibilní s Digest ověřením)</string>
<string name="login_login">Login</string>
<string name="login_back">Zpět</string>
<string name="login_create_account">Vytvořit účet</string>
@@ -123,9 +124,6 @@
<string name="settings_password">Heslo</string>
<string name="settings_password_summary">Aktualizovat heslo dle svého serveru.</string>
<string name="settings_enter_password">Vložit své heslo:</string>
<string name="settings_preemptive">Preemptivní ověření</string>
<string name="settings_preemptive_on">Přihlašovací údaje jsou zasílány s každým požadavkem (doporučeno)</string>
<string name="settings_preemptive_off">Přihlašovací údaje jsou zasílány po vyžádání serverem</string>
<string name="settings_sync">Synchronizace</string>
<string name="settings_sync_interval_contacts">Interval synchronizace kontaktů</string>
<string name="settings_sync_summary_manually">Pouze manuálně</string>
@@ -239,4 +237,7 @@
<item>ukládání stavu synchronizace</item>
</string-array>
<string name="sync_error_unauthorized">Chybné uživatelské jméno/heslo</string>
<!--cert4android-->
<string name="certificate_notification_connection_security">DAVdroid: Zabezpečení připojení</string>
<string name="trust_certificate_unknown_certificate_found">DAVdroid nalezl neznámý certifikát. Chcete mu důvěřovat?</string>
</resources>

View File

@@ -54,12 +54,6 @@
<string name="app_settings_reset_hints_summary">Genaktiverer hjælp, som er blevet lukket tidligere</string>
<string name="app_settings_reset_hints_success">Al vejledning vil blive vist igen</string>
<string name="app_settings_security">Sikkerhed</string>
<string name="app_settings_reset_trusted_certificates">Nulstil verificerede certifikater</string>
<string name="app_settings_reset_trusted_certificates_summary">Glemmer alle certifikater, der er blevet godkendt tidligere</string>
<plurals name="app_settings_reset_trusted_certificates_success">
<item quantity="one">Ikke-accepteret certifikat</item>
<item quantity="other">%d kke-accepterede certifikater</item>
</plurals>
<string name="app_settings_debug">Debugging</string>
<string name="app_settings_log_to_external_storage">Log til ekstern fil</string>
<string name="app_settings_log_to_external_storage_on">Logger til eksternt lager (hvis muligt)</string>
@@ -101,7 +95,6 @@
<string name="login_user_name">Brugernavn</string>
<string name="login_user_name_required">Brugernavn påkrævet</string>
<string name="login_base_url">Basis-URL</string>
<string name="login_auth_preemptive">Forhåndsgodkendelse (preemptive authentication - anbefalet, men ikke kompatiblelt med Digest auth)</string>
<string name="login_login">Login</string>
<string name="login_back">Tilbage</string>
<string name="login_create_account">Opret konto</string>
@@ -122,9 +115,6 @@
<string name="settings_password">Adgangskode</string>
<string name="settings_password_summary">Opdater adgangskoden, så den svarer til din server.</string>
<string name="settings_enter_password">Indtast adgangskode:</string>
<string name="settings_preemptive">Forhåndsgodkendelse</string>
<string name="settings_preemptive_on">Loginoplysninger sendes ved hver anmodning (anbefalet)</string>
<string name="settings_preemptive_off">Loginoplysninger sendes efter server anmoder om dem</string>
<string name="settings_sync">Synkronisering</string>
<string name="settings_sync_interval_contacts">Synkroniseringsinterval for kontakter</string>
<string name="settings_sync_summary_manually">Kun manuelt</string>
@@ -237,4 +227,5 @@
<item>gemmer synkroniseringsstatus</item>
</string-array>
<string name="sync_error_unauthorized">Fejl i brugernavn/adgangskode</string>
<!--cert4android-->
</resources>

View File

@@ -7,6 +7,9 @@
<string name="please_wait">Por favor, espere...</string>
<string name="send">Enviar</string>
<!--startup dialogs-->
<string name="startup_battery_optimization">Optimización de batería</string>
<string name="startup_battery_optimization_message">Android puede desactivar/reducir la sincronización de DAVdroid después de unos días. Para prevenir esto, desactiva la optimización.</string>
<string name="startup_battery_optimization_disable">Apagar para DAVdroid</string>
<string name="startup_dont_show_again">No mostrar de nuevo</string>
<string name="startup_development_version">Versión candidata final de DAVdroid</string>
<string name="startup_development_version_message">Esta es una versión de desarrollo de DAVdroid. Tenga presente que puede que no todo funcione como espera. Por favor, denos una retroalimentación constructiva para mejorar DAVdroid.</string>
@@ -43,7 +46,7 @@
<string name="navigation_drawer_faq">Preguntas frequentes</string>
<string name="navigation_drawer_forums">Comunidad</string>
<string name="navigation_drawer_donate">Donar</string>
<string name="account_list_empty">Bienvenido a DAVdroid!\n\nAhora puede añadir una cuenta CalDAV/CardDAV.</string>
<string name="account_list_empty">Bienvenido a DAVdroid!\n\nAhora puedes añadir una cuenta CalDAV/CardDAV.</string>
<!--DavService-->
<string name="dav_service_refresh_failed">Falló la detección del servicio</string>
<string name="dav_service_refresh_couldnt_refresh">No se pudo refrescar lista de colección</string>
@@ -51,15 +54,15 @@
<string name="app_settings">Ajustes</string>
<string name="app_settings_user_interface">Interfaz de usuario</string>
<string name="app_settings_reset_hints">Restablecer advertencias</string>
<string name="app_settings_reset_hints_summary">Habilita las advertencias que han sido cesadas con anterioridad</string>
<string name="app_settings_reset_hints_success">Todas las advertencias serán mostradas de nuevo</string>
<string name="app_settings_reset_hints_summary">Habilita las advertencias que han sido rechazadas con anterioridad</string>
<string name="app_settings_reset_hints_success">Todas las advertencias se mostrarán nuevamente</string>
<string name="app_settings_security">Seguridad</string>
<string name="app_settings_reset_trusted_certificates">Restablecer certificados de confianza</string>
<string name="app_settings_reset_trusted_certificates_summary">Olvidar todos los certificados aceptados previamente</string>
<plurals name="app_settings_reset_trusted_certificates_success">
<item quantity="one">Retirada la confianza de un certificado</item>
<item quantity="other">Retirada la confianza de %d certificados</item>
</plurals>
<string name="app_settings_distrust_system_certs">Invalidar los certificados del sistema</string>
<string name="app_settings_distrust_system_certs_on">Los CA del sistema y los añadidos por el usuario no serán válidos</string>
<string name="app_settings_distrust_system_certs_off">Los CA del sistema y los añadidos por el usuario serán usados y de confianza (recomendado)</string>
<string name="app_settings_reset_certificates">Reiniciar certificados (in)validados</string>
<string name="app_settings_reset_certificates_summary">Reinicia la validez de todos los certificados particulares</string>
<string name="app_settings_reset_certificates_success">Todos los certificados particulares han sido limpiados</string>
<string name="app_settings_debug">Depuración</string>
<string name="app_settings_log_to_external_storage">Registrar en fichero externo</string>
<string name="app_settings_log_to_external_storage_on">Registro en almacenamiento externo (si está disponible)</string>
@@ -71,8 +74,8 @@
<string name="account_synchronizing_now">Sincronizando...</string>
<string name="account_settings">Ajustes de cuenta</string>
<string name="account_delete">Eliminar cuenta</string>
<string name="account_delete_confirmation_title">¿Seguro que desea eliminar la cuenta?</string>
<string name="account_delete_confirmation_text">Todas las copias locales de sus contactos, calendarios y tareas serán eliminadas.</string>
<string name="account_delete_confirmation_title">¿Seguro que deseas eliminar la cuenta?</string>
<string name="account_delete_confirmation_text">Todas las copias locales de tus contactos, calendarios y tareas serán eliminadas.</string>
<string name="account_refresh_address_book_list">Refrescar contactos</string>
<string name="account_create_new_address_book">Crear nueva lista de contactos</string>
<string name="account_refresh_calendar_list">Refrescar calendario</string>
@@ -80,13 +83,13 @@
<!--PermissionsActivity-->
<string name="permissions_title">Permisos de DAVdroid</string>
<string name="permissions_calendar">Permisos de calendario</string>
<string name="permissions_calendar_details">Para sincronizar eventos CalDAV con sus calendarios locales, DAVdroid necesita acceder a los mismos.</string>
<string name="permissions_calendar_details">Para sincronizar eventos CalDAV con tus calendarios locales, DAVdroid necesita acceder a los mismos.</string>
<string name="permissions_calendar_request">Solicitar permisos sobre calendario</string>
<string name="permissions_contacts">Permisos de contactos</string>
<string name="permissions_contacts_details">Para sincronizar libretas de contactos CadDAV con sus contactos locales, DAVdroid necesita acceder a los mismos.</string>
<string name="permissions_contacts_details">Para sincronizar libretas de contactos CadDAV con tus contactos locales, DAVdroid necesita acceder a los mismos.</string>
<string name="permissions_contacts_request">Solicitar permisos sobre contactos</string>
<string name="permissions_opentasks">Permisos de OpenTasks</string>
<string name="permissions_opentasks_details">Para sincronizar listas de tareas CalDAV con sus listas de tareas locales, DAVdroid necesita acceder a OpenTasks.</string>
<string name="permissions_opentasks_details">Para sincronizar listas de tareas CalDAV con tus listas de tareas locales, DAVdroid necesita acceder a OpenTasks.</string>
<string name="permissions_opentasks_request">Solicitar permisos sobre OpenTasks</string>
<!--AddAccountActivity-->
<string name="login_title">Añadir cuenta</string>
@@ -101,17 +104,17 @@
<string name="login_user_name">Nombre de usuario</string>
<string name="login_user_name_required">Nombre de usuario requerido</string>
<string name="login_base_url">URL base</string>
<string name="login_auth_preemptive">Autenticación preferente (recomendado, pero incompatible con Digest auth)</string>
<string name="login_login">Registrar</string>
<string name="login_back">Volver</string>
<string name="login_create_account">Crear cuenta</string>
<string name="login_account_name">Nombre de cuenta</string>
<string name="login_account_name_info">Use su dirección de correo como nombre de su cuenta puesto que Android usará el nombre de la cuenta como campo de \"organizador\" en los eventos que cree. No puede tener dos cuentas con el mismo nombre.</string>
<string name="login_account_name_info">Usa tu dirección de correo como nombre de cuenta puesto que Android usará el nombre de la cuenta como campo de \"organizador\" en los eventos que cree. No puedes tener dos cuentas con el mismo nombre.</string>
<string name="login_account_contact_group_method">Método de contacto de grupo:</string>
<string name="login_account_name_required">Nombre de cuenta requerido</string>
<string name="login_account_not_created">La cuenta no pudo ser creada</string>
<string name="login_configuration_detection">Detectar configuración</string>
<string name="login_querying_server">Por favor espere, consultando al servidor...</string>
<string name="login_no_caldav_carddav">No se pudo encontrar servicio CalDAV o CardDAV.</string>
<string name="login_querying_server">Por favor espera, consultando al servidor...</string>
<string name="login_no_caldav_carddav">No se pudo encontrar el servicio CalDAV o CardDAV.</string>
<string name="login_view_logs">Ver registros</string>
<!--AccountSettingsActivity-->
<string name="settings_title">Ajustes: %s</string>
@@ -121,9 +124,6 @@
<string name="settings_password">Contraseña</string>
<string name="settings_password_summary">Actualiza la contraseña de acuerdo a tu servidor.</string>
<string name="settings_enter_password">Introduce tu contraseña:</string>
<string name="settings_preemptive">Autenticación preferente</string>
<string name="settings_preemptive_on">Las credenciales se envían en cada petición (recomendado)</string>
<string name="settings_preemptive_off">Las credenciales se envían después de que el servidor las pida</string>
<string name="settings_sync">Sincronización</string>
<string name="settings_sync_interval_contacts">Intervalo de sincronización de contactos</string>
<string name="settings_sync_summary_manually">Solo manualmente</string>
@@ -153,11 +153,24 @@
</string-array>
<string name="settings_sync_wifi_only">Sincronizar sólo sobre WiFi</string>
<string name="settings_sync_wifi_only_on">La sincronización está restringida a conexiones WiFi</string>
<string name="settings_sync_wifi_only_off">Tipo de conexión no tomada en consideración</string>
<string name="settings_sync_wifi_only_off">Tipo de conexión no tenido en cuenta</string>
<string name="settings_sync_wifi_only_ssid">Restricción WiFi SSID</string>
<string name="settings_sync_wifi_only_ssid_on">Sólo se sincronizará sobre %s</string>
<string name="settings_sync_wifi_only_ssid_off">Todas las conexiones WiFi pueden ser usadas</string>
<string name="settings_sync_wifi_only_ssid_message">Introduzca el nombre de una red WiFi (SSID) para restringir la sincronización a esta red, o deje el campo en blanco para usar todas las conexiones WiFi.</string>
<string name="settings_sync_wifi_only_ssid_message">Introduce el nombre de una red WiFi (SSID) para restringir la sincronización a esta red, o deja el campo en blanco para usar todas las conexiones WiFi.</string>
<string name="settings_carddav">CardDAV</string>
<string name="settings_contact_group_method">Método de contacto de grupo</string>
<string-array name="settings_contact_group_method_values">
<item>GROUP_VCARDS</item>
<item>CATEGORIAS</item>
</string-array>
<string-array name="settings_contact_group_method_entries">
<item>Los groups tienen VCards separadas</item>
<item>Los groups tienen una categoría por contacto</item>
</string-array>
<string name="settings_rfc6868_for_vcards">Usar RFC6868 para VCards</string>
<string name="settings_rfc6868_for_vcards_on">Las comillas dobles se pueden usar en los valores de los parámetros</string>
<string name="settings_rfc6868_for_vcards_off">Las comillas dobles no se pueden usar en los valores de los parámetros</string>
<string name="settings_caldav">CalDAV</string>
<string name="settings_sync_time_range_past">Límite de tiempo de eventos pasados</string>
<string name="settings_sync_time_range_past_none">Todos los eventos serán sincronizados</string>
@@ -165,7 +178,7 @@
<item quantity="one">Los eventos anteriores a un día serán ignorados</item>
<item quantity="other">Los eventos anteriores a %d días serán ignorados</item>
</plurals>
<string name="settings_sync_time_range_past_message">Los eventos anteriores a este número de días serán ignorados (puede ser 0). Deje en blanco el campo para sincronizar todos los eventos.</string>
<string name="settings_sync_time_range_past_message">Los eventos anteriores a este número de días serán ignorados (puede ser 0). Deja en blanco el campo para sincronizar todos los eventos.</string>
<string name="settings_manage_calendar_colors">Colores de calendario</string>
<string name="settings_manage_calendar_colors_on">Los colores de los calendarios son administrados por DAVdroid</string>
<string name="settings_manage_calendar_colors_off">Los colores de los calendarios no son establecidos por DAVdroid</string>
@@ -190,7 +203,7 @@
<string name="create_collection_home_set">Establecer localización:</string>
<string name="create_collection_create">Crear</string>
<string name="delete_collection">Eliminar colección</string>
<string name="delete_collection_confirm_title">¿Está seguro/a?</string>
<string name="delete_collection_confirm_title">¿Estás seguro/a?</string>
<string name="delete_collection_confirm_warning">Esta colección (%s) y toda su información será eliminada del servidor.</string>
<string name="delete_collection_deleting_collection">Eliminando colección</string>
<!--ExceptionInfoFragment-->
@@ -208,5 +221,22 @@
<string name="sync_error">Error al %s</string>
<string name="sync_error_http_dav">Error de servidor al %s</string>
<string name="sync_error_local_storage">Error de base de datos al %s</string>
<string-array name="sync_error_phases">
<item>preparando sincronización</item>
<item>buscando capacidades</item>
<item>procesando entradas borradas localmente</item>
<item>preparando entradas creadas/modificadas</item>
<item>cargando entradas creadas/modificadas</item>
<item>comprobando estado de sincronización</item>
<item>enumerando entradas locales</item>
<item>enumerando entradas remotas</item>
<item>comparando entradas locales/remotas</item>
<item>descargando entradas remotas</item>
<item>post-procesando</item>
<item>guardando estado de sincronización</item>
</string-array>
<string name="sync_error_unauthorized">Nombre de usuario/contraseña erróneo</string>
<!--cert4android-->
<string name="certificate_notification_connection_security">DAVdroid: Seguridad de conexión</string>
<string name="trust_certificate_unknown_certificate_found">DAVdroid ha encontrado un certificado desconocido. ¿Quieres que sea válido?</string>
</resources>

View File

@@ -7,6 +7,9 @@
<string name="please_wait">SVP attendez ...</string>
<string name="send">Envoyer</string>
<!--startup dialogs-->
<string name="startup_battery_optimization">Optimisation de la batterie</string>
<string name="startup_battery_optimization_message">Android peut désactiver/réduire la synchronisation de DAVdroid après quelques jours. Pour éviter cela, désactivez l\'optimisation de la batterie.</string>
<string name="startup_battery_optimization_disable">Désactivez pour DAVdroid</string>
<string name="startup_dont_show_again">Ne plus afficher</string>
<string name="startup_development_version">Pré-version de DAVdroid</string>
<string name="startup_development_version_message">Il s\'agit d\'une version de développement de DAVdroid. Il se peut que les choses ne fonctionnent pas comme prévu. Sil vous plaît faites-nous un retour pour améliorer DAVdroid.</string>
@@ -53,12 +56,8 @@
<string name="app_settings_reset_hints_summary">Réactiver les astuces qui ont été vu précédemment</string>
<string name="app_settings_reset_hints_success">Toutes les astuces seront affichés à nouveau</string>
<string name="app_settings_security">Sécurité</string>
<string name="app_settings_reset_trusted_certificates">Réinitialiser les certificats de confiance</string>
<string name="app_settings_reset_trusted_certificates_summary">Oublier tous les certificats qui ont été acceptés précédemment</string>
<plurals name="app_settings_reset_trusted_certificates_success">
<item quantity="one">Un certificat douteux</item>
<item quantity="other">%d certificats douteux</item>
</plurals>
<string name="app_settings_reset_certificates_summary">Réinitialiser la confiance de tous les certificats personnalisés</string>
<string name="app_settings_reset_certificates_success">Tous les certificats personnalisés ont été effacés</string>
<string name="app_settings_debug">Débogage</string>
<string name="app_settings_log_to_external_storage">Journaliser dans un fichier externe</string>
<string name="app_settings_log_to_external_storage_on">Journaliser sur le stockage externe (si disponible)</string>
@@ -100,7 +99,6 @@
<string name="login_user_name">Nom d\'utilisateur</string>
<string name="login_user_name_required">Nom d\'utilisateur requis</string>
<string name="login_base_url">URL de base</string>
<string name="login_auth_preemptive">Authentification préventive (recommandé, mais incompatible avec l\'authentification Digest)</string>
<string name="login_login">Se connecter</string>
<string name="login_back">Retour</string>
<string name="login_create_account">Créer un compte</string>
@@ -120,9 +118,6 @@
<string name="settings_password">Mot de passe</string>
<string name="settings_password_summary">Mettre à jour le mot de passe </string>
<string name="settings_enter_password">Saisissez votre mot de passe :</string>
<string name="settings_preemptive">Authentification préventive</string>
<string name="settings_preemptive_on">Le nom d\'utilisateur et le mot de passe sont envoyés avec chaque requête (recommandé)</string>
<string name="settings_preemptive_off">Le nom d\'utilisateur et le mot de passe sont envoyés à la demande du serveur.</string>
<string name="settings_sync">Synchronisation</string>
<string name="settings_sync_interval_contacts">Interval de synchronisation des carnets d\'adresses</string>
<string name="settings_sync_summary_manually">Manuellement</string>
@@ -215,5 +210,21 @@
<string name="sync_error">Erreur durant %s</string>
<string name="sync_error_http_dav">Erreur de serveur durant %s</string>
<string name="sync_error_local_storage">Erreur de base de donnée durant %s</string>
<string-array name="sync_error_phases">
<item>prépare la synchronisation</item>
<item>demande les autorisations</item>
<item>procède à la suppression des entrées locales</item>
<item>prépare les entrées créées/modifiées</item>
<item>envoi les entrées créées/modifiées</item>
<item>vérifie l\'état de la synchronisation</item>
<item>liste les entrées locales</item>
<item>liste les entrées distantes</item>
<item>compare les entrées locales/distantes</item>
<item>télécharge les entrées distantes</item>
<item>post-traitement</item>
<item>enregistre l\'état de la synchronisation</item>
</string-array>
<string name="sync_error_unauthorized">Nom d\'utilisateur ou mot de passe erroné</string>
<!--cert4android-->
<string name="trust_certificate_unknown_certificate_found">DAVdroid a rencontré un certificat inconnu. Voulez-vous lui faire confiance?</string>
</resources>

View File

@@ -7,6 +7,9 @@
<string name="please_wait">Kérjük, várjon ...</string>
<string name="send">Küldés</string>
<!--startup dialogs-->
<string name="startup_battery_optimization">Akkumulátoroptimalizálás </string>
<string name="startup_battery_optimization_message">Az operációs rendszer a DAVdroid szinkronizálást pár nap után leállíthatja vagy visszafoghatja. Ennek elkerülésére kapcsolja ki az akkumulátoroptimalizálást.</string>
<string name="startup_battery_optimization_disable">Kikapcsolás a DAVdroid kapcsán</string>
<string name="startup_dont_show_again">Ne jelenjen meg többet</string>
<string name="startup_development_version">DAVdroid előzetes kiadás</string>
<string name="startup_development_version_message">Ez a DAVdroid egy fejlesztői verziója. Elképzelhető, hogy nem minden működik úgy, ahogyan kellene. Ha így lenne, kérjük küldjön a tapasztaltakról visszajelzést.</string>
@@ -54,12 +57,12 @@
<string name="app_settings_reset_hints_summary">Újra jelenjen meg az összes tipp</string>
<string name="app_settings_reset_hints_success">Az összes tipp újra meg fog jelenni</string>
<string name="app_settings_security">Biztonság</string>
<string name="app_settings_reset_trusted_certificates">A tanúsítványtár visszaállítása</string>
<string name="app_settings_reset_trusted_certificates_summary">Az összes korábban megbízhatónak kiválasztott tanúsítvány törlése</string>
<plurals name="app_settings_reset_trusted_certificates_success">
<item quantity="one">Egy tanúsítvány megbízhatósága törölve</item>
<item quantity="other">%d tanúsítvány megbízhatósága törölve</item>
</plurals>
<string name="app_settings_distrust_system_certs">A rendszertanúsítványok elfogadása</string>
<string name="app_settings_distrust_system_certs_on">A rendszer által kezelt, előre vagy felhasználó által telepített tanúsítványok figyelmen kívül lesznek hagyva</string>
<string name="app_settings_distrust_system_certs_off">A rendszer által kezelt, előre vagy felhasználó által telepített tanúsítványok megbízhatóak (javasolt)</string>
<string name="app_settings_reset_certificates">A tanúsítványok megbízhatóságának törlésére</string>
<string name="app_settings_reset_certificates_summary">A tanúsítványok megbízhatóságával kapcsolatos beállítások törlésére</string>
<string name="app_settings_reset_certificates_success">A tanúsítványok megbízhatóságával kapcsolatos beállítások törölve</string>
<string name="app_settings_debug">Hibakeresés</string>
<string name="app_settings_log_to_external_storage">Naplózás fájlba</string>
<string name="app_settings_log_to_external_storage_on">Naplózás külső tárhelyre (ha elérhető)</string>
@@ -101,7 +104,6 @@
<string name="login_user_name">Felhasználónév</string>
<string name="login_user_name_required">A felhasználónév megadása feltétlenül szükséges</string>
<string name="login_base_url">URL-törzs</string>
<string name="login_auth_preemptive">Preemptív authentikáció (ajánlott, de Digest authentikációval nem működik)</string>
<string name="login_login">Bejelentkezés</string>
<string name="login_back">Vissza</string>
<string name="login_create_account">Fiók létrehozása</string>
@@ -122,9 +124,6 @@
<string name="settings_password">Jelszó</string>
<string name="settings_password_summary">Adja meg a szerveren érvényes új jelszót.</string>
<string name="settings_enter_password">Adja meg a jelszót:</string>
<string name="settings_preemptive">Preemptív authentikáció</string>
<string name="settings_preemptive_on">A hitelesítő adatok elküldése minden kérésnél (ajánlott)</string>
<string name="settings_preemptive_off">A hitelesítő adatok elküldése, csak ha a szerver azt igényli</string>
<string name="settings_sync">Szinkronizálás</string>
<string name="settings_sync_interval_contacts">Névjegyszinkronizálás sűrűsége</string>
<string name="settings_sync_summary_manually">Manuális</string>
@@ -161,6 +160,10 @@
<string name="settings_sync_wifi_only_ssid_message">Adja meg a WIFI hálózat nevét (SSID) a szinkronizálás egy hálózatra való korlátozához, vagy hagyja üresen, ha nem akar ilyen szűkítést.</string>
<string name="settings_carddav">CardDAV</string>
<string name="settings_contact_group_method">A csoportok kezelésének módja</string>
<string-array name="settings_contact_group_method_values">
<item>GROUP_VCARDS</item>
<item>CATEGORIES</item>
</string-array>
<string-array name="settings_contact_group_method_entries">
<item>Minden csoport egy különálló VCard</item>
<item>A csoportok a kapcsolatonkéni kategóriák</item>
@@ -233,4 +236,7 @@
<item>szinkronizációs állapot mentése</item>
</string-array>
<string name="sync_error_unauthorized">A felhasználónév vagy jelszó hibás</string>
<!--cert4android-->
<string name="certificate_notification_connection_security">DAVdroid: kapcsolatbiztonság</string>
<string name="trust_certificate_unknown_certificate_found">Egy eddig ismeretlen tanúsítvány érkezett. Megbízhatónak kívánja elfogadni?</string>
</resources>

View File

@@ -81,4 +81,5 @@
<string name="exception_show_details">Mostra dettagli</string>
<!--sync errors and DebugInfoActivity-->
<string name="sync_error_permissions">Permessi DAVdroid</string>
<!--cert4android-->
</resources>

View File

@@ -7,6 +7,9 @@
<string name="please_wait">しばらくお待ちください …</string>
<string name="send">送信</string>
<!--startup dialogs-->
<string name="startup_battery_optimization">バッテリー最適化</string>
<string name="startup_battery_optimization_message">Android は数日後に DAVdroid の同期を無効にする/減らすことがあります。これを防止するには、バッテリー最適化をオフにしてください。</string>
<string name="startup_battery_optimization_disable">DAVdroid 用にオフにする</string>
<string name="startup_dont_show_again">次回から表示しない</string>
<string name="startup_development_version">DAVdroid プレビュー リリース</string>
<string name="startup_development_version_message">これは DAVdroid の開発版です。期待した通りに動作しない可能性があることにご注意ください。私たちが DAVdroid を改善するために、建設的なフィードバックをお願いします。</string>
@@ -54,11 +57,12 @@
<string name="app_settings_reset_hints_summary">以前非表示にしたヒントを、再度有効にします</string>
<string name="app_settings_reset_hints_success">すべてのヒントが再度表示されます</string>
<string name="app_settings_security">セキュリティ</string>
<string name="app_settings_reset_trusted_certificates">信頼済証明書をリセット</string>
<string name="app_settings_reset_trusted_certificates_summary">以前承認されたすべての証明書を忘れます</string>
<plurals name="app_settings_reset_trusted_certificates_success">
<item quantity="other">%d 証明書の信頼を解除しました</item>
</plurals>
<string name="app_settings_distrust_system_certs">システム証明書の信頼を解除</string>
<string name="app_settings_distrust_system_certs_on">システムとユーザーが追加したCAを信頼しない</string>
<string name="app_settings_distrust_system_certs_off">システムとユーザーが追加したCAを信頼する (推奨)</string>
<string name="app_settings_reset_certificates">(未)信頼済証明書をリセット</string>
<string name="app_settings_reset_certificates_summary">すべてのカスタム証明書の信頼をリセット</string>
<string name="app_settings_reset_certificates_success">すべてのカスタム証明書をクリアしました</string>
<string name="app_settings_debug">デバッグ</string>
<string name="app_settings_log_to_external_storage">外部ファイルにログ出力</string>
<string name="app_settings_log_to_external_storage_on">(可能な場合) 外部ストレージにログ出力します</string>
@@ -100,7 +104,6 @@
<string name="login_user_name">ユーザー名</string>
<string name="login_user_name_required">ユーザー名が必要です</string>
<string name="login_base_url">ベース URL</string>
<string name="login_auth_preemptive">プリエンプティブ認証 (推奨ですが、ダイジェスト認証と互換性がありません)</string>
<string name="login_login">ログイン</string>
<string name="login_back">戻る</string>
<string name="login_create_account">アカウントを作成</string>
@@ -121,9 +124,6 @@
<string name="settings_password">パスワード</string>
<string name="settings_password_summary">ご利用のサーバーに従ってパスワードを更新します。</string>
<string name="settings_enter_password">パスワードを入力:</string>
<string name="settings_preemptive">プリエンプティブ認証</string>
<string name="settings_preemptive_on">すべてのリクエストで資格情報を送信します (推奨)</string>
<string name="settings_preemptive_off">サーバーが要求した後、資格情報を送信します</string>
<string name="settings_sync">同期</string>
<string name="settings_sync_interval_contacts">連絡先同期間隔</string>
<string name="settings_sync_summary_manually">手動のみ</string>
@@ -235,4 +235,7 @@
<item>同期の状態を保存中</item>
</string-array>
<string name="sync_error_unauthorized">ユーザー名/パスワードが間違っています</string>
<!--cert4android-->
<string name="certificate_notification_connection_security">DAVdroid: 接続セキュリティ</string>
<string name="trust_certificate_unknown_certificate_found">DAVdroidは、未知の証明書を検出しました。それを信頼しますか?</string>
</resources>

View File

@@ -54,12 +54,6 @@
<string name="app_settings_reset_hints_summary">Hints die al gezien zijn opnieuw weergeven</string>
<string name="app_settings_reset_hints_success">Alle hints worden opnieuw weergegeven</string>
<string name="app_settings_security">Beveiliging</string>
<string name="app_settings_reset_trusted_certificates">Vertrouwde certificaten resetten</string>
<string name="app_settings_reset_trusted_certificates_summary">Vergeet alle eerder geaccepteerde certificaten</string>
<plurals name="app_settings_reset_trusted_certificates_success">
<item quantity="one">Onbetrouwbaar certificaat</item>
<item quantity="other">Onbetrouwbaar %d certificaten</item>
</plurals>
<string name="app_settings_debug">Debuggen</string>
<string name="app_settings_log_to_external_storage">Log naar extern bestand</string>
<string name="app_settings_log_to_external_storage_on">Loggen naar externe opslag (wanneer beschikbaar)</string>
@@ -101,12 +95,12 @@
<string name="login_user_name">Gebruikersnaam</string>
<string name="login_user_name_required">Gebruikersnaam vereist</string>
<string name="login_base_url">Basis URL</string>
<string name="login_auth_preemptive">Preëmptieve authenticatie (aanbevolen, maar werkt niet met Digest-auth)</string>
<string name="login_login">Login</string>
<string name="login_back">Terug</string>
<string name="login_create_account">Maak een account</string>
<string name="login_account_name">Accountnaam</string>
<string name="login_account_name_info">Gebruik je email adres als account naam want Android zal je account naam gebruiken als ORGANIZER veld voor gemaakte afspraken. Je kunt geen 2 accounts met dezelfde naam hebben,</string>
<string name="login_account_contact_group_method">Contact groep methode:</string>
<string name="login_account_name_required">Accountnaam vereist</string>
<string name="login_account_not_created">Account kon niet gemaakt worden.</string>
<string name="login_configuration_detection">Configuratie detectie</string>
@@ -121,9 +115,6 @@
<string name="settings_password">Wachtwoord</string>
<string name="settings_password_summary">Gebruik het zelfde wachtwoord als op de server.</string>
<string name="settings_enter_password">Wachtwoord invoeren:</string>
<string name="settings_preemptive">Preëmptieve authenticatie</string>
<string name="settings_preemptive_on">Credentials worden met elk verzoek verzonden (aanbevolen)</string>
<string name="settings_preemptive_off">Credentials worden alleen op aanvraag verzonden</string>
<string name="settings_sync">Synchronisatie</string>
<string name="settings_sync_interval_contacts">Contacten verversen</string>
<string name="settings_sync_summary_manually">Alleen handmatig</string>
@@ -158,6 +149,19 @@
<string name="settings_sync_wifi_only_ssid_on">Zal alleen synchroniseren over %s</string>
<string name="settings_sync_wifi_only_ssid_off">Alle WiFI verbindingen mogen worden gebruikt</string>
<string name="settings_sync_wifi_only_ssid_message">Type de naam van het WiFi netwerk (SSID) om synchronisatie tot dit netwerk te beperken. Leeg laten voor sync over alle netwerken.</string>
<string name="settings_carddav">CardDAV</string>
<string name="settings_contact_group_method">Contact groep methode</string>
<string-array name="settings_contact_group_method_values">
<item>GROUP_VCARDS</item>
<item>CATEGORIES</item>
</string-array>
<string-array name="settings_contact_group_method_entries">
<item>Groepen zijn apparte VCards</item>
<item>Groepen zijn per-contact categories</item>
</string-array>
<string name="settings_rfc6868_for_vcards">Gebruik RFC6868 voor VCards</string>
<string name="settings_rfc6868_for_vcards_on">Aanhalingstekens kunnen worden gebruikt voor parameter waardes</string>
<string name="settings_rfc6868_for_vcards_off">Aanhalingstekens kunnen niet worden gebruikt voor parameter waardes</string>
<string name="settings_caldav">CalDAV</string>
<string name="settings_sync_time_range_past">Tijdslimiet verleden afspraken</string>
<string name="settings_sync_time_range_past_none">Alle afspraken worden gesynchronizeerd</string>
@@ -208,5 +212,20 @@
<string name="sync_error">Fout tijdens %s</string>
<string name="sync_error_http_dav">Serverfout tijdens %s</string>
<string name="sync_error_local_storage">Database fout tijdens %s</string>
<string-array name="sync_error_phases">
<item>synchronisatie voorbereiden</item>
<item>querying mogelijkheden</item>
<item>verwerken van lokaal verwijderde data</item>
<item>voorberteiding maken/wijzigen data</item>
<item>uploaden maken/bewerken data</item>
<item>controleren syngronisatie voortgang</item>
<item>lijst lokale data</item>
<item>lijst remote data</item>
<item>vergelijken lokale/remote data</item>
<item>downloaden remote data</item>
<item>nabewerking</item>
<item>opslaan sync voortgang</item>
</string-array>
<string name="sync_error_unauthorized">Gebruikersnaam/wachtwoord onjuist</string>
<!--cert4android-->
</resources>

View File

@@ -7,13 +7,19 @@
<string name="please_wait">Proszę czekać</string>
<string name="send">Wyślij</string>
<!--startup dialogs-->
<string name="startup_battery_optimization">Optymalizacja baterii</string>
<string name="startup_battery_optimization_message">Android może wyłączyć/zmniejszyć synchronizacje DAVdroid po kilku dniach. Aby temu zapobiec należy wyłączyć optymalizację baterii.</string>
<string name="startup_battery_optimization_disable">Wyłącz dla DAVdroid</string>
<string name="startup_dont_show_again">Nie pokazuj ponownie</string>
<string name="startup_development_version">DAVdroid Preview Release</string>
<string name="startup_development_version_message">Jest to wersja rozwojowa DAVdroid. Należy pamiętać, że rzeczy mogą nie działać zgodnie z oczekiwaniami. Prosimy o konstruktywny informacje zwrotne, aby ulepszyć DAVdroid.</string>
<string name="startup_development_version_give_feedback">Przekaż opinię</string>
<string name="startup_donate">Informacje Open-Source</string>
<string name="startup_donate_message">Jesteśmy szczęśliwi, że używasz DAVdroid, który jest oprogramowaniem open-source (GPLv3). Ponieważ rozwijanie DAVdroid jest ciężką pracą i zajęło nam tysiące godzin pracy, prosimy o rozważenie darowizny.</string>
<string name="startup_donate_now">Pokaż stronę darowizny</string>
<string name="startup_donate_later">Może później</string>
<string name="startup_google_play_accounts_removed">Informacje o błędzie DRM Sklepu Play</string>
<string name="startup_google_play_accounts_removed_message">Pod pewnymi warunkami, DRM Sklepu Play może powodować, że wszystkie konta DAVdroid mogą zostać usunięte po uruchomieniu lub po uaktualnieniu DAVdroid. Jeśli jesteś dotknięty tym problemem (i tylko wtedy) należy zainstalować \"DAVdroid JB Obejście\" ze Sklepu Play.</string>
<string name="startup_google_play_accounts_removed_more_info">Więcej informacji</string>
<string name="startup_opentasks_not_installed">OpenTasks nie jest zainstalowany</string>
<string name="startup_opentasks_not_installed_message">Aplikacja Open Tasks nie jest dostępna, więc DAVdroid nie będzie mógł synchronizować listy zadań. </string>
@@ -21,6 +27,7 @@
<string name="startup_opentasks_not_installed_install">Zainstaluj OpenTasks</string>
<!--AboutActivity-->
<string name="about_license_terms">Warunki licencji</string>
<string name="about_license_info_no_warranty">Ten program jest ABSOLUTNIE BEZ GWARANCJI. To jest wolne oprogramowanie i mile widziane jest dalsze rozpowszechnianie go pod pewnymi warunkami.</string>
<!--global settings-->
<string name="logging_davdroid_file_logging">Plik logów DAVdroid</string>
<string name="logging_to_external_storage">Logowanie do zewnątrznej pamięci: %s</string>
@@ -33,31 +40,42 @@
<string name="navigation_drawer_subtitle">Adapter synchronizacji CalDAV/CardDAV</string>
<string name="navigation_drawer_about">O DAVdroid / Licencja</string>
<string name="navigation_drawer_settings">Ustawienia</string>
<string name="navigation_drawer_news_updates">Nowości &amp; aktualizacje
</string>
<string name="navigation_drawer_news_updates">Nowości &amp; aktualizacje</string>
<string name="navigation_drawer_external_links">Zewnętrzne odnośniki</string>
<string name="navigation_drawer_website">Strona WWW</string>
<string name="navigation_drawer_faq">FQA</string>
<string name="navigation_drawer_forums">Społeczność</string>
<string name="navigation_drawer_donate">Dotacja</string>
<string name="account_list_empty">Witamy w DAVdroid!\n\nMożesz teraz dodać konto CalDAV/CardDAV.</string>
<!--DavService-->
<string name="dav_service_refresh_failed">Wykrycie serwisu nie powiodło się</string>
<string name="dav_service_refresh_couldnt_refresh">Nie można odświeżyć listy kolekcji</string>
<!--AppSettingsActivity-->
<string name="app_settings">Ustawienia</string>
<string name="app_settings_user_interface">
Interfejs użytkownika</string>
<string name="app_settings_user_interface">Interfejs użytkownika</string>
<string name="app_settings_reset_hints">Zresetuj podpowiedzi</string>
<string name="app_settings_reset_hints_summary">Ponownie włącz wskazówki, które zostały usunięte wcześniej</string>
<string name="app_settings_reset_hints_success">Wszystkie wskazówki pojawią się ponownie</string>
<string name="app_settings_security">Bezpieczeństwo</string>
<string name="app_settings_distrust_system_certs">Usuń certyfikaty systemowe</string>
<string name="app_settings_distrust_system_certs_on">CA systemowe i użytkownika nie zostaną dodane</string>
<string name="app_settings_distrust_system_certs_off">CA systemowe i użytkownika zostaną dodane (zalecane)</string>
<string name="app_settings_reset_certificates">Zresetuj (nie)zaufane certyfikaty</string>
<string name="app_settings_reset_certificates_summary">Zresetuj wszystkie niestandardowe certyfikaty.</string>
<string name="app_settings_reset_certificates_success">Wszystkie niestandardowe certyfikaty zostały wyczyszczone</string>
<string name="app_settings_debug">Debugowanie</string>
<string name="app_settings_log_to_external_storage">Loguj to zewnętrznego pliku</string>
<string name="app_settings_log_to_external_storage_on">Logowanie do zewnętrznej pamięci (jeśli jest dostępna)</string>
<string name="app_settings_log_to_external_storage_off">Logowanie do zewnętrznego pliku jest niedostępne</string>
<string name="app_settings_show_debug_info">Pokaż informacje do debug\'owania</string>
<string name="app_settings_show_debug_info_details">Przeglądaj/udostępnij oprogramowanie i szczegóły konfiguracji </string>
<!--AccountActivity-->
<string name="account_synchronize_now">Synchronizuj teraz</string>
<string name="account_synchronizing_now">Synchronizcja w toku</string>
<string name="account_settings">Ustawienia konta</string>
<string name="account_delete">Usuń konto</string>
<string name="account_delete_confirmation_title">Naprawdę chcesz usunąć konto?</string>
<string name="account_delete_confirmation_text">Wszystkie lokalne kopie książek adresowych, kalendarzy i list zadań zostaną usunięte.</string>
<string name="account_refresh_address_book_list">Odśwież list książek adresowych</string>
<string name="account_create_new_address_book">Stwórz nową książkę adresową</string>
<string name="account_refresh_calendar_list">Odśwież liste kalendarzy</string>
@@ -65,10 +83,13 @@ Interfejs użytkownika</string>
<!--PermissionsActivity-->
<string name="permissions_title">Uprawnienia DAVdroid</string>
<string name="permissions_calendar">Uprawnienia kalendarza</string>
<string name="permissions_calendar_details">Aby synchronizować wydarzenia CalDav z lokalnymi kalendarzami, DAVdroid potrzebuje dostępu do twoich kalendarzy.</string>
<string name="permissions_calendar_request">Zezwól na uprawnienia kalendarza</string>
<string name="permissions_contacts">Uprawnienia kontaktów</string>
<string name="permissions_contacts_details">Aby synchronizować książki adresowe CardDAV z lokalnymi kontaktami, DAVdroid potrzebuje dostępu do twoich kontaktów.</string>
<string name="permissions_contacts_request">Zezwól na uprawnienia kontaktów</string>
<string name="permissions_opentasks">Uprawnienia OpenTasks</string>
<string name="permissions_opentasks_details">Aby synchronizować zadania CalDav z lokalnymi listami zadań, DAVdroid potrzebuje dostępu do OpenTasks.</string>
<string name="permissions_opentasks_request">Zezwól na uprawnienia OpenTasks</string>
<!--AddAccountActivity-->
<string name="login_title">Dodaj konto</string>
@@ -78,20 +99,22 @@ Interfejs użytkownika</string>
<string name="login_password">Hasło</string>
<string name="login_password_required">Wymagane hasło</string>
<string name="login_type_url">Logowanie za pomocą adresu URL i nazwy użytkownika</string>
<string name="login_url_must_be_http_or_https">URL musi zaczynać się z http(s)://</string>
<string name="login_url_host_name_required">Wymagana nazwa hosta</string>
<string name="login_user_name">Nazwa użytkownika</string>
<string name="login_user_name_required">Wymagana nazwa użtkonika</string>
<string name="login_base_url">Podstawowy URL</string>
<string name="login_auth_preemptive">Autoryzacja prewencyjna (zalecana, ale niezgodna z autoryzacją Digest)</string>
<string name="login_login">Zaloguj</string>
<string name="login_back">Wróć</string>
<string name="login_create_account">Stwórz konto</string>
<string name="login_account_name">Nazwa konta</string>
<string name="login_account_name_info">Użyj swojego adresu e-mail jako nazwy konta, ponieważ Android będzie używał nazwy konta jako pola ORGANIZATOR dla wydarzeń, które stworzysz. Nie możesz posiadać dwóch kont o takiej samej nazwie.</string>
<string name="login_account_contact_group_method">Metoda grupowania kontaktów:</string>
<string name="login_account_name_required">Wymagana nazwa konta</string>
<string name="login_account_not_created">Konto nie mogło zostać stworzone</string>
<string name="login_configuration_detection">Wykrywanie konfiguracji</string>
<string name="login_querying_server">Proszę czekać, odpytywanie serwera...</string>
<string name="login_no_caldav_carddav">Nie można znaleźć usługi CalDAV lub CardDAV.</string>
<string name="login_view_logs">Pokaż logi</string>
<!--AccountSettingsActivity-->
<string name="settings_title">Ustawienia: %s</string>
@@ -101,9 +124,6 @@ Interfejs użytkownika</string>
<string name="settings_password">Hasło</string>
<string name="settings_password_summary">Zaktualizuj hasło zgodnie z serwerem.</string>
<string name="settings_enter_password">Wpisz hasło:</string>
<string name="settings_preemptive">Autoryzacja prewencyjna</string>
<string name="settings_preemptive_on">Listy uwierzytelniające są wysyłane przy każdym zapytaniu (zalecane)</string>
<string name="settings_preemptive_off">Listy uwierzytelniające są wysyłane po zapytaniu serwera o nie</string>
<string name="settings_sync">Synchronizacja</string>
<string name="settings_sync_interval_contacts">Okres synchronizacji kontktów</string>
<string name="settings_sync_summary_manually">Tylko ręcznie</string>
@@ -131,6 +151,13 @@ Interfejs użytkownika</string>
<item>Co 4 godziny</item>
<item>Raz dziennie</item>
</string-array>
<string name="settings_sync_wifi_only">Synchronizuj tylko przez WiFi</string>
<string name="settings_sync_wifi_only_on">Synchronizacja jest ograniczony do połączeń WiFi</string>
<string name="settings_sync_wifi_only_off">Rodzaj połączenia nie jest brany pod uwagę</string>
<string name="settings_sync_wifi_only_ssid">Organicznie WiFi SSID</string>
<string name="settings_sync_wifi_only_ssid_on">Będzie synchronizować tylko przez %s.</string>
<string name="settings_sync_wifi_only_ssid_off">Wszystkie połączenia WiFi mogą zostać wykorzystane</string>
<string name="settings_sync_wifi_only_ssid_message">Wprowadź nazwę sieci WiFi (SSID), aby ograniczyć synchronizację do tej sieci lub pozostaw puste dla wszystkich połączeń WiFi.</string>
<string name="settings_carddav">CardDAV</string>
<string name="settings_contact_group_method">Metoda grupowania kontaktów</string>
<string-array name="settings_contact_group_method_values">
@@ -138,11 +165,22 @@ Interfejs użytkownika</string>
<item>CATEGORIES</item>
</string-array>
<string name="settings_rfc6868_for_vcards">Użyj RFC6868 dla VCards</string>
<string name="settings_rfc6868_for_vcards_on">Podwójne apostrofy można stosować w wartościach parametrów</string>
<string name="settings_rfc6868_for_vcards_off">Podwójne apostrofy nie można stosować w wartościach parametrów</string>
<string name="settings_caldav">CalDAV</string>
<string name="settings_sync_time_range_past">Limit czasowy przeszłych wydarzeń</string>
<string name="settings_sync_time_range_past_none">Wszystkie wydarzenia zostaną synchronizowane</string>
<plurals name="settings_sync_time_range_past_days">
<item quantity="one">Wydarzenia starsze niż jeden dzień zostaną zignorowane.</item>
<item quantity="few">Wydarzenia starsze niż %d dni zostaną zignorowane.</item>
<item quantity="other">Wydarzenia starsze niż %d dni zostaną zignorowane.</item>
</plurals>
<string name="settings_sync_time_range_past_message">Wydarzenia, które są starsze niż podana liczba dni zostaną zignorowane (może być 0). Zostaw puste, aby synchronizować wszystkie wydarzenia.</string>
<string name="settings_manage_calendar_colors">Zarządzaj kolorami kalendarza</string>
<string name="settings_manage_calendar_colors_on">Kolory kalendarza są zarządzane przez DAVdroid</string>
<string name="settings_manage_calendar_colors_off">Kolory kalendarze nie są ustawiane przez DAVdroid</string>
<string name="settings_version_update">Aktualizacji wersji DAVdroid</string>
<string name="settings_version_update_settings_updated">Ustawienia wewnętrzne zostały zaktualizowane.</string>
<string name="settings_version_update_install_hint">Problemy? Odinstaluj DAVdroid i zainstaluj ponownie.</string>
<!--collection management-->
<string name="create_addressbook">Stwórz książkę adresową</string>
@@ -180,5 +218,22 @@ Interfejs użytkownika</string>
<string name="sync_error">Błąd podczas %s</string>
<string name="sync_error_http_dav">Błąd servera podczas %s</string>
<string name="sync_error_local_storage">Bład bazy danych podczas %s</string>
<string-array name="sync_error_phases">
<item>przygotowanie synchronizacji</item>
<item>odpytywanie możliwości</item>
<item>przetwarzanie lokalnie usuniętych wpisów</item>
<item>przygotowanie stworzonych/zmodyfikowanych wpisów</item>
<item>wysyłanie stworzonych/zmodyfikowanych wpisów</item>
<item>sprawdzanie stanu synchronizacji</item>
<item>listowanie lokalnych wpisów</item>
<item>listowanie zdalnych wpisów</item>
<item>porównywanie lokalnych/zdalnych wpisów</item>
<item>pobieranie zdalnych wpisów</item>
<item>przetwarzanie końcowe</item>
<item>zapisywanie stanu synchronizacji</item>
</string-array>
<string name="sync_error_unauthorized">Błędna nazwa użytkownika lub hasło</string>
<!--cert4android-->
<string name="certificate_notification_connection_security">DAVdroid: Bezpieczeństwo połączenia</string>
<string name="trust_certificate_unknown_certificate_found">DAVdroid napotkał nieznany certyfikat. Czy chcesz go dodać?</string>
</resources>

View File

@@ -7,6 +7,9 @@
<string name="please_wait">Por favor, aguarde...</string>
<string name="send">Enviar</string>
<!--startup dialogs-->
<string name="startup_battery_optimization">Otimização da bateria</string>
<string name="startup_battery_optimization_message">O Android pode desativar/reduzir a sincronização do DAVdroid depois de alguns dias. Para evitar isso, desligue a otimização da bateria.</string>
<string name="startup_battery_optimization_disable">Desligar para o DAVdroid</string>
<string name="startup_dont_show_again">Não mostrar novamente</string>
<string name="startup_development_version">Versão prévia do DAVdroid</string>
<string name="startup_development_version_message">Esta é uma versão de desenvolvimento do DAVdroid. Lembre-se de que as coisas podem não funcionar como esperado. Por favor, envie sugestões e comentários construtivos para melhorar o DAVdroid.</string>
@@ -54,18 +57,18 @@
<string name="app_settings_reset_hints_summary">Restaura as sugestões que foram descartadas anteriormente</string>
<string name="app_settings_reset_hints_success">Todas as sugestões serão exibidas novamente</string>
<string name="app_settings_security">Segurança</string>
<string name="app_settings_reset_trusted_certificates">Restaurar certificados confiáveis</string>
<string name="app_settings_reset_trusted_certificates_summary">Esquece de todos os certificados que foram aceitos anteriormente</string>
<plurals name="app_settings_reset_trusted_certificates_success">
<item quantity="one">Retirada a confiança de um certificado</item>
<item quantity="other">Retirada a confiança de %d certificados</item>
</plurals>
<string name="app_settings_distrust_system_certs">Desconfiar dos certificados de sistema</string>
<string name="app_settings_distrust_system_certs_on">ACs adicionadas pelo usuário e pelo sistema não serão confiáveis</string>
<string name="app_settings_distrust_system_certs_off">ACs adicionadas pelo usuário e pelo sistema serão confiáveis (recomendado)</string>
<string name="app_settings_reset_certificates">Restaurar certificados não-confiáveis</string>
<string name="app_settings_reset_certificates_summary">Restaura a confiança de todos os certificados personalizados</string>
<string name="app_settings_reset_certificates_success">Todos os certificados personalizados foram restaurados</string>
<string name="app_settings_debug">Depuração</string>
<string name="app_settings_log_to_external_storage">Registrar em arquivo externo</string>
<string name="app_settings_log_to_external_storage_on">Registrando no armazenamento externo (se disponível)</string>
<string name="app_settings_log_to_external_storage_off">O registro em arquivo externo está desativado</string>
<string name="app_settings_show_debug_info">Mostrar informações de depuração</string>
<string name="app_settings_show_debug_info_details">Exibir/compartilhar o software e os detalhes da configuração</string>
<string name="app_settings_show_debug_info_details">Exibe/compartilha o software e os detalhes da configuração</string>
<!--AccountActivity-->
<string name="account_synchronize_now">Sincronizar agora</string>
<string name="account_synchronizing_now">Sincronizando</string>
@@ -101,7 +104,6 @@
<string name="login_user_name">Usuário</string>
<string name="login_user_name_required">É necessário um nome de usuário</string>
<string name="login_base_url">URL base</string>
<string name="login_auth_preemptive">Autenticação preferencial (recomendado, mas incompatível com autenticação Digest)</string>
<string name="login_login">Autenticar</string>
<string name="login_back">Voltar</string>
<string name="login_create_account">Criar conta</string>
@@ -122,9 +124,6 @@
<string name="settings_password">Senha</string>
<string name="settings_password_summary">Atualize a senha de acordo com seu servidor</string>
<string name="settings_enter_password">Digite sua senha:</string>
<string name="settings_preemptive">Autenticação preferencial</string>
<string name="settings_preemptive_on">Credenciais enviadas a cada requisição (recomendado)</string>
<string name="settings_preemptive_off">Credenciais enviadas após a requisição do servidor</string>
<string name="settings_sync">Sincronização</string>
<string name="settings_sync_interval_contacts">Intervalo sinc. de contatos</string>
<string name="settings_sync_summary_manually">Apenas manualmente</string>
@@ -237,4 +236,7 @@
<item>salvando o estado da sincronização</item>
</string-array>
<string name="sync_error_unauthorized">Usuário/senha incorreto</string>
<!--cert4android-->
<string name="certificate_notification_connection_security">DAVdroid: Segurança da conexão</string>
<string name="trust_certificate_unknown_certificate_found">O DAVdroid encontrou um certificado desconhecido. Deseja torná-lo confiável?</string>
</resources>

View File

@@ -14,7 +14,6 @@
<!--AddAccountActivity-->
<string name="login_type_email">Login com seu enderço de email</string>
<string name="login_type_url">Login com URL e nome do usuário</string>
<string name="login_auth_preemptive">Autenticação preferida (recomendado, mas incompatível com Digest)</string>
<!--AccountSettingsActivity-->
<string name="settings_authentication">Autenticação</string>
<string name="settings_username">Nome de usuário</string>
@@ -22,9 +21,6 @@
<string name="settings_password">Senha</string>
<string name="settings_password_summary">Atualize sua denha de acordo com a do seu servidor.</string>
<string name="settings_enter_password">Informe sua senha:</string>
<string name="settings_preemptive">Pre-emptive authentication</string>
<string name="settings_preemptive_on">Credenciais são enviadas com cadas requisição (recomendado)</string>
<string name="settings_preemptive_off">Credenciais são enviadas apos o servidor requisitar</string>
<string name="settings_sync">Sincronização</string>
<string name="settings_sync_interval_contacts">Intervalo de sincronização dos contatos</string>
<string name="settings_sync_summary_manually">Manualmente apenas</string>
@@ -54,4 +50,5 @@
<!--collection management-->
<!--ExceptionInfoFragment-->
<!--sync errors and DebugInfoActivity-->
<!--cert4android-->
</resources>

View File

@@ -15,7 +15,6 @@
<!--AddAccountActivity-->
<string name="login_type_email">Вход по адресу email</string>
<string name="login_type_url">Вход через URL и имя пользователя</string>
<string name="login_auth_preemptive">Упреждающая идентификация (рекомендовано, но несовместимо с Digest идентификацией)</string>
<!--AccountSettingsActivity-->
<string name="settings_authentication">Идентификация</string>
<string name="settings_username">Имя</string>
@@ -23,9 +22,6 @@
<string name="settings_password">Пароль</string>
<string name="settings_password_summary">Обновить пароль в соответствии с вашим сервером.</string>
<string name="settings_enter_password">Введите свой пароль:</string>
<string name="settings_preemptive">Упреждающая идентификация</string>
<string name="settings_preemptive_on">Учетные данные посылаются с каждым запросом (рекомендовано)</string>
<string name="settings_preemptive_off">Учетные данные посылаются после их запроса сервером</string>
<string name="settings_sync">Синхронизация</string>
<string name="settings_sync_interval_contacts">Интервал синхронизации контактов</string>
<string name="settings_sync_summary_manually">Вручную</string>
@@ -64,4 +60,5 @@
<string name="sync_error_http_dav">Ошибка сервера %s</string>
<string name="sync_error_local_storage">Ошибка базы данных в процессе %s</string>
<string name="sync_error_unauthorized">Имя пользователя/пароль неверные</string>
<!--cert4android-->
</resources>

View File

@@ -7,6 +7,9 @@
<string name="please_wait">Сачекајте…</string>
<string name="send">Пошаљи</string>
<!--startup dialogs-->
<string name="startup_battery_optimization">Оптимизација батерије</string>
<string name="startup_battery_optimization_message">Андроид може да искључи/умањи синхронизацију ДАВдроида након неколико дана. Да бисте спречили ово, искључите оптимизацију батерије.</string>
<string name="startup_battery_optimization_disable">Искључи за ДАВдроид</string>
<string name="startup_dont_show_again">Не приказуј поново</string>
<string name="startup_development_version">ДАВдроид прелиминарно издање</string>
<string name="startup_development_version_message">Ово је развојно издање ДАВдроида. Имајте на уму да можда неће радити очекивано. Замољавамо вас за конструктивне повратне информације како бисмо га побољшали.</string>
@@ -54,13 +57,12 @@
<string name="app_settings_reset_hints_summary">Поновно приказивање претходно одбачених савета</string>
<string name="app_settings_reset_hints_success">Сви савети ће поново бити приказани</string>
<string name="app_settings_security">Безбедност</string>
<string name="app_settings_reset_trusted_certificates">Ресетуј поуздане сертификате</string>
<string name="app_settings_reset_trusted_certificates_summary">Заборављање претходно прихваћених сертификата</string>
<plurals name="app_settings_reset_trusted_certificates_success">
<item quantity="one">Посумњано у један сертификат</item>
<item quantity="few">Посумњано у %d сертификата</item>
<item quantity="other">Посумњано у %d сертификата</item>
</plurals>
<string name="app_settings_distrust_system_certs">Посумњај у системске сертификате</string>
<string name="app_settings_distrust_system_certs_on">Системски и кориснички додати сертификати неће бити поуздани</string>
<string name="app_settings_distrust_system_certs_off">Системски и кориснички додати сертификати ће бити поуздани (препоручљиво)</string>
<string name="app_settings_reset_certificates">Ресетуј (не)поуздане сертификате</string>
<string name="app_settings_reset_certificates_summary">Ресетуј поуздање свих прилагођених сертификата</string>
<string name="app_settings_reset_certificates_success">Сви прилагођени сертификати су уклоњени</string>
<string name="app_settings_debug">Тражење грешака</string>
<string name="app_settings_log_to_external_storage">Уписуј у спољашњи фајл</string>
<string name="app_settings_log_to_external_storage_on">Уписивање евиденције у спољашње складиште (ако је доступно)</string>
@@ -102,7 +104,6 @@
<string name="login_user_name">Корисничко име</string>
<string name="login_user_name_required">Корисничко име је обавезно</string>
<string name="login_base_url">Корени УРЛ</string>
<string name="login_auth_preemptive">Превентивна аутентификација (препоручено, али некомпатибилно са Дигест аутентификацијом)</string>
<string name="login_login">Пријава</string>
<string name="login_back">Назад</string>
<string name="login_create_account">Направи налог</string>
@@ -123,9 +124,6 @@
<string name="settings_password">Лозинка</string>
<string name="settings_password_summary">Ажурирајте лозинку за ваш сервер.</string>
<string name="settings_enter_password">Унесите лозинку:</string>
<string name="settings_preemptive">Превентивна аутентификација</string>
<string name="settings_preemptive_on">Слање акредитива са сваким захтевом (препоручено)</string>
<string name="settings_preemptive_off">Слање акредитива по захтеву сервера</string>
<string name="settings_sync">Синхронизација</string>
<string name="settings_sync_interval_contacts">Интервал синх. контаката</string>
<string name="settings_sync_summary_manually">Само ручно</string>
@@ -239,4 +237,7 @@
<item>уписујем стање синхронизације</item>
</string-array>
<string name="sync_error_unauthorized">Корисничко име или лозинка погрешни</string>
<!--cert4android-->
<string name="certificate_notification_connection_security">ДАВдроид: Безбедност везе</string>
<string name="trust_certificate_unknown_certificate_found">ДАВдроид је наишао на непознат сертификат. Желите ли да се поуздате у њега?</string>
</resources>

View File

@@ -54,11 +54,6 @@
<string name="app_settings_reset_hints_summary">Daha önceden azat edilen ipuçlarını yeniden etkinleştirir</string>
<string name="app_settings_reset_hints_success">Tüm ipuçları artık gösterilecek</string>
<string name="app_settings_security">Güvenlik</string>
<string name="app_settings_reset_trusted_certificates">Güvenilen sertifikaları sıfırla</string>
<string name="app_settings_reset_trusted_certificates_summary">Daha önceden kabul edilmiş tüm sertifikaları unutur</string>
<plurals name="app_settings_reset_trusted_certificates_success">
<item quantity="other">Güvenilmeyen %d sertifikaları</item>
</plurals>
<string name="app_settings_debug">Hata ayıklama</string>
<string name="app_settings_log_to_external_storage">Harici dosyaya jurnalle</string>
<string name="app_settings_log_to_external_storage_on">Harici depolamaya jurnalleniyor (eğer uygunsa)</string>
@@ -101,7 +96,6 @@
<string name="login_user_name">Kullanıcı adı</string>
<string name="login_user_name_required">Kullanıcı adı zorunludur</string>
<string name="login_base_url">Baz URL</string>
<string name="login_auth_preemptive">Önleyici doğrulama (tavsiye edilir, fakat Digest doğrulama ile uyumsuz)</string>
<string name="login_login">Giriş</string>
<string name="login_back">Geri</string>
<string name="login_create_account">Hesap yarat</string>
@@ -121,9 +115,6 @@
<string name="settings_password">Parola</string>
<string name="settings_password_summary">Parolayı sunucunuza göre güncelleyin.</string>
<string name="settings_enter_password">Parola girin:</string>
<string name="settings_preemptive">Önleyici doğrulama</string>
<string name="settings_preemptive_on">Giriş bilgileri her istek ile gönderilir (tavsiye edilir)</string>
<string name="settings_preemptive_off">Giriş bilgileri sunucu istedikten sonra gönderilir</string>
<string name="settings_sync">Senkronizasyon</string>
<string name="settings_sync_interval_contacts">Kişiler senk. aralığı</string>
<string name="settings_sync_summary_manually">Sadece elle</string>
@@ -209,4 +200,5 @@
<string name="sync_error_http_dav">%s yaparken sunucu hatası</string>
<string name="sync_error_local_storage">%s yaparken veritabanı hatası</string>
<string name="sync_error_unauthorized">Kullanıcı adı/parola yanlış</string>
<!--cert4android-->
</resources>

View File

@@ -14,7 +14,6 @@
<!--AddAccountActivity-->
<string name="login_type_email">Увійти за допомогою електронної пошти</string>
<string name="login_type_url">Увійти за допомогою URL та імені користувача</string>
<string name="login_auth_preemptive">Випереджаюча автентифікація (рекомендовано, але несумісно із Digest auth)</string>
<!--AccountSettingsActivity-->
<string name="settings_authentication">Автентифікація</string>
<string name="settings_username">Ім\'я користувача</string>
@@ -22,9 +21,6 @@
<string name="settings_password">Пароль</string>
<string name="settings_password_summary">Оновити пароль, згідно налаштувань Вашого сервера.</string>
<string name="settings_enter_password">Введіть Ваш пароль:</string>
<string name="settings_preemptive">Випереджаюча автентифікація</string>
<string name="settings_preemptive_on">Дані автентифікації будуть надсилатися із кожним запитом (рекомендовано)</string>
<string name="settings_preemptive_off">Дані автентифікації будуть надіслані після відповідного запиту сервера</string>
<string name="settings_sync">Синхронізація</string>
<string name="settings_sync_interval_contacts">Інтервал синхронізації контактів</string>
<string name="settings_sync_summary_manually">Лише вручну</string>
@@ -55,4 +51,5 @@
<!--collection management-->
<!--ExceptionInfoFragment-->
<!--sync errors and DebugInfoActivity-->
<!--cert4android-->
</resources>

View File

@@ -7,6 +7,9 @@
<string name="please_wait">请稍等...</string>
<string name="send">发送</string>
<!--startup dialogs-->
<string name="startup_battery_optimization">电池优化</string>
<string name="startup_battery_optimization_message">系统可能会在几天后减少或停用 DAVdroid 同步。为了避免这一情况,请对 DAVdroid 忽略电池优化。</string>
<string name="startup_battery_optimization_disable">忽略电池优化</string>
<string name="startup_dont_show_again">不再显示</string>
<string name="startup_development_version">DAVdroid 预览版</string>
<string name="startup_development_version_message">这是 DAVdroid 的开发版本,部分功能可能无法正常工作。请您提出建设性反馈,帮助我们完善 DAVdroid。</string>
@@ -54,11 +57,12 @@
<string name="app_settings_reset_hints_summary">重新显示之前忽略过的提示</string>
<string name="app_settings_reset_hints_success">所有提示将会再次显示</string>
<string name="app_settings_security">安全</string>
<string name="app_settings_reset_trusted_certificates">重设受信任证书</string>
<string name="app_settings_reset_trusted_certificates_summary">取消信任所有之前接受的证书</string>
<plurals name="app_settings_reset_trusted_certificates_success">
<item quantity="other">已删除 %d 个证书</item>
</plurals>
<string name="app_settings_distrust_system_certs">不信任系统证书</string>
<string name="app_settings_distrust_system_certs_on">系统和用户增加的发布者不会被信任</string>
<string name="app_settings_distrust_system_certs_off">系统和用户增加的发布者会被信任(推荐)</string>
<string name="app_settings_reset_certificates">重设证书信任状态</string>
<string name="app_settings_reset_certificates_summary">重设所有自定义证书的信任状态</string>
<string name="app_settings_reset_certificates_success">所有自定义证书已清除</string>
<string name="app_settings_debug">调试</string>
<string name="app_settings_log_to_external_storage">外部文件日志</string>
<string name="app_settings_log_to_external_storage_on">记录日志到外部存储(如果可用)</string>
@@ -100,7 +104,6 @@
<string name="login_user_name">用户名</string>
<string name="login_user_name_required">请输入用户名</string>
<string name="login_base_url">根地址</string>
<string name="login_auth_preemptive">强制认证模式(推荐使用,但不兼容 Digest 认证方式)</string>
<string name="login_login">登录</string>
<string name="login_back">返回</string>
<string name="login_create_account">创建账户</string>
@@ -121,9 +124,6 @@
<string name="settings_password">密码</string>
<string name="settings_password_summary">修改服务器密码</string>
<string name="settings_enter_password">输入密码</string>
<string name="settings_preemptive">强制认证模式</string>
<string name="settings_preemptive_on">认证信息在每次请求中发送(推荐)</string>
<string name="settings_preemptive_off">认证信息在服务器要求后才发送</string>
<string name="settings_sync">同步</string>
<string name="settings_sync_interval_contacts">通讯录自动同步间隔</string>
<string name="settings_sync_summary_manually">手动同步</string>
@@ -235,4 +235,7 @@
<item>保存同步状态</item>
</string-array>
<string name="sync_error_unauthorized">用户名或密码错误</string>
<!--cert4android-->
<string name="certificate_notification_connection_security">DAVdroid: 连接安全性</string>
<string name="trust_certificate_unknown_certificate_found">DAVdroid 遇到了未知证书。你是否要信任该证书?</string>
</resources>

View File

@@ -16,7 +16,7 @@
android:title="@string/navigation_drawer_about"/>
<item
android:id="@+id/nav_app_settings"
android:icon="@drawable/ic_settings_dark"
android:icon="@drawable/ic_settings_action"
android:title="@string/navigation_drawer_settings"/>
<item android:title="@string/navigation_drawer_news_updates">
@@ -37,7 +37,7 @@
android:title="@string/navigation_drawer_website"/>
<item
android:id="@+id/nav_faq"
android:icon="@drawable/ic_help_dark"
android:icon="@drawable/ic_help_action"
android:title="@string/navigation_drawer_faq"/>
<item
android:id="@+id/nav_forums"
@@ -46,9 +46,8 @@
<item
android:id="@+id/nav_donate"
android:icon="@drawable/ic_attach_money_dark"
android:title="(entry disabled)"
android:visible="false"
tools:ignore="HardcodedText"/>
android:title="@string/navigation_drawer_donate"
android:visible="false"/>
</menu>
</item>

View File

@@ -15,28 +15,22 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS"/>
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/>
<uses-permission android:name="android.permission.READ_SYNC_STATS"/>
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/>
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<!-- account management permissions not required for own accounts since API level 22 -->
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" android:maxSdkVersion="22"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS" android:maxSdkVersion="22"/>
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" android:maxSdkVersion="22"/>
<!-- legacy permissions -->
<uses-permission
android:name="android.permission.AUTHENTICATE_ACCOUNTS"
android:maxSdkVersion="22"
tools:ignore="UnusedAttribute"/>
<!--
for writing external log files; permission only required for SDK <= 18 because since then,
writing to app-private directory doesn't require extra permissions
-->
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="18"
tools:ignore="UnusedAttribute"/>
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18"
tools:ignore="UnusedAttribute"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="18"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18"/>
<!-- other permissions -->
<!-- android.permission-group.CONTACTS -->
@@ -52,17 +46,18 @@
android:name=".App"
android:allowBackup="true"
android:fullBackupContent="false"
android:icon="@drawable/ic_launcher"
android:networkSecurityConfig="@xml/network_security_config"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
tools:ignore="UnusedAttribute">
<receiver
android:name=".App$ReinitLoggingReceiver"
android:name=".App$ReinitSettingsReceiver"
android:exported="false"
android:process=":sync">
<intent-filter>
<action android:name="at.bitfire.davdroid.REINIT_LOGGER"/>
<action android:name="at.bitfire.davdroid.REINIT_SETTINGS"/>
</intent-filter>
</receiver>
<receiver
@@ -191,11 +186,6 @@
android:label="@string/debug_info_title">
</activity>
<!-- MemorizingTrustManager -->
<activity
android:name="de.duenndns.ssl.MemorizingActivity"
android:theme="@android:style/Theme.Holo.Light.Dialog.NoActionBar"/>
</application>
</manifest>

View File

@@ -10,8 +10,9 @@ package at.bitfire.davdroid;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
@@ -20,12 +21,13 @@ import android.content.Context;
import android.content.Intent;
import android.content.PeriodicSync;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.os.Bundle;
import android.provider.CalendarContract;
import android.provider.ContactsContract;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v7.app.NotificationCompat;
import android.text.TextUtils;
@@ -55,7 +57,6 @@ public class AccountSettings {
KEY_SETTINGS_VERSION = "version",
KEY_USERNAME = "user_name",
KEY_AUTH_PREEMPTIVE = "auth_preemptive",
KEY_WIFI_ONLY = "wifi_only", // sync on WiFi only (default: false)
KEY_WIFI_ONLY_SSID = "wifi_only_ssid"; // restrict sync to specific WiFi SSID
@@ -92,6 +93,7 @@ public class AccountSettings {
final Account account;
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public AccountSettings(@NonNull Context context, @NonNull Account account) throws InvalidAccountException {
this.context = context;
this.account = account;
@@ -112,8 +114,8 @@ public class AccountSettings {
if (version < CURRENT_VERSION) {
Notification notify = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_new_releases_light)
.setLargeIcon(((BitmapDrawable)context.getResources().getDrawable(R.drawable.ic_launcher)).getBitmap())
.setSmallIcon(R.drawable.ic_error_light)
.setLargeIcon(App.getLauncherBitmap(context))
.setContentTitle(context.getString(R.string.settings_version_update))
.setContentText(context.getString(R.string.settings_version_update_settings_updated))
.setSubText(context.getString(R.string.settings_version_update_install_hint))
@@ -121,9 +123,12 @@ public class AccountSettings {
.bigText(context.getString(R.string.settings_version_update_settings_updated)))
.setCategory(NotificationCompat.CATEGORY_SYSTEM)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(PendingIntent.getActivity(context, 0,
new Intent(Intent.ACTION_VIEW, Constants.webUri.buildUpon().appendEncodedPath("faq/entry/davdroid-not-working-after-update/").build()),
PendingIntent.FLAG_CANCEL_CURRENT))
.setLocalOnly(true)
.build();
NotificationManager nm = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationManagerCompat nm = NotificationManagerCompat.from(context);
nm.notify(Constants.NOTIFICATION_ACCOUNT_SETTINGS_UPDATED, notify);
update(version);
@@ -131,11 +136,10 @@ public class AccountSettings {
}
}
public static Bundle initialUserData(String userName, boolean preemptive) {
public static Bundle initialUserData(String userName) {
Bundle bundle = new Bundle();
bundle.putString(KEY_SETTINGS_VERSION, String.valueOf(CURRENT_VERSION));
bundle.putString(KEY_USERNAME, userName);
bundle.putString(KEY_AUTH_PREEMPTIVE, Boolean.toString(preemptive));
return bundle;
}
@@ -148,9 +152,6 @@ public class AccountSettings {
public String password() { return accountManager.getPassword(account); }
public void password(@NonNull String password) { accountManager.setPassword(account, password); }
public boolean preemptiveAuth() { return Boolean.parseBoolean(accountManager.getUserData(account, KEY_AUTH_PREEMPTIVE)); }
public void preemptiveAuth(boolean preemptive) { accountManager.setUserData(account, KEY_AUTH_PREEMPTIVE, Boolean.toString(preemptive)); }
// sync. settings
@@ -198,11 +199,17 @@ public class AccountSettings {
// CardDAV settings
public boolean getVCardRFC6868() {
if (BuildConfig.settingVCardRFC6868 != null)
return BuildConfig.settingVCardRFC6868;
return accountManager.getUserData(account, KEY_VCARD_RFC6868) == null;
}
public void setVCardRFC6868(boolean use) {
accountManager.setUserData(account, KEY_VCARD_RFC6868, use ? null : "0");
if (BuildConfig.settingVCardRFC6868 == null)
accountManager.setUserData(account, KEY_VCARD_RFC6868, use ? null : "0");
else if (BuildConfig.settingVCardRFC6868 != use)
throw new UnsupportedOperationException("Setting is read-only");
}
@@ -235,6 +242,9 @@ public class AccountSettings {
@NonNull
public GroupMethod getGroupMethod() {
if (BuildConfig.settingContactGroupMethod != null)
return BuildConfig.settingContactGroupMethod;
final String name = accountManager.getUserData(account, KEY_CONTACT_GROUP_METHOD);
return name != null ?
GroupMethod.valueOf(name) :
@@ -242,8 +252,11 @@ public class AccountSettings {
}
public void setGroupMethod(@NonNull GroupMethod method) {
final String name = method == GroupMethod.GROUP_VCARDS ? null : method.name();
accountManager.setUserData(account, KEY_CONTACT_GROUP_METHOD, name);
if (BuildConfig.settingContactGroupMethod == null) {
final String name = method == GroupMethod.GROUP_VCARDS ? null : method.name();
accountManager.setUserData(account, KEY_CONTACT_GROUP_METHOD, name);
} else if (BuildConfig.settingContactGroupMethod != method)
throw new UnsupportedOperationException("Setting is read-only");
}
@@ -428,13 +441,13 @@ public class AccountSettings {
public static class AppUpdatedReceiver extends BroadcastReceiver {
@Override
@SuppressLint("UnsafeProtectedBroadcastReceiver")
@SuppressLint("UnsafeProtectedBroadcastReceiver,MissingPermission")
public void onReceive(Context context, Intent intent) {
App.log.info("DAVdroid was updated, checking for AccountSettings version");
// peek into AccountSettings to initiate a possible migration
AccountManager accountManager = AccountManager.get(context);
for (Account account : accountManager.getAccountsByType(Constants.ACCOUNT_TYPE))
for (Account account : accountManager.getAccountsByType(context.getString(R.string.account_type)))
try {
App.log.info("Checking account " + account.name);
new AccountSettings(context, account);

View File

@@ -8,6 +8,7 @@
package at.bitfire.davdroid;
import android.accounts.AccountManager;
import android.accounts.OnAccountsUpdateListener;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -22,12 +23,14 @@ public class AccountsChangedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent(context, DavService.class);
serviceIntent.setAction(DavService.ACTION_ACCOUNTS_UPDATED);
context.startService(serviceIntent);
if (AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION.equals(intent.getAction())) {
Intent serviceIntent = new Intent(context, DavService.class);
serviceIntent.setAction(DavService.ACTION_ACCOUNTS_UPDATED);
context.startService(serviceIntent);
for (OnAccountsUpdateListener listener : listeners)
listener.onAccountsUpdated(null);
for (OnAccountsUpdateListener listener : listeners)
listener.onAccountsUpdated(null);
}
}
public static void registerListener(OnAccountsUpdateListener listener, boolean callImmediately) {

View File

@@ -8,12 +8,18 @@
package at.bitfire.davdroid;
import android.annotation.TargetApi;
import android.app.Application;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v7.app.NotificationCompat;
import android.util.Log;
@@ -28,22 +34,27 @@ import java.util.logging.Logger;
import javax.net.ssl.HostnameVerifier;
import at.bitfire.cert4android.CustomCertManager;
import at.bitfire.davdroid.log.LogcatHandler;
import at.bitfire.davdroid.log.PlainTextFormatter;
import at.bitfire.davdroid.model.ServiceDB;
import at.bitfire.davdroid.model.Settings;
import de.duenndns.ssl.MemorizingTrustManager;
import lombok.Cleanup;
import lombok.Getter;
import okhttp3.internal.tls.OkHostnameVerifier;
public class App extends Application {
public static final String FLAVOR_GOOGLE_PLAY = "gplay";
public static final String
FLAVOR_GOOGLE_PLAY = "gplay",
FLAVOR_ICLOUD = "icloud",
FLAVOR_STANDARD = "standard";
public static final String LOG_TO_EXTERNAL_STORAGE = "logToExternalStorage";
public static final String
DISTRUST_SYSTEM_CERTIFICATES = "distrustSystemCerts",
LOG_TO_EXTERNAL_STORAGE = "logToExternalStorage";
@Getter
private static MemorizingTrustManager memorizingTrustManager;
private CustomCertManager certManager;
@Getter
private static SSLSocketFactoryCompat sslSocketFactoryCompat;
@@ -54,21 +65,30 @@ public class App extends Application {
public final static Logger log = Logger.getLogger("davdroid");
static {
at.bitfire.dav4android.Constants.log = Logger.getLogger("davdroid.dav4android");
at.bitfire.cert4android.Constants.log = Logger.getLogger("davdroid.cert4android");
}
@Override
public void onCreate() {
super.onCreate();
// initialize MemorizingTrustManager
memorizingTrustManager = new MemorizingTrustManager(this);
sslSocketFactoryCompat = new SSLSocketFactoryCompat(memorizingTrustManager);
hostnameVerifier = memorizingTrustManager.wrapHostnameVerifier(OkHostnameVerifier.INSTANCE);
// initializer logger
reinitCertManager();
reinitLogger();
}
public void reinitCertManager() {
if (BuildConfig.customCerts) {
if (certManager != null)
certManager.close();
@Cleanup ServiceDB.OpenHelper dbHelper = new ServiceDB.OpenHelper(this);
Settings settings = new Settings(dbHelper.getReadableDatabase());
certManager = new CustomCertManager(this, !settings.getBoolean(DISTRUST_SYSTEM_CERTIFICATES, false));
sslSocketFactoryCompat = new SSLSocketFactoryCompat(certManager);
hostnameVerifier = certManager.hostnameVerifier(OkHostnameVerifier.INSTANCE);
}
}
public void reinitLogger() {
// don't use Android default logging, we have our own handlers
log.setUseParentHandlers(false);
@@ -89,12 +109,12 @@ public class App extends Application {
// add logcat handler
log.addHandler(LogcatHandler.INSTANCE);
NotificationManager nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
NotificationManagerCompat nm = NotificationManagerCompat.from(this);
// log to external file according to preferences
if (logToFile) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder .setSmallIcon(R.drawable.ic_sd_storage_light)
.setLargeIcon(((BitmapDrawable)getResources().getDrawable(R.drawable.ic_launcher)).getBitmap())
.setLargeIcon(getLauncherBitmap(this))
.setContentTitle(getString(R.string.logging_davdroid_file_logging))
.setLocalOnly(true);
@@ -130,15 +150,30 @@ public class App extends Application {
nm.cancel(Constants.NOTIFICATION_EXTERNAL_FILE_LOGGING);
}
@Nullable
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static Bitmap getLauncherBitmap(@NonNull Context context) {
Bitmap bitmapLogo = null;
Drawable drawableLogo = android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP ?
context.getDrawable(R.mipmap.ic_launcher) :
context.getResources().getDrawable(R.mipmap.ic_launcher);
if (drawableLogo instanceof BitmapDrawable)
bitmapLogo = ((BitmapDrawable)drawableLogo).getBitmap();
return bitmapLogo;
}
public static class ReinitLoggingReceiver extends BroadcastReceiver {
public static class ReinitSettingsReceiver extends BroadcastReceiver {
public static final String ACTION_REINIT_SETTINGS = "at.bitfire.davdroid.REINIT_SETTINGS";
@Override
public void onReceive(Context context, Intent intent) {
log.info("Received broadcast: re-initializing logger");
log.info("Received broadcast: re-initializing settings (logger/cert manager)");
App app = (App)context.getApplicationContext();
app.reinitLogger();
app.reinitCertManager();
}
}

View File

@@ -11,9 +11,6 @@ import android.net.Uri;
public class Constants {
public static final String
ACCOUNT_TYPE = "bitfire.at.davdroid";
// notification IDs
public final static int
NOTIFICATION_ACCOUNT_SETTINGS_UPDATED = 0,
@@ -22,8 +19,11 @@ public class Constants {
NOTIFICATION_CONTACTS_SYNC = 10,
NOTIFICATION_CALENDAR_SYNC = 11,
NOTIFICATION_TASK_SYNC = 12,
NOTIFICATION_PERMISSIONS = 20;
NOTIFICATION_PERMISSIONS = 20,
NOTIFICATION_SUBSCRIPTION = 21;
public static final Uri webUri = Uri.parse("https://davdroid.bitfire.at/?pk_campaign=davdroid-app");
public static final Uri webUri = BuildConfig.FLAVOR == App.FLAVOR_ICLOUD ?
Uri.parse("https://multisync.cloud/?pk_campaign=multisync-app") :
Uri.parse("https://davdroid.bitfire.at/?pk_campaign=davdroid-app");
}

View File

@@ -10,8 +10,8 @@ package at.bitfire.davdroid;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ContentValues;
@@ -19,11 +19,11 @@ import android.content.Intent;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.drawable.BitmapDrawable;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v7.app.NotificationCompat;
import android.text.TextUtils;
@@ -140,6 +140,7 @@ public class DavService extends Service {
which actually do the work
*/
@SuppressLint("MissingPermission")
void cleanupAccounts() {
App.log.info("Cleaning up orphaned accounts");
@@ -149,7 +150,7 @@ public class DavService extends Service {
List<String> sqlAccountNames = new LinkedList<>();
AccountManager am = AccountManager.get(this);
for (Account account : am.getAccountsByType(Constants.ACCOUNT_TYPE))
for (Account account : am.getAccountsByType(getString(R.string.account_type)))
sqlAccountNames.add(DatabaseUtils.sqlEscapeString(account.name));
if (sqlAccountNames.isEmpty())
@@ -290,8 +291,8 @@ public class DavService extends Service {
info.selected = true;
}
db.beginTransactionNonExclusive();
try {
db.beginTransactionNonExclusive();
saveHomeSets(homeSets);
saveCollections(collections.values());
db.setTransactionSuccessful();
@@ -309,10 +310,10 @@ public class DavService extends Service {
if (account != null)
debugIntent.putExtra(DebugInfoActivity.KEY_ACCOUNT, account);
NotificationManager nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
NotificationManagerCompat nm = NotificationManagerCompat.from(DavService.this);
Notification notify = new NotificationCompat.Builder(DavService.this)
.setSmallIcon(R.drawable.ic_error_light)
.setLargeIcon(((BitmapDrawable)getResources().getDrawable(R.drawable.ic_launcher)).getBitmap())
.setLargeIcon(App.getLauncherBitmap(DavService.this))
.setContentTitle(getString(R.string.dav_service_refresh_failed))
.setContentText(getString(R.string.dav_service_refresh_couldnt_refresh))
.setContentIntent(PendingIntent.getActivity(DavService.this, 0, debugIntent, PendingIntent.FLAG_UPDATE_CURRENT))
@@ -357,7 +358,7 @@ public class DavService extends Service {
private Account account() {
@Cleanup Cursor cursor = db.query(Services._TABLE, new String[] { Services.ACCOUNT_NAME }, Services.ID + "=?", new String[] { String.valueOf(service) }, null, null, null);
if (cursor.moveToNext()) {
return new Account(cursor.getString(0), Constants.ACCOUNT_TYPE);
return new Account(cursor.getString(0), getString(R.string.account_type));
} else
throw new IllegalArgumentException("Service not found");
}

View File

@@ -12,6 +12,7 @@ import android.accounts.Account;
import android.content.Context;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.io.IOException;
import java.text.SimpleDateFormat;
@@ -21,9 +22,7 @@ import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import at.bitfire.dav4android.BasicDigestAuthenticator;
import lombok.RequiredArgsConstructor;
import okhttp3.Credentials;
import at.bitfire.dav4android.BasicDigestAuthHandler;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
@@ -43,40 +42,40 @@ public class HttpClient {
private HttpClient() {
}
public static OkHttpClient create(@NonNull Context context, @NonNull Account account, @NonNull final Logger logger) throws InvalidAccountException {
OkHttpClient.Builder builder = defaultBuilder(logger);
public static OkHttpClient create(@Nullable Context context, @NonNull Account account, @NonNull final Logger logger) throws InvalidAccountException {
OkHttpClient.Builder builder = defaultBuilder(context, logger);
// use account settings for authentication and logging
// use account settings for authentication
AccountSettings settings = new AccountSettings(context, account);
if (settings.preemptiveAuth())
builder.addNetworkInterceptor(new PreemptiveAuthenticationInterceptor(settings.username(), settings.password()));
else
builder.authenticator(new BasicDigestAuthenticator(null, settings.username(), settings.password()));
builder = addAuthentication(builder, null, settings.username(), settings.password());
return builder.build();
}
public static OkHttpClient create(@NonNull Logger logger) {
return defaultBuilder(logger).build();
public static OkHttpClient create(@NonNull Context context, @NonNull Logger logger) {
return defaultBuilder(context, logger).build();
}
public static OkHttpClient create(@NonNull Context context, @NonNull Account account) throws InvalidAccountException {
return create(context, account, App.log);
}
public static OkHttpClient create() {
return create(App.log);
public static OkHttpClient create(@Nullable Context context) {
return create(context, App.log);
}
private static OkHttpClient.Builder defaultBuilder(@NonNull final Logger logger) {
private static OkHttpClient.Builder defaultBuilder(@Nullable Context context, @NonNull final Logger logger) {
OkHttpClient.Builder builder = client.newBuilder();
// use MemorizingTrustManager to manage self-signed certificates
if (App.getSslSocketFactoryCompat() != null)
builder.sslSocketFactory(App.getSslSocketFactoryCompat(), App.getMemorizingTrustManager());
if (App.getHostnameVerifier() != null)
builder.hostnameVerifier(App.getHostnameVerifier());
if (context != null) {
App app = (App)context.getApplicationContext();
if (App.getSslSocketFactoryCompat() != null && app.getCertManager() != null)
builder.sslSocketFactory(App.getSslSocketFactoryCompat(), app.getCertManager());
if (App.getHostnameVerifier() != null)
builder.hostnameVerifier(App.getHostnameVerifier());
}
// set timeouts
builder.connectTimeout(30, TimeUnit.SECONDS);
@@ -107,24 +106,23 @@ public class HttpClient {
return builder;
}
private static OkHttpClient.Builder addAuthentication(@NonNull OkHttpClient.Builder builder, @NonNull String username, @NonNull String password, boolean preemptive) {
if (preemptive)
builder.addNetworkInterceptor(new PreemptiveAuthenticationInterceptor(username, password));
else
builder.authenticator(new BasicDigestAuthenticator(null, username, password));
return builder;
private static OkHttpClient.Builder addAuthentication(@NonNull OkHttpClient.Builder builder, @Nullable String host, @NonNull String username, @NonNull String password) {
BasicDigestAuthHandler authHandler = new BasicDigestAuthHandler(host, username, password);
return builder
.addNetworkInterceptor(authHandler)
.authenticator(authHandler);
}
public static OkHttpClient addAuthentication(@NonNull OkHttpClient client, @NonNull String username, @NonNull String password, boolean preemptive) {
public static OkHttpClient addAuthentication(@NonNull OkHttpClient client, @NonNull String username, @NonNull String password) {
OkHttpClient.Builder builder = client.newBuilder();
addAuthentication(builder, username, password, preemptive);
addAuthentication(builder, null, username, password);
return builder.build();
}
public static OkHttpClient addAuthentication(@NonNull OkHttpClient client, @NonNull String host, @NonNull String username, @NonNull String password) {
return client.newBuilder()
.authenticator(new BasicDigestAuthenticator(host, username, password))
.build();
OkHttpClient.Builder builder = client.newBuilder();
addAuthentication(builder, host, username, password);
return builder.build();
}
@@ -140,18 +138,4 @@ public class HttpClient {
}
}
@RequiredArgsConstructor
static class PreemptiveAuthenticationInterceptor implements Interceptor {
final String username, password;
@Override
public Response intercept(Chain chain) throws IOException {
App.log.fine("Adding basic authorization header for user " + username);
Request request = chain.request().newBuilder()
.header("Authorization", Credentials.basic(username, password))
.build();
return chain.proceed(request);
}
}
}

View File

@@ -27,7 +27,6 @@ import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.X509TrustManager;
import de.duenndns.ssl.MemorizingTrustManager;
import lombok.Cleanup;
public class SSLSocketFactoryCompat extends SSLSocketFactory {
@@ -99,10 +98,10 @@ public class SSLSocketFactoryCompat extends SSLSocketFactory {
}
}
public SSLSocketFactoryCompat(@NonNull MemorizingTrustManager mtm) {
public SSLSocketFactoryCompat(@NonNull X509TrustManager trustManager) {
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new X509TrustManager[] { mtm }, null);
sslContext.init(null, new X509TrustManager[] { trustManager }, null);
delegate = sslContext.getSocketFactory();
} catch (GeneralSecurityException e) {
throw new AssertionError(); // The system has no TLS. Just give up.

View File

@@ -175,7 +175,7 @@ public class LocalAddressBook extends AndroidAddressBook implements LocalCollect
// SYNC STATE
@SuppressWarnings("Recycle")
@SuppressWarnings("ParcelClassLoader,Recycle")
protected void readSyncState() throws ContactsStorageException {
@Cleanup("recycle") Parcel parcel = Parcel.obtain();
byte[] raw = getSyncState();

View File

@@ -30,7 +30,6 @@ import net.fortuna.ical4j.model.component.VTimeZone;
import org.apache.commons.lang3.StringUtils;
import java.io.FileNotFoundException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@@ -51,10 +50,6 @@ public class LocalCalendar extends AndroidCalendar implements LocalCollection {
public static final String COLUMN_CTAG = Calendars.CAL_SYNC1;
protected static final int
DIRTY_INCREASE_SEQUENCE = 1,
DIRTY_DONT_INCREASE_SEQUENCE = 2;
static String[] BASE_INFO_COLUMNS = new String[] {
Events._ID,
Events._SYNC_ID,
@@ -140,14 +135,11 @@ public class LocalCalendar extends AndroidCalendar implements LocalCollection {
public LocalResource[] getDirty() throws CalendarStorageException, FileNotFoundException {
List<LocalResource> dirty = new LinkedList<>();
// get dirty events which are not required to have an increased SEQUENCE value
Collections.addAll(dirty, (LocalEvent[])queryEvents(Events.DIRTY + "=" + DIRTY_DONT_INCREASE_SEQUENCE + " AND " + Events.ORIGINAL_ID + " IS NULL", null));
// get dirty events which are required to have an increased SEQUENCE value
for (LocalEvent event : (LocalEvent[])queryEvents(Events.DIRTY + "=" + DIRTY_INCREASE_SEQUENCE + " AND " + Events.ORIGINAL_ID + " IS NULL", null)) {
for (LocalEvent event : (LocalEvent[])queryEvents(Events.DIRTY + "!=0 AND " + Events.ORIGINAL_ID + " IS NULL", null)) {
if (event.getEvent().sequence == null) // sequence has not been assigned yet (i.e. this event was just locally created)
event.getEvent().sequence = 0;
else
else if (event.weAreOrganizer)
event.getEvent().sequence++;
dirty.add(event);
}
@@ -203,14 +195,15 @@ public class LocalCalendar extends AndroidCalendar implements LocalCollection {
BatchOperation batch = new BatchOperation(provider);
// re-schedule original event and set it to DIRTY
batch.enqueue(ContentProviderOperation.newUpdate(
syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, originalID)))
.withValue(LocalEvent.COLUMN_SEQUENCE, originalSequence + 1)
.withValue(Events.DIRTY, DIRTY_INCREASE_SEQUENCE)
.build());
batch.enqueue(new BatchOperation.Operation(
ContentProviderOperation.newUpdate(syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, originalID)))
.withValue(LocalEvent.COLUMN_SEQUENCE, originalSequence + 1)
.withValue(Events.DIRTY, 1)
));
// remove exception
batch.enqueue(ContentProviderOperation.newDelete(
syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, id))).build());
batch.enqueue(new BatchOperation.Operation(
ContentProviderOperation.newDelete(syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, id)))
));
batch.commit();
}
} catch (RemoteException e) {
@@ -232,16 +225,16 @@ public class LocalCalendar extends AndroidCalendar implements LocalCollection {
BatchOperation batch = new BatchOperation(provider);
// original event to DIRTY
batch.enqueue(ContentProviderOperation.newUpdate(
syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, originalID)))
.withValue(Events.DIRTY, DIRTY_DONT_INCREASE_SEQUENCE)
.build());
batch.enqueue(new BatchOperation.Operation(
ContentProviderOperation.newUpdate(syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, originalID)))
.withValue(Events.DIRTY, 1)
));
// increase SEQUENCE and set DIRTY to 0
batch.enqueue(ContentProviderOperation.newUpdate(
syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, id)))
batch.enqueue(new BatchOperation.Operation(
ContentProviderOperation.newUpdate(syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, id)))
.withValue(LocalEvent.COLUMN_SEQUENCE, sequence + 1)
.withValue(Events.DIRTY, 0)
.build());
));
batch.commit();
}
} catch (RemoteException e) {

View File

@@ -98,14 +98,17 @@ public class LocalContact extends AndroidContact implements LocalResource {
super.insertDataRows(batch);
if (contact.unknownProperties != null) {
ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(dataSyncURI());
if (id == null)
builder.withValueBackReference(UnknownProperties.RAW_CONTACT_ID, 0);
else
final BatchOperation.Operation op;
final ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(dataSyncURI());
if (id == null) {
op = new BatchOperation.Operation(builder, UnknownProperties.RAW_CONTACT_ID, 0);
} else {
op = new BatchOperation.Operation(builder);
builder.withValue(UnknownProperties.RAW_CONTACT_ID, id);
}
builder .withValue(UnknownProperties.MIMETYPE, UnknownProperties.CONTENT_ITEM_TYPE)
.withValue(UnknownProperties.UNKNOWN_PROPERTIES, contact.unknownProperties);
batch.enqueue(builder.build());
batch.enqueue(op);
}
}
@@ -113,35 +116,32 @@ public class LocalContact extends AndroidContact implements LocalResource {
public void addToGroup(BatchOperation batch, long groupID) {
assertID();
batch.enqueue(ContentProviderOperation
.newInsert(dataSyncURI())
.withValue(GroupMembership.MIMETYPE, GroupMembership.CONTENT_ITEM_TYPE)
.withValue(GroupMembership.RAW_CONTACT_ID, id)
.withValue(GroupMembership.GROUP_ROW_ID, groupID)
.build()
);
batch.enqueue(new BatchOperation.Operation(
ContentProviderOperation.newInsert(dataSyncURI())
.withValue(GroupMembership.MIMETYPE, GroupMembership.CONTENT_ITEM_TYPE)
.withValue(GroupMembership.RAW_CONTACT_ID, id)
.withValue(GroupMembership.GROUP_ROW_ID, groupID)
));
batch.enqueue(ContentProviderOperation
.newInsert(dataSyncURI())
.withValue(CachedGroupMembership.MIMETYPE, CachedGroupMembership.CONTENT_ITEM_TYPE)
.withValue(CachedGroupMembership.RAW_CONTACT_ID, id)
.withValue(CachedGroupMembership.GROUP_ID, groupID)
.withYieldAllowed(true)
.build()
);
batch.enqueue(new BatchOperation.Operation(
ContentProviderOperation.newInsert(dataSyncURI())
.withValue(CachedGroupMembership.MIMETYPE, CachedGroupMembership.CONTENT_ITEM_TYPE)
.withValue(CachedGroupMembership.RAW_CONTACT_ID, id)
.withValue(CachedGroupMembership.GROUP_ID, groupID)
.withYieldAllowed(true)
));
}
public void removeGroupMemberships(BatchOperation batch) {
assertID();
batch.enqueue(ContentProviderOperation
.newDelete(dataSyncURI())
.withSelection(
Data.RAW_CONTACT_ID + "=? AND " + Data.MIMETYPE + " IN (?,?)",
new String[] { String.valueOf(id), GroupMembership.CONTENT_ITEM_TYPE, CachedGroupMembership.CONTENT_ITEM_TYPE }
)
.withYieldAllowed(true)
.build()
);
batch.enqueue(new BatchOperation.Operation(
ContentProviderOperation.newDelete(dataSyncURI())
.withSelection(
Data.RAW_CONTACT_ID + "=? AND " + Data.MIMETYPE + " IN (?,?)",
new String[] { String.valueOf(id), GroupMembership.CONTENT_ITEM_TYPE, CachedGroupMembership.CONTENT_ITEM_TYPE }
)
.withYieldAllowed(true)
));
}
/**

View File

@@ -41,6 +41,8 @@ public class LocalEvent extends AndroidEvent implements LocalResource {
@Getter protected String fileName;
@Getter @Setter protected String eTag;
public boolean weAreOrganizer = true;
public LocalEvent(@NonNull AndroidCalendar calendar, Event event, String fileName, String eTag) {
super(calendar, event);
this.fileName = fileName;
@@ -66,6 +68,8 @@ public class LocalEvent extends AndroidEvent implements LocalResource {
event.uid = values.getAsString(COLUMN_UID);
event.sequence = values.getAsInteger(COLUMN_SEQUENCE);
if (values.getAsInteger(Events.IS_ORGANIZER) == 0)
weAreOrganizer = false;
}
@Override

View File

@@ -19,7 +19,6 @@ import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.Groups;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.RawContacts.Data;
import android.provider.ContactsContract.RawContactsEntity;
import org.apache.commons.lang3.ArrayUtils;
@@ -66,24 +65,23 @@ public class LocalGroup extends AndroidGroup implements LocalResource {
BatchOperation batch = new BatchOperation(addressBook.provider);
// delete cached group memberships
batch.enqueue(ContentProviderOperation
.newDelete(addressBook.syncAdapterURI(ContactsContract.Data.CONTENT_URI))
.withSelection(
CachedGroupMembership.MIMETYPE + "=? AND " + CachedGroupMembership.GROUP_ID + "=?",
new String[] { CachedGroupMembership.CONTENT_ITEM_TYPE, String.valueOf(id) }
).build()
);
batch.enqueue(new BatchOperation.Operation(
ContentProviderOperation.newDelete(addressBook.syncAdapterURI(ContactsContract.Data.CONTENT_URI))
.withSelection(
CachedGroupMembership.MIMETYPE + "=? AND " + CachedGroupMembership.GROUP_ID + "=?",
new String[] { CachedGroupMembership.CONTENT_ITEM_TYPE, String.valueOf(id) }
)
));
// insert updated cached group memberships
for (long member : getMembers())
batch.enqueue(ContentProviderOperation
.newInsert(addressBook.syncAdapterURI(ContactsContract.Data.CONTENT_URI))
.withValue(CachedGroupMembership.MIMETYPE, CachedGroupMembership.CONTENT_ITEM_TYPE)
.withValue(CachedGroupMembership.RAW_CONTACT_ID, member)
.withValue(CachedGroupMembership.GROUP_ID, id)
.withYieldAllowed(true)
.build()
);
batch.enqueue(new BatchOperation.Operation(
ContentProviderOperation.newInsert(addressBook.syncAdapterURI(ContactsContract.Data.CONTENT_URI))
.withValue(CachedGroupMembership.MIMETYPE, CachedGroupMembership.CONTENT_ITEM_TYPE)
.withValue(CachedGroupMembership.RAW_CONTACT_ID, member)
.withValue(CachedGroupMembership.GROUP_ID, id)
.withYieldAllowed(true)
));
batch.commit();
}
@@ -120,12 +118,11 @@ public class LocalGroup extends AndroidGroup implements LocalResource {
BatchOperation batch = new BatchOperation(addressBook.provider);
for (long member : getMembers())
batch.enqueue(ContentProviderOperation
.newUpdate(addressBook.syncAdapterURI(ContentUris.withAppendedId(RawContacts.CONTENT_URI, member)))
.withValue(RawContacts.DIRTY, 1)
.withYieldAllowed(true)
.build()
);
batch.enqueue(new BatchOperation.Operation(
ContentProviderOperation.newUpdate(addressBook.syncAdapterURI(ContentUris.withAppendedId(RawContacts.CONTENT_URI, member)))
.withValue(RawContacts.DIRTY, 1)
.withYieldAllowed(true)
));
batch.commit();
}
@@ -151,15 +148,14 @@ public class LocalGroup extends AndroidGroup implements LocalResource {
Constants.log.fine("Assigning members to group " + id);
// delete all memberships and cached memberships for this group
batch.enqueue(ContentProviderOperation
.newDelete(addressBook.syncAdapterURI(ContactsContract.Data.CONTENT_URI))
.withSelection(
"(" + GroupMembership.MIMETYPE + "=? AND " + GroupMembership.GROUP_ROW_ID + "=?) OR (" +
CachedGroupMembership.MIMETYPE + "=? AND " + CachedGroupMembership.GROUP_ID + "=?)",
new String[] { GroupMembership.CONTENT_ITEM_TYPE, String.valueOf(id), CachedGroupMembership.CONTENT_ITEM_TYPE, String.valueOf(id) })
.withYieldAllowed(true)
.build()
);
batch.enqueue(new BatchOperation.Operation(
ContentProviderOperation.newDelete(addressBook.syncAdapterURI(ContactsContract.Data.CONTENT_URI))
.withSelection(
"(" + GroupMembership.MIMETYPE + "=? AND " + GroupMembership.GROUP_ROW_ID + "=?) OR (" +
CachedGroupMembership.MIMETYPE + "=? AND " + CachedGroupMembership.GROUP_ID + "=?)",
new String[] { GroupMembership.CONTENT_ITEM_TYPE, String.valueOf(id), CachedGroupMembership.CONTENT_ITEM_TYPE, String.valueOf(id) })
.withYieldAllowed(true)
));
// extract list of member UIDs
List<String> members = new LinkedList<>();
@@ -181,12 +177,11 @@ public class LocalGroup extends AndroidGroup implements LocalResource {
}
// remove pending memberships
batch.enqueue(ContentProviderOperation
.newUpdate(addressBook.syncAdapterURI(ContentUris.withAppendedId(Groups.CONTENT_URI, id)))
.withValue(COLUMN_PENDING_MEMBERS, null)
.withYieldAllowed(true)
.build()
);
batch.enqueue(new BatchOperation.Operation(
ContentProviderOperation.newUpdate(addressBook.syncAdapterURI(ContentUris.withAppendedId(Groups.CONTENT_URI, id)))
.withValue(COLUMN_PENDING_MEMBERS, null)
.withYieldAllowed(true)
));
batch.commit();
}

View File

@@ -21,68 +21,69 @@ import android.os.IBinder;
import at.bitfire.davdroid.ui.setup.LoginActivity;
public class AccountAuthenticatorService extends Service {
private static AccountAuthenticator accountAuthenticator;
private AccountAuthenticator getAuthenticator() {
if (accountAuthenticator != null)
return accountAuthenticator;
return accountAuthenticator = new AccountAuthenticator(this);
}
@Override
public IBinder onBind(Intent intent) {
if (intent.getAction().equals(android.accounts.AccountManager.ACTION_AUTHENTICATOR_INTENT))
return getAuthenticator().getIBinder();
return null;
}
private static class AccountAuthenticator extends AbstractAccountAuthenticator {
final Context context;
public AccountAuthenticator(Context context) {
super(context);
this.context = context;
}
private AccountAuthenticator accountAuthenticator;
@Override
public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType,
String[] requiredFeatures, Bundle options) throws NetworkErrorException {
Intent intent = new Intent(context, LoginActivity.class);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
return bundle;
}
@Override
public void onCreate() {
accountAuthenticator = new AccountAuthenticator(this);
}
@Override
public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) throws NetworkErrorException {
return null;
}
@Override
public IBinder onBind(Intent intent) {
if (intent.getAction().equals(android.accounts.AccountManager.ACTION_AUTHENTICATOR_INTENT))
return accountAuthenticator.getIBinder();
return null;
}
@Override
public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
return null;
}
private static class AccountAuthenticator extends AbstractAccountAuthenticator {
final Context context;
public AccountAuthenticator(Context context) {
super(context);
this.context = context;
}
@Override
public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
return null;
}
public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType,
String[] requiredFeatures, Bundle options) throws NetworkErrorException {
Intent intent = new Intent(context, LoginActivity.class);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
return bundle;
}
@Override
public String getAuthTokenLabel(String authTokenType) {
return null;
}
@Override
public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) throws NetworkErrorException {
return null;
}
@Override
public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) throws NetworkErrorException {
return null;
}
@Override
public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
return null;
}
@Override
public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
return null;
}
}
@Override
public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
return null;
}
@Override
public String getAuthTokenLabel(String authTokenType) {
return null;
}
@Override
public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) throws NetworkErrorException {
return null;
}
@Override
public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
return null;
}
}
}

View File

@@ -53,9 +53,7 @@ public class CalendarsSyncAdapterService extends SyncAdapterService {
}
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
super.onPerformSync(account, extras, authority, provider, syncResult);
public void sync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
try {
AccountSettings settings = new AccountSettings(getContext(), account);
if (!extras.containsKey(ContentResolver.SYNC_EXTRAS_MANUAL) && !checkSyncConditions(settings))

View File

@@ -47,9 +47,7 @@ public class ContactsSyncAdapterService extends SyncAdapterService {
}
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
super.onPerformSync(account, extras, authority, provider, syncResult);
public void sync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
SQLiteOpenHelper dbHelper = new ServiceDB.OpenHelper(getContext());
try {
AccountSettings settings = new AccountSettings(getContext(), account);

View File

@@ -47,6 +47,7 @@ import at.bitfire.dav4android.property.AddressData;
import at.bitfire.dav4android.property.GetCTag;
import at.bitfire.dav4android.property.GetContentType;
import at.bitfire.dav4android.property.GetETag;
import at.bitfire.dav4android.property.ResourceType;
import at.bitfire.dav4android.property.SupportedAddressData;
import at.bitfire.davdroid.AccountSettings;
import at.bitfire.davdroid.App;
@@ -211,12 +212,11 @@ public class ContactsSyncManager extends SyncManager {
currentGroups = contact.getGroupMemberships();
for (Long groupID : SetUtils.disjunction(cachedGroups, currentGroups)) {
App.log.fine("Marking group as dirty: " + groupID);
batch.enqueue(ContentProviderOperation
.newUpdate(addressBook.syncAdapterURI(ContentUris.withAppendedId(Groups.CONTENT_URI, groupID)))
batch.enqueue(new BatchOperation.Operation(
ContentProviderOperation.newUpdate(addressBook.syncAdapterURI(ContentUris.withAppendedId(Groups.CONTENT_URI, groupID)))
.withValue(Groups.DIRTY, 1)
.withYieldAllowed(true)
.build()
);
));
}
} catch(FileNotFoundException ignored) {
}
@@ -270,26 +270,15 @@ public class ContactsSyncManager extends SyncManager {
@Override
protected void listRemote() throws IOException, HttpException, DavException {
// fetch list of remote VCards and build hash table to index file name
try {
davAddressBook().addressbookQuery();
} catch(HttpException e) {
/* non-successful responses to CARDDAV:addressbook-query with empty filter, tested on 2015/10/21
* fastmail.com 403 Forbidden (DAV:error CARDDAV:supported-filter)
* mailbox.org (OpenXchange) 400 Bad Request
* SOGo 207 Multi-status, but without entries http://www.sogo.nu/bugs/view.php?id=3370
* Zimbra ZCS 500 Server Error https://bugzilla.zimbra.com/show_bug.cgi?id=101902
*/
if (e.status == 400 || e.status == 403 || e.status == 500 || e.status == 501) {
App.log.log(Level.WARNING, "Server error on REPORT addressbook-query, falling back to PROPFIND", e);
davAddressBook().propfind(1, GetETag.NAME);
} else
// no defined fallback, pass through exception
throw e;
}
davAddressBook().propfind(1, ResourceType.NAME, GetETag.NAME);
remoteResources = new HashMap<>(davCollection.members.size());
for (DavResource vCard : davCollection.members) {
// ignore member collections
ResourceType type = (ResourceType)vCard.properties.get(ResourceType.NAME);
if (type != null && type.types.contains(ResourceType.COLLECTION))
continue;
String fileName = vCard.fileName();
App.log.fine("Found remote VCard: " + fileName);
remoteResources.put(fileName, vCard);
@@ -495,7 +484,7 @@ public class ContactsSyncManager extends SyncManager {
return null;
}
OkHttpClient resourceClient = HttpClient.create();
OkHttpClient resourceClient = HttpClient.create(context);
// authenticate only against a certain host, and only upon request
resourceClient = HttpClient.addAuthentication(resourceClient, baseUrl.host(), settings.username(), settings.password());

View File

@@ -0,0 +1,11 @@
package at.bitfire.davdroid.syncadapter;
import android.content.Context;
import android.support.annotation.NonNull;
interface ISyncPlugin {
boolean beforeSync(@NonNull Context context);
void afterSync(@NonNull Context context);
}

View File

@@ -28,7 +28,14 @@ import android.os.IBinder;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
//import com.android.vending.billing.IInAppBillingService;
import org.apache.commons.collections4.IteratorUtils;
import java.util.List;
import java.util.ServiceLoader;
import java.util.logging.Level;
import at.bitfire.davdroid.AccountSettings;
@@ -50,16 +57,39 @@ public abstract class SyncAdapterService extends Service {
public static abstract class SyncAdapter extends AbstractThreadedSyncAdapter {
private static final ServiceLoader<ISyncPlugin> syncPluginLoader = ServiceLoader.load(ISyncPlugin.class);
private final List<ISyncPlugin> syncPlugins = IteratorUtils.toList(syncPluginLoader.iterator());
public SyncAdapter(Context context) {
super(context, false);
for (ISyncPlugin plugin : syncPlugins)
App.log.info("Registered sync plugin: " + plugin.getClass().getName());
}
abstract void sync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult);
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
App.log.info("Sync for " + authority + " has been initiated");
// required for dav4android (ServiceLoader)
Thread.currentThread().setContextClassLoader(getContext().getClassLoader());
final Context context = getContext();
Thread.currentThread().setContextClassLoader(context.getClassLoader());
boolean runSync = true;
for (ISyncPlugin plugin : syncPlugins)
if (!plugin.beforeSync(context))
runSync = false;
if (runSync)
sync(account, extras, authority, provider, syncResult);
for (ISyncPlugin plugin : syncPlugins)
plugin.afterSync(context);
App.log.info("Sync for " + authority + " complete");
}
@Override
@@ -72,14 +102,13 @@ public abstract class SyncAdapterService extends Service {
Notification notify = new NotificationCompat.Builder(getContext())
.setSmallIcon(R.drawable.ic_error_light)
.setLargeIcon(((BitmapDrawable)getContext().getResources().getDrawable(R.drawable.ic_launcher)).getBitmap())
.setLargeIcon(App.getLauncherBitmap(getContext()))
.setContentTitle(getContext().getString(R.string.sync_error_permissions))
.setContentText(getContext().getString(R.string.sync_error_permissions_text))
.setContentIntent(PendingIntent.getActivity(getContext(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT))
.setCategory(NotificationCompat.CATEGORY_ERROR)
.setLocalOnly(true)
.build();
NotificationManager nm = (NotificationManager)getContext().getSystemService(NOTIFICATION_SERVICE);
NotificationManagerCompat nm = NotificationManagerCompat.from(getContext());
nm.notify(Constants.NOTIFICATION_PERMISSIONS, notify);
}

View File

@@ -9,15 +9,14 @@ package at.bitfire.davdroid.syncadapter;
import android.accounts.Account;
import android.annotation.TargetApi;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SyncResult;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v7.app.NotificationCompat;
import android.text.TextUtils;
@@ -69,7 +68,7 @@ abstract public class SyncManager {
SYNC_PHASE_POST_PROCESSING = 10,
SYNC_PHASE_SAVE_SYNC_STATE = 11;
protected final NotificationManager notificationManager;
protected final NotificationManagerCompat notificationManager;
protected final String uniqueCollectionId;
protected final Context context;
@@ -113,7 +112,7 @@ abstract public class SyncManager {
// dismiss previous error notifications
this.uniqueCollectionId = uniqueCollectionId;
notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager = NotificationManagerCompat.from(context);
notificationManager.cancel(uniqueCollectionId, notificationId());
}
@@ -230,11 +229,10 @@ abstract public class SyncManager {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder .setSmallIcon(R.drawable.ic_error_light)
.setLargeIcon(((BitmapDrawable)context.getResources().getDrawable(R.drawable.ic_launcher)).getBitmap())
.setLargeIcon(App.getLauncherBitmap(context))
.setContentTitle(getSyncErrorTitle())
.setContentIntent(PendingIntent.getActivity(context, 0, detailsIntent, PendingIntent.FLAG_CANCEL_CURRENT))
.setCategory(NotificationCompat.CATEGORY_ERROR)
.setLocalOnly(true);
.setCategory(NotificationCompat.CATEGORY_ERROR);
try {
String[] phases = context.getResources().getStringArray(R.array.sync_error_phases);

View File

@@ -58,9 +58,7 @@ public class TasksSyncAdapterService extends SyncAdapterService {
}
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient providerClient, SyncResult syncResult) {
super.onPerformSync(account, extras, authority, providerClient, syncResult);
public void sync(Account account, Bundle extras, String authority, ContentProviderClient providerClient, SyncResult syncResult) {
try {
@Cleanup TaskProvider provider = TaskProvider.acquire(getContext().getContentResolver(), TaskProvider.ProviderName.OpenTasks);
if (provider == null)

View File

@@ -65,15 +65,15 @@ public class AboutActivity extends AppCompatActivity {
@RequiredArgsConstructor
private static class ComponentInfo {
final String title, version, website, copyright;
final int licenseInfo;
final Integer licenseInfo;
final String licenseTextFile;
}
private final static ComponentInfo components[] = {
new ComponentInfo(
"DAVdroid", BuildConfig.VERSION_NAME, "https://davdroid.bitfire.at",
null, BuildConfig.VERSION_NAME, "https://davdroid.bitfire.at",
DateFormatUtils.format(BuildConfig.buildTime, "yyyy") + " Ricki Hirner, Bernhard Stockmann (bitfire web engineering)",
R.string.about_license_info_no_warranty, "gpl-3.0-standalone.html"
null, null
), new ComponentInfo(
"AmbilWarna", null, "https://github.com/yukuku/ambilwarna",
"Yuku", R.string.about_license_info_no_warranty, "apache2.html"
@@ -89,9 +89,6 @@ public class AboutActivity extends AppCompatActivity {
), new ComponentInfo(
"ical4j", "2.x", "https://ical4j.github.io/",
"Ben Fortuna", R.string.about_license_info_no_warranty, "bsd-3clause.html"
), new ComponentInfo(
"MemorizingTrustManager", null, "https://github.com/ge0rg/MemorizingTrustManager",
"Georg Lukas", R.string.about_license_info_no_warranty, "mit.html"
), new ComponentInfo(
"OkHttp", null, "https://square.github.io/okhttp/",
"Square, Inc.", R.string.about_license_info_no_warranty, "apache2.html"
@@ -102,7 +99,7 @@ public class AboutActivity extends AppCompatActivity {
};
private static class TabsAdapter extends FragmentPagerAdapter {
private class TabsAdapter extends FragmentPagerAdapter {
public TabsAdapter(FragmentManager fm) {
super(fm);
}
@@ -114,7 +111,7 @@ public class AboutActivity extends AppCompatActivity {
@Override
public CharSequence getPageTitle(int position) {
return components[position].title;
return components[position].title != null ? components[position].title : getString(R.string.app_name);
}
@Override
@@ -145,7 +142,8 @@ public class AboutActivity extends AppCompatActivity {
View v = inflater.inflate(R.layout.about_component, container, false);
TextView tv = (TextView)v.findViewById(R.id.title);
tv.setText(info.title + (info.version != null ? (" " + info.version) : ""));
tv.setText((info.title == null ? getString(R.string.app_name) : info.title) +
(info.version != null ? (" " + info.version) : ""));
tv = (TextView)v.findViewById(R.id.website);
tv.setAutoLinkMask(Linkify.WEB_URLS);
@@ -155,12 +153,20 @@ public class AboutActivity extends AppCompatActivity {
tv.setText("© " + info.copyright);
tv = (TextView)v.findViewById(R.id.license_info);
tv.setText(info.licenseInfo);
if (info.licenseInfo == null)
tv.setVisibility(View.GONE);
else
tv.setText(info.licenseInfo);
// load and format license text
Bundle args = new Bundle(1);
args.putString(KEY_FILE_NAME, info.licenseTextFile);
getLoaderManager().initLoader(0, args, this);
if (info.licenseTextFile == null) {
v.findViewById(R.id.license_header).setVisibility(View.GONE);
v.findViewById(R.id.license_text).setVisibility(View.GONE);
} else {
Bundle args = new Bundle(1);
args.putString(KEY_FILE_NAME, info.licenseTextFile);
getLoaderManager().initLoader(0, args, this);
}
return v;
}

View File

@@ -14,6 +14,7 @@ import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.annotation.TargetApi;
import android.app.LoaderManager;
import android.content.AsyncTaskLoader;
import android.content.ComponentName;
@@ -24,6 +25,7 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.Loader;
import android.content.ServiceConnection;
import android.content.SyncStatusObserver;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
@@ -62,6 +64,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import at.bitfire.cert4android.CustomCertManager;
import at.bitfire.davdroid.App;
import at.bitfire.davdroid.DavService;
import at.bitfire.davdroid.R;
@@ -73,6 +76,8 @@ import at.bitfire.davdroid.model.ServiceDB.Services;
import at.bitfire.ical4android.TaskProvider;
import lombok.Cleanup;
import static android.content.ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE;
public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenuItemClickListener, PopupMenu.OnMenuItemClickListener, LoaderManager.LoaderCallbacks<AccountActivity.AccountInfo> {
public static final String EXTRA_ACCOUNT = "account";
@@ -83,6 +88,7 @@ public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenu
Toolbar tbCardDAV, tbCalDAV;
@Override
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -110,6 +116,22 @@ public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenu
getLoaderManager().initLoader(0, getIntent().getExtras(), this);
}
@Override
protected void onPause() {
super.onPause();
CustomCertManager certManager = ((App)getApplicationContext()).getCertManager();
if (certManager != null)
certManager.appInForeground = false;
}
@Override
protected void onResume() {
super.onResume();
CustomCertManager certManager = ((App)getApplicationContext()).getCertManager();
if (certManager != null)
certManager.appInForeground = true;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_account, menu);
@@ -267,7 +289,7 @@ public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenu
@Override
public Loader<AccountInfo> onCreateLoader(int id, Bundle args) {
return new AccountLoader(this, account.name);
return new AccountLoader(this, account);
}
public void reload() {
@@ -333,19 +355,22 @@ public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenu
}
private static class AccountLoader extends AsyncTaskLoader<AccountInfo> implements DavService.RefreshingStatusListener, ServiceConnection {
private final String accountName;
private static class AccountLoader extends AsyncTaskLoader<AccountInfo> implements DavService.RefreshingStatusListener, ServiceConnection, SyncStatusObserver {
private final Account account;
private final OpenHelper dbHelper;
private DavService.InfoBinder davService;
private Object syncStatusListener;
public AccountLoader(Context context, String accountName) {
public AccountLoader(Context context, Account account) {
super(context);
this.accountName = accountName;
this.account = account;
dbHelper = new OpenHelper(context);
}
@Override
protected void onStartLoading() {
syncStatusListener = ContentResolver.addStatusChangeListener(SYNC_OBSERVER_TYPE_ACTIVE, this);
getContext().bindService(new Intent(getContext(), DavService.class), this, Context.BIND_AUTO_CREATE);
}
@@ -353,6 +378,9 @@ public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenu
protected void onStopLoading() {
davService.removeRefreshingStatusListener(this);
getContext().unbindService(this);
if (syncStatusListener != null)
ContentResolver.removeStatusChangeListener(syncStatusListener);
}
@Override
@@ -373,6 +401,11 @@ public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenu
forceLoad();
}
@Override
public void onStatusChanged(int which) {
forceLoad();
}
@Override
public AccountInfo loadInBackground() {
AccountInfo info = new AccountInfo();
@@ -382,7 +415,7 @@ public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenu
@Cleanup Cursor cursor = db.query(
Services._TABLE,
new String[] { Services.ID, Services.SERVICE },
Services.ACCOUNT_NAME + "=?", new String[] { accountName },
Services.ACCOUNT_NAME + "=?", new String[] { account.name },
null, null, null);
if (cursor.getCount() == 0)
@@ -395,14 +428,16 @@ public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenu
if (Services.SERVICE_CARDDAV.equals(service)) {
info.carddav = new AccountInfo.ServiceInfo();
info.carddav.id = id;
info.carddav.refreshing = davService.isRefreshing(id);
info.carddav.refreshing = davService.isRefreshing(id) || ContentResolver.isSyncActive(account, ContactsContract.AUTHORITY);
info.carddav.hasHomeSets = hasHomeSets(db, id);
info.carddav.collections = readCollections(db, id);
} else if (Services.SERVICE_CALDAV.equals(service)) {
info.caldav = new AccountInfo.ServiceInfo();
info.caldav.id = id;
info.caldav.refreshing = davService.isRefreshing(id);
info.caldav.refreshing = davService.isRefreshing(id) ||
ContentResolver.isSyncActive(account, CalendarContract.AUTHORITY) ||
ContentResolver.isSyncActive(account, TaskProvider.ProviderName.OpenTasks.authority);
info.caldav.hasHomeSets = hasHomeSets(db, id);
info.caldav.collections = readCollections(db, id);
}
@@ -430,6 +465,7 @@ public class AccountActivity extends AppCompatActivity implements Toolbar.OnMenu
}
return collections;
}
}

View File

@@ -11,6 +11,7 @@ package at.bitfire.davdroid.ui;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.OnAccountsUpdateListener;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
@@ -103,8 +104,9 @@ public class AccountListFragment extends ListFragment implements LoaderManager.L
}
@Override
@SuppressLint("MissingPermission")
public Account[] loadInBackground() {
return accountManager.getAccountsByType(Constants.ACCOUNT_TYPE);
return accountManager.getAccountsByType(getContext().getString(R.string.account_type));
}
}

View File

@@ -27,6 +27,7 @@ import java.util.logging.Level;
import at.bitfire.davdroid.AccountSettings;
import at.bitfire.davdroid.App;
import at.bitfire.davdroid.BuildConfig;
import at.bitfire.davdroid.InvalidAccountException;
import at.bitfire.davdroid.R;
import at.bitfire.ical4android.TaskProvider;
@@ -114,17 +115,6 @@ public class AccountSettingsActivity extends AppCompatActivity {
}
});
final SwitchPreferenceCompat prefPreemptive = (SwitchPreferenceCompat)findPreference("preemptive");
prefPreemptive.setChecked(settings.preemptiveAuth());
prefPreemptive.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
settings.preemptiveAuth((Boolean)newValue);
refresh();
return false;
}
});
// category: synchronization
final ListPreference prefSyncContacts = (ListPreference)findPreference("sync_interval_contacts");
final Long syncIntervalContacts = settings.getSyncInterval(ContactsContract.AUTHORITY);
@@ -221,14 +211,17 @@ public class AccountSettingsActivity extends AppCompatActivity {
final SwitchPreferenceCompat prefRFC6868 = (SwitchPreferenceCompat)findPreference("vcard_rfc6868");
if (syncIntervalContacts != null) {
prefRFC6868.setChecked(settings.getVCardRFC6868());
prefRFC6868.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object o) {
settings.setVCardRFC6868((Boolean)o);
refresh();
return false;
}
});
if (BuildConfig.settingVCardRFC6868 == null)
prefRFC6868.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object o) {
settings.setVCardRFC6868((Boolean)o);
refresh();
return false;
}
});
else
prefRFC6868.setEnabled(false);
} else
prefRFC6868.setEnabled(false);
@@ -236,15 +229,18 @@ public class AccountSettingsActivity extends AppCompatActivity {
if (syncIntervalContacts != null) {
prefGroupMethod.setValue(settings.getGroupMethod().name());
prefGroupMethod.setSummary(prefGroupMethod.getEntry());
prefGroupMethod.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object o) {
String name = (String)o;
settings.setGroupMethod(GroupMethod.valueOf(name));
refresh();
return false;
}
});
if (BuildConfig.settingContactGroupMethod == null)
prefGroupMethod.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object o) {
String name = (String)o;
settings.setGroupMethod(GroupMethod.valueOf(name));
refresh();
return false;
}
});
else
prefGroupMethod.setEnabled(false);
} else
prefGroupMethod.setEnabled(false);

View File

@@ -9,8 +9,6 @@
package at.bitfire.davdroid.ui;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.NavigationView;
@@ -23,14 +21,16 @@ import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;
import at.bitfire.davdroid.App;
import at.bitfire.davdroid.BuildConfig;
import at.bitfire.davdroid.Constants;
import java.util.ServiceLoader;
import at.bitfire.davdroid.R;
import at.bitfire.davdroid.ui.setup.LoginActivity;
public class AccountsActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
private static final ServiceLoader<IAccountsDrawerHandler> serviceLoader = ServiceLoader.load(IAccountsDrawerHandler.class);
private static final IAccountsDrawerHandler accountsDrawerHandler = serviceLoader.iterator().next();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -76,34 +76,12 @@ public class AccountsActivity extends AppCompatActivity implements NavigationVie
@Override
public boolean onNavigationItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.nav_about:
startActivity(new Intent(this, AboutActivity.class));
break;
case R.id.nav_app_settings:
startActivity(new Intent(this, AppSettingsActivity.class));
break;
case R.id.nav_twitter:
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://twitter.com/davdroidapp")));
break;
case R.id.nav_website:
startActivity(new Intent(Intent.ACTION_VIEW, Constants.webUri));
break;
case R.id.nav_faq:
startActivity(new Intent(Intent.ACTION_VIEW, Constants.webUri.buildUpon().appendEncodedPath("faq/").build()));
break;
case R.id.nav_forums:
startActivity(new Intent(Intent.ACTION_VIEW, Constants.webUri.buildUpon().appendEncodedPath("forums/").build()));
break;
case R.id.nav_donate:
if (BuildConfig.FLAVOR != App.FLAVOR_GOOGLE_PLAY)
startActivity(new Intent(Intent.ACTION_VIEW, Constants.webUri.buildUpon().appendEncodedPath("donate/").build()));
break;
}
boolean processed = accountsDrawerHandler.onNavigationItemSelected(this, item);
DrawerLayout drawer = (DrawerLayout)findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
return processed;
}
}

View File

@@ -16,15 +16,10 @@ import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceFragmentCompat;
import android.support.v7.preference.SwitchPreferenceCompat;
import java.security.KeyStoreException;
import java.util.Enumeration;
import java.util.logging.Level;
import at.bitfire.davdroid.App;
import at.bitfire.davdroid.R;
import at.bitfire.davdroid.model.ServiceDB;
import at.bitfire.davdroid.model.Settings;
import de.duenndns.ssl.MemorizingTrustManager;
import lombok.Cleanup;
public class AppSettingsActivity extends AppCompatActivity {
@@ -42,19 +37,47 @@ public class AppSettingsActivity extends AppCompatActivity {
public static class SettingsFragment extends PreferenceFragmentCompat {
Preference prefResetHints,
prefResetCertificates;
SwitchPreferenceCompat prefLogToExternalStorage;
ServiceDB.OpenHelper dbHelper;
Settings settings;
Preference
prefResetHints,
prefResetCertificates;
SwitchPreferenceCompat
prefDistrustSystemCerts,
prefLogToExternalStorage;
@Override
public void onCreate(Bundle savedInstanceState) {
dbHelper = new ServiceDB.OpenHelper(getContext());
settings = new Settings(dbHelper.getReadableDatabase());
super.onCreate(savedInstanceState);
}
@Override
public void onDestroy() {
super.onDestroy();
dbHelper.close();
}
@Override
public void onCreatePreferences(Bundle bundle, String s) {
addPreferencesFromResource(R.xml.settings_app);
prefResetHints = findPreference("reset_hints");
prefResetCertificates = findPreference("reset_certificates");
@Cleanup ServiceDB.OpenHelper dbHelper = new ServiceDB.OpenHelper(getContext());
Settings settings = new Settings(dbHelper.getReadableDatabase());
prefDistrustSystemCerts = (SwitchPreferenceCompat)findPreference("distrust_system_certs");
App app = (App)getContext().getApplicationContext();
if (app.getCertManager() == null)
prefDistrustSystemCerts.setVisible(false);
else
prefDistrustSystemCerts.setChecked(settings.getBoolean(App.DISTRUST_SYSTEM_CERTIFICATES, false));
prefResetCertificates = findPreference("reset_certificates");
if (app.getCertManager() == null)
prefResetCertificates.setVisible(false);
prefLogToExternalStorage = (SwitchPreferenceCompat)findPreference("log_to_external_storage");
prefLogToExternalStorage.setChecked(settings.getBoolean(App.LOG_TO_EXTERNAL_STORAGE, false));
}
@@ -63,6 +86,8 @@ public class AppSettingsActivity extends AppCompatActivity {
public boolean onPreferenceTreeClick(Preference preference) {
if (preference == prefResetHints)
resetHints();
else if (preference == prefDistrustSystemCerts)
setDistrustSystemCerts(((SwitchPreferenceCompat)preference).isChecked());
else if (preference == prefResetCertificates)
resetCertificates();
else if (preference == prefLogToExternalStorage)
@@ -73,31 +98,29 @@ public class AppSettingsActivity extends AppCompatActivity {
}
private void resetHints() {
@Cleanup ServiceDB.OpenHelper dbHelper = new ServiceDB.OpenHelper(getContext());
Settings settings = new Settings(dbHelper.getWritableDatabase());
settings.remove(StartupDialogFragment.HINT_BATTERY_OPTIMIZATIONS);
settings.remove(StartupDialogFragment.HINT_GOOGLE_PLAY_ACCOUNTS_REMOVED);
settings.remove(StartupDialogFragment.HINT_OPENTASKS_NOT_INSTALLED);
Snackbar.make(getView(), R.string.app_settings_reset_hints_success, Snackbar.LENGTH_LONG).show();
}
private void resetCertificates() {
MemorizingTrustManager mtm = App.getMemorizingTrustManager();
private void setDistrustSystemCerts(boolean distrust) {
settings.putBoolean(App.DISTRUST_SYSTEM_CERTIFICATES, distrust);
int deleted = 0;
Enumeration<String> iterator = mtm.getCertificates();
while (iterator.hasMoreElements())
try {
mtm.deleteCertificate(iterator.nextElement());
deleted++;
} catch (KeyStoreException e) {
App.log.log(Level.SEVERE, "Couldn't distrust certificate", e);
}
Snackbar.make(getView(), getResources().getQuantityString(R.plurals.app_settings_reset_trusted_certificates_success, deleted, deleted), Snackbar.LENGTH_LONG).show();
// re-initialize certificate manager
App app = (App)getContext().getApplicationContext();
app.reinitCertManager();
// reinitialize certificate manager of :sync process
getContext().sendBroadcast(new Intent(App.ReinitSettingsReceiver.ACTION_REINIT_SETTINGS));
}
private void resetCertificates() {
((App)getContext().getApplicationContext()).getCertManager().resetCertificates();
Snackbar.make(getView(), getString(R.string.app_settings_reset_certificates_success), Snackbar.LENGTH_LONG).show();
}
private void setExternalLogging(boolean externalLogging) {
@Cleanup ServiceDB.OpenHelper dbHelper = new ServiceDB.OpenHelper(getContext());
Settings settings = new Settings(dbHelper.getWritableDatabase());
settings.putBoolean(App.LOG_TO_EXTERNAL_STORAGE, externalLogging);
// reinitialize logger of default process
@@ -105,7 +128,7 @@ public class AppSettingsActivity extends AppCompatActivity {
app.reinitLogger();
// reinitialize logger of :sync process
getContext().sendBroadcast(new Intent("at.bitfire.davdroid.REINIT_LOGGER"));
getContext().sendBroadcast(new Intent(App.ReinitSettingsReceiver.ACTION_REINIT_SETTINGS));
}
}

View File

@@ -10,6 +10,7 @@ package at.bitfire.davdroid.ui;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.annotation.SuppressLint;
import android.app.LoaderManager;
import android.content.AsyncTaskLoader;
import android.content.ContentResolver;
@@ -144,6 +145,7 @@ public class DebugInfoActivity extends AppCompatActivity implements LoaderManage
}
@Override
@SuppressLint("MissingPermission")
public String loadInBackground() {
Throwable throwable = null;
String logs = null,
@@ -195,9 +197,10 @@ public class DebugInfoActivity extends AppCompatActivity implements LoaderManage
workaroundInstalled = pm.getPackageInfo("at.bitfire.davdroid.jbworkaround", 0) != null;
} catch(PackageManager.NameNotFoundException ignored) {}
report.append("\nSOFTWARE INFORMATION\n" +
"DAVdroid version: ").append(BuildConfig.VERSION_NAME).append(" (").append(BuildConfig.VERSION_CODE).append(") ").append(new Date(BuildConfig.buildTime)).append("\n")
.append("Installed from: ").append(installedFrom).append("\n")
.append("JB Workaround installed: ").append(workaroundInstalled ? "yes" : "no").append("\n\n");
"Package: ").append(BuildConfig.APPLICATION_ID).append("\n" +
"Version: ").append(BuildConfig.VERSION_NAME).append(" (").append(BuildConfig.VERSION_CODE).append(") ").append(new Date(BuildConfig.buildTime)).append("\n")
.append("Installed from: ").append(installedFrom).append("\n")
.append("JB Workaround installed: ").append(workaroundInstalled ? "yes" : "no").append("\n\n");
} catch(Exception ex) {
App.log.log(Level.SEVERE, "Couldn't get software information", ex);
}
@@ -206,14 +209,13 @@ public class DebugInfoActivity extends AppCompatActivity implements LoaderManage
"CONFIGURATION\n" +
"System-wide synchronization: ").append(ContentResolver.getMasterSyncAutomatically() ? "automatically" : "manually").append("\n");
AccountManager accountManager = AccountManager.get(getContext());
for (Account acct : accountManager.getAccountsByType(Constants.ACCOUNT_TYPE))
for (Account acct : accountManager.getAccountsByType(getContext().getString(R.string.account_type)))
try {
AccountSettings settings = new AccountSettings(getContext(), acct);
report.append("Account: ").append(acct.name).append("\n" +
" Address book sync. interval: ").append(syncStatus(settings, ContactsContract.AUTHORITY)).append("\n" +
" Calendar sync. interval: ").append(syncStatus(settings, CalendarContract.AUTHORITY)).append("\n" +
" OpenTasks sync. interval: ").append(syncStatus(settings, "org.dmfs.tasks")).append("\n" +
" Preemptive auth: ").append(settings.preemptiveAuth()).append("\n" +
" WiFi only: ").append(settings.getSyncWifiOnly());
if (settings.getSyncWifiOnlySSID() != null)
report.append(", SSID: ").append(settings.getSyncWifiOnlySSID());

View File

@@ -0,0 +1,11 @@
package at.bitfire.davdroid.ui;
import android.app.Activity;
import android.support.annotation.NonNull;
import android.view.MenuItem;
public interface IAccountsDrawerHandler {
public boolean onNavigationItemSelected(@NonNull Activity activity, MenuItem item);
}

View File

@@ -9,12 +9,12 @@
package at.bitfire.davdroid.ui;
import android.Manifest;
import android.app.NotificationManager;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
@@ -63,7 +63,7 @@ public class PermissionsActivity extends AppCompatActivity {
}
if (!noCalendarPermissions && !noContactsPermissions && !noTaskPermissions) {
NotificationManager nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
NotificationManagerCompat nm = NotificationManagerCompat.from(this);
nm.cancel(Constants.NOTIFICATION_PERMISSIONS);
finish();

View File

@@ -8,6 +8,8 @@
package at.bitfire.davdroid.ui;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
@@ -17,6 +19,7 @@ import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.PowerManager;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
@@ -37,14 +40,15 @@ import lombok.Cleanup;
public class StartupDialogFragment extends DialogFragment {
public static final String
HINT_BATTERY_OPTIMIZATIONS = "hint_BatteryOptimizations",
HINT_GOOGLE_PLAY_ACCOUNTS_REMOVED = "hint_GooglePlayAccountsRemoved",
HINT_OPENTASKS_NOT_INSTALLED = "hint_OpenTasksNotInstalled";
private static final String ARGS_MODE = "mode";
enum Mode {
BATTERY_OPTIMIZATIONS,
DEVELOPMENT_VERSION,
FDROID_DONATE,
GOOGLE_PLAY_ACCOUNTS_REMOVED,
OPENTASKS_NOT_INSTALLED
}
@@ -64,17 +68,18 @@ public class StartupDialogFragment extends DialogFragment {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP && // only on Android <5
settings.getBoolean(HINT_GOOGLE_PLAY_ACCOUNTS_REMOVED, true)) // and only when "Don't show again" hasn't been clicked yet
dialogs.add(StartupDialogFragment.instantiate(Mode.GOOGLE_PLAY_ACCOUNTS_REMOVED));
} else {
// other stores
final String installedFrom = installedFrom(context);
if (installedFrom == null || installedFrom.startsWith("org.fdroid"))
dialogs.add(StartupDialogFragment.instantiate(Mode.FDROID_DONATE));
}
}
// battery optimization whitelisting
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && settings.getBoolean(HINT_BATTERY_OPTIMIZATIONS, true)) {
PowerManager powerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
if (!powerManager.isIgnoringBatteryOptimizations(BuildConfig.APPLICATION_ID))
dialogs.add(StartupDialogFragment.instantiate(Mode.BATTERY_OPTIMIZATIONS));
}
// OpenTasks information
if (!LocalTaskList.tasksProviderAvailable(context) &&
settings.getBoolean(HINT_OPENTASKS_NOT_INSTALLED, true))
if (!LocalTaskList.tasksProviderAvailable(context) && settings.getBoolean(HINT_OPENTASKS_NOT_INSTALLED, true))
dialogs.add(StartupDialogFragment.instantiate(Mode.OPENTASKS_NOT_INSTALLED));
Collections.reverse(dialogs);
@@ -91,6 +96,8 @@ public class StartupDialogFragment extends DialogFragment {
@NonNull
@Override
@TargetApi(Build.VERSION_CODES.M)
@SuppressLint("BatteryLife")
public Dialog onCreateDialog(Bundle savedInstanceState) {
setCancelable(false);
@@ -98,9 +105,35 @@ public class StartupDialogFragment extends DialogFragment {
Mode mode = Mode.valueOf(getArguments().getString(ARGS_MODE));
switch (mode) {
case BATTERY_OPTIMIZATIONS:
return new AlertDialog.Builder(getActivity())
.setTitle(R.string.startup_battery_optimization)
.setMessage(R.string.startup_battery_optimization_message)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setNeutralButton(R.string.startup_battery_optimization_disable, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
Uri.parse("package:" + BuildConfig.APPLICATION_ID));
getContext().startActivity(intent);
}
})
.setNegativeButton(R.string.startup_dont_show_again, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Settings settings = new Settings(dbHelper.getWritableDatabase());
settings.putBoolean(HINT_BATTERY_OPTIMIZATIONS, false);
}
})
.create();
case DEVELOPMENT_VERSION:
return new AlertDialog.Builder(getActivity())
.setIcon(R.drawable.ic_launcher)
.setIcon(R.mipmap.ic_launcher)
.setTitle(R.string.startup_development_version)
.setMessage(R.string.startup_development_version_message)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@@ -116,27 +149,6 @@ public class StartupDialogFragment extends DialogFragment {
})
.create();
case FDROID_DONATE:
if (BuildConfig.FLAVOR != App.FLAVOR_GOOGLE_PLAY)
return new AlertDialog.Builder(getActivity())
.setIcon(R.drawable.ic_launcher)
.setTitle(R.string.startup_donate)
.setMessage(R.string.startup_donate_message)
.setPositiveButton(R.string.startup_donate_now, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startActivity(new Intent(Intent.ACTION_VIEW, Constants.webUri.buildUpon().appendEncodedPath("donate/").build()));
}
})
.setNegativeButton(R.string.startup_donate_later, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.create();
else
throw new IllegalArgumentException();
case GOOGLE_PLAY_ACCOUNTS_REMOVED:
Drawable icon = null;
try {

View File

@@ -10,6 +10,7 @@ package at.bitfire.davdroid.ui.setup;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
@@ -32,6 +33,7 @@ import java.util.logging.Level;
import at.bitfire.davdroid.AccountSettings;
import at.bitfire.davdroid.App;
import at.bitfire.davdroid.BuildConfig;
import at.bitfire.davdroid.Constants;
import at.bitfire.davdroid.DavService;
import at.bitfire.davdroid.InvalidAccountException;
@@ -78,11 +80,13 @@ public class AccountDetailsFragment extends Fragment {
DavResourceFinder.Configuration config = (DavResourceFinder.Configuration)getArguments().getSerializable(KEY_CONFIG);
final EditText editName = (EditText)v.findViewById(R.id.account_name);
editName.setText(config.userName);
editName.setText((config.calDAV != null && config.calDAV.email != null) ? config.calDAV.email : config.userName);
// CardDAV-specific
v.findViewById(R.id.carddav).setVisibility(config.cardDAV != null ? View.VISIBLE : View.GONE);
spnrGroupMethod = (Spinner)v.findViewById(R.id.contact_group_method);
if (BuildConfig.settingContactGroupMethod != null)
spnrGroupMethod.setEnabled(false);
Button btnCreate = (Button)v.findViewById(R.id.create_account);
btnCreate.setOnClickListener(new View.OnClickListener() {
@@ -92,9 +96,10 @@ public class AccountDetailsFragment extends Fragment {
if (name.isEmpty())
editName.setError(getString(R.string.login_account_name_required));
else {
if (createAccount(name, (DavResourceFinder.Configuration)getArguments().getSerializable(KEY_CONFIG)))
if (createAccount(name, (DavResourceFinder.Configuration)getArguments().getSerializable(KEY_CONFIG))) {
getActivity().setResult(Activity.RESULT_OK);
getActivity().finish();
else
} else
Snackbar.make(v, R.string.login_account_not_created, Snackbar.LENGTH_LONG).show();
}
}
@@ -104,10 +109,10 @@ public class AccountDetailsFragment extends Fragment {
}
protected boolean createAccount(String accountName, DavResourceFinder.Configuration config) {
Account account = new Account(accountName, Constants.ACCOUNT_TYPE);
Account account = new Account(accountName, getString(R.string.account_type));
// create Android account
Bundle userData = AccountSettings.initialUserData(config.userName, config.preemptive);
Bundle userData = AccountSettings.initialUserData(config.userName);
App.log.log(Level.INFO, "Creating Android account with initial config", new Object[] { account, userData });
AccountManager accountManager = AccountManager.get(getContext());
@@ -157,13 +162,23 @@ public class AccountDetailsFragment extends Fragment {
settings.setSyncInterval(CalendarContract.AUTHORITY, DEFAULT_SYNC_INTERVAL);
// enable task sync, if possible
if (Build.VERSION.SDK_INT >= 23 || LocalTaskList.tasksProviderAvailable(getContext())) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
/* Android >=6, it's possible to gain OpenTasks permissions dynamically, so
* OpenTasks sync will be enabled by default. Setting the sync interval to "manually"
* if OpenTasks is not installed avoids the "sync error" in Android settings / Accounts. */
ContentResolver.setIsSyncable(account, TaskProvider.ProviderName.OpenTasks.authority, 1);
settings.setSyncInterval(TaskProvider.ProviderName.OpenTasks.authority, DEFAULT_SYNC_INTERVAL);
} else
// Android <6 only: disable OpenTasks sync forever when OpenTasks is not installed
// because otherwise, there will be a non-catchable SecurityException as soon as OpenTasks is installed
ContentResolver.setIsSyncable(account, TaskProvider.ProviderName.OpenTasks.authority, 0);
settings.setSyncInterval(TaskProvider.ProviderName.OpenTasks.authority,
LocalTaskList.tasksProviderAvailable(getContext()) ? DEFAULT_SYNC_INTERVAL : AccountSettings.SYNC_INTERVAL_MANUALLY);
} else {
// Android <6: enable task sync according to whether OpenTasks is accessible
if (LocalTaskList.tasksProviderAvailable(getContext())) {
ContentResolver.setIsSyncable(account, TaskProvider.ProviderName.OpenTasks.authority, 1);
settings.setSyncInterval(TaskProvider.ProviderName.OpenTasks.authority, DEFAULT_SYNC_INTERVAL);
} else
// Android <6 only: disable OpenTasks sync forever when OpenTasks is not installed
// because otherwise, there will be a non-catchable SecurityException as soon as OpenTasks is installed
ContentResolver.setIsSyncable(account, TaskProvider.ProviderName.OpenTasks.authority, 0);
}
} else {
// disable calendar and task sync when CalDAV is not available
ContentResolver.setIsSyncable(account, CalendarContract.AUTHORITY, 0);

View File

@@ -19,6 +19,7 @@ import org.xbill.DNS.Type;
import java.io.IOException;
import java.io.Serializable;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
@@ -28,6 +29,7 @@ import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import at.bitfire.dav4android.Constants;
import at.bitfire.dav4android.DavResource;
import at.bitfire.dav4android.UrlUtils;
import at.bitfire.dav4android.exception.DavException;
@@ -39,6 +41,7 @@ import at.bitfire.dav4android.property.CalendarColor;
import at.bitfire.dav4android.property.CalendarDescription;
import at.bitfire.dav4android.property.CalendarHomeSet;
import at.bitfire.dav4android.property.CalendarTimezone;
import at.bitfire.dav4android.property.CalendarUserAddressSet;
import at.bitfire.dav4android.property.CurrentUserPrincipal;
import at.bitfire.dav4android.property.CurrentUserPrivilegeSet;
import at.bitfire.dav4android.property.DisplayName;
@@ -77,8 +80,8 @@ public class DavResourceFinder {
log.setLevel(Level.FINEST);
log.addHandler(logBuffer);
httpClient = HttpClient.create(log);
httpClient = HttpClient.addAuthentication(httpClient, credentials.userName, credentials.password, credentials.authPreemptive);
httpClient = HttpClient.create(context, log);
httpClient = HttpClient.addAuthentication(httpClient, credentials.userName, credentials.password);
}
@@ -88,7 +91,7 @@ public class DavResourceFinder {
calDavConfig = findInitialConfiguration(Service.CALDAV);
return new Configuration(
credentials.userName, credentials.password, credentials.authPreemptive,
credentials.userName, credentials.password,
cardDavConfig, calDavConfig,
logBuffer.toString()
);
@@ -140,6 +143,26 @@ public class DavResourceFinder {
}
}
if (config.principal != null && service == Service.CALDAV) {
// query email address (CalDAV scheduling: calendar-user-address-set)
DavResource davPrincipal = new DavResource(httpClient, HttpUrl.get(config.principal), log);
try {
davPrincipal.propfind(0, CalendarUserAddressSet.NAME);
CalendarUserAddressSet addressSet = (CalendarUserAddressSet)davPrincipal.properties.get(CalendarUserAddressSet.NAME);
if (addressSet != null)
for (String href : addressSet.hrefs)
try {
URI uri = new URI(href);
if ("mailto".equals(uri.getScheme()))
config.email = uri.getSchemeSpecificPart();
} catch(URISyntaxException e) {
Constants.log.log(Level.WARNING, "Unparseable user address", e);
}
} catch(IOException | HttpException | DavException e) {
Constants.log.log(Level.WARNING, "Couldn't query user email address", e);
}
}
// return config or null if config doesn't contain useful information
boolean serviceAvailable = config.principal != null || !config.homeSets.isEmpty() || !config.collections.isEmpty();
return serviceAvailable ? config : null;
@@ -368,10 +391,11 @@ public class DavResourceFinder {
public URI principal;
public final Set<URI> homeSets = new HashSet<>();
public final Map<URI, CollectionInfo> collections = new HashMap<>();
public String email;
}
public final String userName, password;
public final boolean preemptive;
public final ServiceInfo cardDAV;
public final ServiceInfo calDAV;

View File

@@ -0,0 +1,9 @@
package at.bitfire.davdroid.ui.setup;
import android.support.v4.app.Fragment;
public interface ILoginCredentialsFragment {
Fragment getFragment();
}

View File

@@ -14,23 +14,70 @@ import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import java.util.ServiceLoader;
import at.bitfire.davdroid.App;
import at.bitfire.davdroid.Constants;
import at.bitfire.davdroid.R;
/**
* Activity to initially connect to a server and create an account.
* Fields for server/user data can be pre-filled with extras in the Intent.
*/
public class LoginActivity extends AppCompatActivity {
/**
* When set, "login by URL" will be activated by default, and the URL field will be set to this value.
* When not set, "login by email" will be activated by default.
*/
public static final String EXTRA_URL = "url";
/**
* When set, and {@link #EXTRA_PASSWORD} is set too, the user name field will be set to this value.
* When set, and {@link #EXTRA_URL} is not set, the email address field will be set to this value.
*/
public static final String EXTRA_USERNAME = "username";
/**
* When set, the password field will be set to this value.
*/
public static final String EXTRA_PASSWORD = "password";
private static final ServiceLoader<ILoginCredentialsFragment> loginFragmentLoader = ServiceLoader.load(ILoginCredentialsFragment.class);
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null)
// first call, add fragment
getSupportFragmentManager().beginTransaction()
.replace(android.R.id.content, new LoginCredentialsFragment())
.commit();
for (ILoginCredentialsFragment fragment : loginFragmentLoader)
getSupportFragmentManager().beginTransaction()
.replace(android.R.id.content, fragment.getFragment())
.commit();
}
@Override
protected void onResume() {
super.onResume();
App app = (App)getApplicationContext();
if (app.getCertManager() != null)
app.getCertManager().appInForeground = true;
}
@Override
protected void onPause() {
super.onPause();
App app = (App)getApplicationContext();
if (app.getCertManager() != null)
app.getCertManager().appInForeground = false;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_login, menu);

View File

@@ -19,7 +19,6 @@ import lombok.RequiredArgsConstructor;
public class LoginCredentials implements Parcelable {
public final URI uri;
public final String userName, password;
public final boolean authPreemptive;
@Override
public int describeContents() {
@@ -31,7 +30,6 @@ public class LoginCredentials implements Parcelable {
dest.writeSerializable(uri);
dest.writeString(userName);
dest.writeString(password);
dest.writeValue(authPreemptive);
}
public static final Creator CREATOR = new Creator<LoginCredentials>() {
@@ -39,8 +37,7 @@ public class LoginCredentials implements Parcelable {
public LoginCredentials createFromParcel(Parcel source) {
return new LoginCredentials(
(URI)source.readSerializable(),
source.readString(), source.readString(),
(boolean)source.readValue(null)
source.readString(), source.readString()
);
}

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -1,17 +0,0 @@
<!--
~ Copyright © 2013 2016 Ricki Hirner (bitfire web engineering).
~ All rights reserved. This program and the accompanying materials
~ are made available under the terms of the GNU Public License v3.0
~ which accompanies this distribution, and is available at
~ http://www.gnu.org/licenses/gpl.html
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M23,12l-2.44,-2.78 0.34,-3.68 -3.61,-0.82 -1.89,-3.18L12,3 8.6,1.54 6.71,4.72l-3.61,0.81 0.34,3.68L1,12l2.44,2.78 -0.34,3.69 3.61,0.82 1.89,3.18L12,21l3.4,1.46 1.89,-3.18 3.61,-0.82 -0.34,-3.68L23,12zm-10,5h-2v-2h2v2zm0,-4h-2V7h2v6z"/>
</vector>

View File

@@ -1,16 +0,0 @@
<!--
~ Copyright © 2013 2016 Ricki Hirner (bitfire web engineering).
~ All rights reserved. This program and the accompanying materials
~ are made available under the terms of the GNU Public License v3.0
~ which accompanies this distribution, and is available at
~ http://www.gnu.org/licenses/gpl.html
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="135"
android:endColor="@color/light_green300"
android:startColor="@color/green700"
android:type="linear"/>
</shape>

View File

@@ -51,6 +51,7 @@
android:layout_marginBottom="32dp"/>
<TextView
android:id="@+id/license_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/TextView.Heading"

View File

@@ -34,7 +34,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:textAppearance="@style/TextAppearance.AppCompat.Title"
android:textColor="@color/white"
android:textColor="@android:color/white"
tools:text="Account Name"/>
</LinearLayout>

View File

@@ -20,11 +20,10 @@
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
app:theme="@style/ThemeOverlay.AppCompat.ActionBar"
android:theme="@style/AppTheme.ActionBar"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"/>
android:layout_height="?attr/actionBarSize"/>
</android.support.design.widget.AppBarLayout>

View File

@@ -17,7 +17,7 @@
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:theme="@style/ThemeOverlay.AppCompat.ActionBar">
android:theme="@style/ThemeOverlay.AppCompat.ActionBar">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
@@ -26,7 +26,7 @@
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
style="@style/tablayout"
app:tabMode="scrollable"
android:layout_width="match_parent"

View File

@@ -39,7 +39,7 @@
android:theme="@style/toolbar_theme"
style="@style/toolbar_style"
app:navigationIcon="@drawable/ic_people_light"
app:title="CardDAV"
app:title="@string/account_carddav"
android:elevation="2dp" tools:ignore="UnusedAttribute"/>
<ProgressBar
@@ -79,7 +79,7 @@
android:theme="@style/toolbar_theme"
style="@style/toolbar_style"
app:navigationIcon="@drawable/ic_event_light"
app:title="CalDAV"
app:title="@string/account_caldav"
android:elevation="2dp" tools:ignore="UnusedAttribute"/>
<ProgressBar

View File

@@ -16,6 +16,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:typeface="monospace"
android:inputType="textPassword"/>
<CheckBox

View File

@@ -10,8 +10,8 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="@dimen/nav_header_height"
android:background="@drawable/side_nav_bar"
android:layout_height="wrap_content"
android:background="@color/grey700"
android:gravity="bottom"
android:orientation="vertical"
android:padding="@dimen/activity_margin"
@@ -21,14 +21,14 @@
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="@dimen/nav_header_vertical_spacing"
android:src="@drawable/ic_launcher"
android:layout_marginTop="24dp"
android:src="@mipmap/ic_launcher"
tools:ignore="ContentDescription"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/nav_header_vertical_spacing"
android:layout_marginTop="@dimen/nav_header_vertical_spacing"
android:text="@string/app_name"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>

View File

@@ -11,12 +11,12 @@
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/sync_now"
android:icon="@drawable/ic_sync_dark"
android:icon="@drawable/ic_sync_action"
android:title="@string/account_synchronize_now"
app:showAsAction="ifRoom"/>
<item android:id="@+id/settings"
android:icon="@drawable/ic_settings_dark"
android:icon="@drawable/ic_settings_action"
android:title="@string/account_settings"
app:showAsAction="ifRoom"/>

View File

@@ -16,7 +16,7 @@
android:title="@string/navigation_drawer_about"/>
<item
android:id="@+id/nav_app_settings"
android:icon="@drawable/ic_settings_dark"
android:icon="@drawable/ic_settings_action"
android:title="@string/navigation_drawer_settings"/>
<item android:title="@string/navigation_drawer_news_updates">
@@ -37,7 +37,7 @@
android:title="@string/navigation_drawer_website"/>
<item
android:id="@+id/nav_faq"
android:icon="@drawable/ic_help_dark"
android:icon="@drawable/ic_help_action"
android:title="@string/navigation_drawer_faq"/>
<item
android:id="@+id/nav_forums"

View File

@@ -11,7 +11,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:icon="@drawable/ic_share_dark"
android:icon="@drawable/ic_share_action"
android:title="@string/send"
app:showAsAction="always"
android:onClick="onShare"/>

View File

@@ -13,7 +13,7 @@
<item
android:id="@+id/help"
android:title="@string/help"
android:icon="@drawable/ic_help_dark"
android:icon="@drawable/ic_help_action"
app:showAsAction="always"
android:onClick="showHelp">
</item>

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@@ -7,6 +7,9 @@
<string name="please_wait">Bitte warten …</string>
<string name="send">Senden</string>
<!--startup dialogs-->
<string name="startup_battery_optimization">Akku-Leistungsoptimierung</string>
<string name="startup_battery_optimization_message">Android kann die DAVdroid-Synchronisierung in ein paar Tagen reduzieren/deaktivieren. Um dies zu verhindern, muss die Akku-Leistungsoptimierung deaktiviert werden.</string>
<string name="startup_battery_optimization_disable">Für DAVdroid deaktivieren</string>
<string name="startup_dont_show_again">Nicht mehr anzeigen</string>
<string name="startup_development_version">DAVdroid Vorab-Version</string>
<string name="startup_development_version_message">Dies ist eine Vorschauversion von DAVdroid. Mit konstruktiven Rückmeldungen und Vorschlägen können Sie uns helfen, DAVdroid zu verbessern.</string>
@@ -54,12 +57,12 @@
<string name="app_settings_reset_hints_summary">Hinweise, die deaktiviert wurden, wieder anzeigen</string>
<string name="app_settings_reset_hints_success">Alle Hinweise werden wieder angezeigt</string>
<string name="app_settings_security">Sicherheit</string>
<string name="app_settings_reset_trusted_certificates">Vertrauenswürdige Zertifikate zurücksetzen</string>
<string name="app_settings_reset_trusted_certificates_summary">Entzieht allen zuvor akzeptierten Zertifikaten die Vertrauenswürdigkeit</string>
<plurals name="app_settings_reset_trusted_certificates_success">
<item quantity="one">Dem Zertifikat wird nicht mehr vertraut</item>
<item quantity="other">%d Zertifikaten wird nicht mehr vertraut</item>
</plurals>
<string name="app_settings_distrust_system_certs">Systemzertifikaten nicht vertrauen</string>
<string name="app_settings_distrust_system_certs_on">System- und installierten CAs wird nicht vertraut</string>
<string name="app_settings_distrust_system_certs_off">System- und installierten CAs wird vertraut (empfohlen)</string>
<string name="app_settings_reset_certificates">Zertifikat-Vertrauen zurücksetzen</string>
<string name="app_settings_reset_certificates_summary">Setzt angenommene/abgelehnte Zertifikate zurück</string>
<string name="app_settings_reset_certificates_success">Alle Informationen über angenommene/abgelehnte Zertifikate wurden zurückgesetzt</string>
<string name="app_settings_debug">Fehlersuche</string>
<string name="app_settings_log_to_external_storage">Protokollierung in externe Datei</string>
<string name="app_settings_log_to_external_storage_on">Protokolliert auf externen Speicher, falls möglich</string>
@@ -101,7 +104,6 @@
<string name="login_user_name">Benutzername</string>
<string name="login_user_name_required">Benutzername wird benötigt</string>
<string name="login_base_url">Basis-URL</string>
<string name="login_auth_preemptive">Präemptive Authentifizierung (empfohlen, aber nicht kompatibel mit Digest-Auth.)</string>
<string name="login_login">Anmelden</string>
<string name="login_back">Zurück</string>
<string name="login_create_account">Konto anlegen</string>
@@ -122,9 +124,6 @@
<string name="settings_password">Passwort</string>
<string name="settings_password_summary">Aktualisieren Sie Ihr Passwort gemäß den Server-Einstellungen.</string>
<string name="settings_enter_password">Passwort eingeben:</string>
<string name="settings_preemptive">Präemptive Authentifizierung</string>
<string name="settings_preemptive_on">Anmeldeinformationen werden bei jeder Anfrage gesendet (empfohlen)</string>
<string name="settings_preemptive_off">Anmeldeinformationen werden nur auf Anforderung gesendet</string>
<string name="settings_sync">Synchronisierung</string>
<string name="settings_sync_interval_contacts">Häufigkeit der Kontakte-Synchronisierung</string>
<string name="settings_sync_summary_manually">Nur manuell</string>
@@ -237,4 +236,7 @@
<item>Speichern des Synchronisierungzustands</item>
</string-array>
<string name="sync_error_unauthorized">Benutzername/Passwort falsch</string>
<!--cert4android-->
<string name="certificate_notification_connection_security">DAVdroid: Verbindungssicherheit</string>
<string name="trust_certificate_unknown_certificate_found">DAVdroid ist auf ein unbekanntes Zertifikat gestoßen. Ist dieses vertrauenswürdig?</string>
</resources>

View File

@@ -9,8 +9,6 @@
<resources>
<!-- AddAccountActivity -->
<style name="account_list_card">
<item name="android:layout_width">600dp</item>
</style>

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