diff --git a/.travis.yml b/.travis.yml
index 0f3376e76..8c0af5731 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,10 +3,10 @@ android:
components:
- platform-tools
- tools
- - build-tools-25.0.0
+ - build-tools-25.0.1
- extra-google-m2repository
- extra-android-m2repository
- - android-23
+ - android-25
- sys-img-x86-android-18
jdk:
# - openjdk8 # not yet available
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9a92b105d..16e64137f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,8 @@
# Wikimedia Commons for Android
+##v2.0.2
+- Make "View in browser" direct to mobile website
+
##v2.0.1
- Disabled minify again (reenabling test failed)
- Hotfix for ShareAction bug
diff --git a/README.md b/README.md
index 6293a332e..687b53ebb 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,13 @@
-# Wikimedia Commons Android app
+# Wikimedia Commons Android app [](https://travis-ci.org/commons-app/apps-android-commons)
The Wikimedia Commons Android app allows users to upload pictures from their Android phone/tablet to Wikimedia Commons. Download the app [here][8], or view our [website][9].
Initially started by the Wikimedia Foundation, this app is now maintained by volunteers. Anyone is welcome to improve it, just choose among the [open issues](https://github.com/commons-app/apps-android-commons/issues) and send us a pull request :-)
-[](https://travis-ci.org/commons-app/apps-android-commons)
+
+
+
+
## Develop with Android Studio or IntelliJ ##
diff --git a/app/build.gradle b/app/build.gradle
index f9fdff800..20e337c69 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -12,30 +12,24 @@ dependencies {
compile 'ch.acra:acra:4.7.0'
compile 'org.mediawiki:api:1.3'
compile 'commons-codec:commons-codec:1.10'
- compile 'com.android.support:support-v4:25.0.0'
- compile 'com.android.support:appcompat-v7:25.0.0'
- compile 'com.android.support:design:25.0.0'
+ compile "com.android.support:support-v4:${project.supportLibVersion}"
+ compile "com.android.support:appcompat-v7:${project.supportLibVersion}"
+ compile "com.android.support:design:${project.supportLibVersion}"
+ compile 'com.google.code.gson:gson:2.7'
testCompile 'junit:junit:4.12'
-
- //noinspection GradleDependency - old version has required feature
- compile 'com.google.code.gson:gson:1.4'
}
android {
- compileSdkVersion 23
- buildToolsVersion '25'
+ compileSdkVersion project.compileSdkVersion
+ buildToolsVersion project.buildToolsVersion
- useLibrary 'org.apache.http.legacy'
+ useLibrary 'org.apache.http.legacy'
defaultConfig {
- applicationId "fr.free.nrw.commons"
- minSdkVersion 15
- targetSdkVersion 23
-
- ndk {
- moduleName "libtranscode"
- }
+ applicationId 'fr.free.nrw.commons'
+ minSdkVersion project.minSdkVersion
+ targetSdkVersion project.targetSdkVersion
}
buildTypes {
@@ -50,4 +44,4 @@ android {
disable 'ExtraTranslation'
abortOnError false
}
-}
+}
\ No newline at end of file
diff --git a/app/src/debug/res/values/placeholder_strings.xml b/app/src/debug/res/values/placeholder_strings.xml
new file mode 100644
index 000000000..dd7a60b20
--- /dev/null
+++ b/app/src/debug/res/values/placeholder_strings.xml
@@ -0,0 +1,6 @@
+
+
+ Overlay
+ Name
+ Description
+
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1ae84b242..9fea24db7 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,7 +1,8 @@
+ android:versionCode="65"
+ android:versionName="2.0.2" >
@@ -85,7 +86,7 @@
+ android:parentActivityName=".contributions.ContributionsActivity" />
diff --git a/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java b/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java
index 44bdf0336..916ea38cd 100644
--- a/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java
+++ b/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java
@@ -59,6 +59,7 @@ public class CommonsApplication extends Application {
public static final String API_URL = "https://commons.wikimedia.org/w/api.php";
public static final String IMAGE_URL_BASE = "https://upload.wikimedia.org/wikipedia/commons";
public static final String HOME_URL = "https://commons.wikimedia.org/wiki/";
+ public static final String MOBILE_HOME_URL = "https://commons.m.wikimedia.org/wiki/";
public static final String EVENTLOG_URL = "https://www.wikimedia.org/beacon/event";
public static final String EVENTLOG_WIKI = "commonswiki";
diff --git a/app/src/main/java/fr/free/nrw/commons/LicenseList.java b/app/src/main/java/fr/free/nrw/commons/LicenseList.java
index 9c791109e..0ef067496 100644
--- a/app/src/main/java/fr/free/nrw/commons/LicenseList.java
+++ b/app/src/main/java/fr/free/nrw/commons/LicenseList.java
@@ -7,6 +7,7 @@ import org.xmlpull.v1.XmlPullParser;
import java.util.Collection;
import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -54,7 +55,7 @@ public class LicenseList {
public String nameIdForTemplate(String template) {
// hack :D (converts dashes and periods to underscores)
// cc-by-sa-3.0 -> cc_by_sa_3_0
- return "license_name_" + template.toLowerCase().replace("-", "_").replace(".", "_");
+ return "license_name_" + template.toLowerCase(Locale.ENGLISH).replace("-", "_").replace(".", "_");
}
private int stringIdByName(String stringId) {
diff --git a/app/src/main/java/fr/free/nrw/commons/Media.java b/app/src/main/java/fr/free/nrw/commons/Media.java
index 366844a27..924427cef 100644
--- a/app/src/main/java/fr/free/nrw/commons/Media.java
+++ b/app/src/main/java/fr/free/nrw/commons/Media.java
@@ -61,6 +61,10 @@ public class Media implements Parcelable {
return CommonsApplication.HOME_URL + "File:" + Utils.urlEncode(getFilename().replace("File:", "").replace(" ", "_"));
}
+ public String getMobileDescriptionUrl() {
+ return CommonsApplication.MOBILE_HOME_URL + "File:" + Utils.urlEncode(getFilename().replace("File:", "").replace(" ", "_"));
+ }
+
public Uri getLocalUri() {
return localUri;
}
diff --git a/app/src/main/java/fr/free/nrw/commons/Utils.java b/app/src/main/java/fr/free/nrw/commons/Utils.java
index f07d5c8bd..9d93a8834 100644
--- a/app/src/main/java/fr/free/nrw/commons/Utils.java
+++ b/app/src/main/java/fr/free/nrw/commons/Utils.java
@@ -27,6 +27,7 @@ import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.Locale;
import java.util.TimeZone;
import java.util.concurrent.Executor;
import java.util.regex.Pattern;
@@ -81,7 +82,7 @@ public class Utils {
}
public static Date parseMWDate(String mwDate) {
- SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); // Assuming MW always gives me UTC
+ SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH); // Assuming MW always gives me UTC
try {
return isoFormat.parse(mwDate);
} catch (ParseException e) {
@@ -90,7 +91,7 @@ public class Utils {
}
public static String toMWDate(Date date) {
- SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); // Assuming MW always gives me UTC
+ SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH); // Assuming MW always gives me UTC
isoFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
return isoFormat.format(date);
}
@@ -201,7 +202,7 @@ public class Utils {
}
public static String capitalize(String string) {
- return string.substring(0,1).toUpperCase() + string.substring(1);
+ return string.substring(0,1).toUpperCase(Locale.getDefault()) + string.substring(1);
}
public static String licenseTemplateFor(String license) {
@@ -303,13 +304,17 @@ public class Utils {
Pattern jpegPattern = Pattern.compile("\\.jpeg$", Pattern.CASE_INSENSITIVE);
// People are used to ".jpg" more than ".jpeg" which the system gives us.
- if (extension != null && extension.toLowerCase().equals("jpeg")) {
+ if (extension != null && extension.toLowerCase(Locale.ENGLISH).equals("jpeg")) {
extension = "jpg";
}
title = jpegPattern.matcher(title).replaceFirst(".jpg");
- if (extension != null && !title.toLowerCase().endsWith("." + extension.toLowerCase())) {
+ if (extension != null && !title.toLowerCase(Locale.getDefault()).endsWith("." + extension.toLowerCase(Locale.ENGLISH))) {
title += "." + extension;
}
return title;
}
+
+ public static boolean isNullOrWhiteSpace(String value) {
+ return value == null || value.trim().isEmpty();
+ }
}
diff --git a/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java b/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java
index 2726c38b3..f5eccf6fb 100644
--- a/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java
+++ b/app/src/main/java/fr/free/nrw/commons/auth/AuthenticatedActivity.java
@@ -1,12 +1,16 @@
package fr.free.nrw.commons.auth;
+import android.Manifest;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
+import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import java.io.IOException;
@@ -20,23 +24,24 @@ public abstract class AuthenticatedActivity extends AppCompatActivity {
CommonsApplication app;
private String authCookie;
-
+
public AuthenticatedActivity(String accountType) {
- this.accountType = accountType;
+ this.accountType = accountType;
}
-
+
private class GetAuthCookieTask extends AsyncTask {
private Account account;
private AccountManager accountManager;
+
public GetAuthCookieTask(Account account, AccountManager accountManager) {
this.account = account;
this.accountManager = accountManager;
}
-
+
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
- if(result != null) {
+ if (result != null) {
authCookie = result;
onAuthCookieAcquired(result);
} else {
@@ -60,19 +65,19 @@ public abstract class AuthenticatedActivity extends AppCompatActivity {
}
}
}
-
+
private class AddAccountTask extends AsyncTask {
private AccountManager accountManager;
+
public AddAccountTask(AccountManager accountManager) {
this.accountManager = accountManager;
}
-
+
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
- if(result != null) {
- Account[] allAccounts =accountManager.getAccountsByType(accountType);
- Account curAccount = allAccounts[0];
+ if (result != null) {
+ Account curAccount = getCurrentAccount();
GetAuthCookieTask getCookieTask = new GetAuthCookieTask(curAccount, accountManager);
getCookieTask.execute();
} else {
@@ -80,6 +85,18 @@ public abstract class AuthenticatedActivity extends AppCompatActivity {
}
}
+ @Nullable
+ private Account getCurrentAccount() {
+ if (ActivityCompat.checkSelfPermission(AuthenticatedActivity.this, Manifest.permission.GET_ACCOUNTS) != PackageManager.PERMISSION_GRANTED) {
+ return null;
+ }
+ Account[] allAccounts = accountManager.getAccountsByType(accountType);
+ if (allAccounts == null) {
+ return null;
+ }
+ return allAccounts[0];
+ }
+
@Override
protected String doInBackground(Void... params) {
AccountManagerFuture resultFuture = accountManager.addAccount(accountType, null, null, null, AuthenticatedActivity.this, null, null);
diff --git a/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java b/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java
index 3dbe7377d..9b76fb627 100644
--- a/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java
+++ b/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java
@@ -26,10 +26,12 @@ import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
+import java.util.Locale;
import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.EventLog;
import fr.free.nrw.commons.R;
+import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.WelcomeActivity;
import fr.free.nrw.commons.contributions.ContributionsActivity;
import fr.free.nrw.commons.contributions.ContributionsContentProvider;
@@ -220,7 +222,7 @@ public class LoginActivity extends AccountAuthenticatorActivity {
private void performLogin() {
String username = usernameEdit.getText().toString();
// Because Mediawiki is upercase-first-char-then-case-sensitive :)
- String canonicalUsername = username.substring(0,1).toUpperCase() + username.substring(1);
+ String canonicalUsername = Utils.capitalize(username.substring(0,1)) + username.substring(1);
String password = passwordEdit.getText().toString();
diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/Contribution.java b/app/src/main/java/fr/free/nrw/commons/contributions/Contribution.java
index 3d9776129..482a4df7f 100644
--- a/app/src/main/java/fr/free/nrw/commons/contributions/Contribution.java
+++ b/app/src/main/java/fr/free/nrw/commons/contributions/Contribution.java
@@ -11,6 +11,7 @@ import android.text.TextUtils;
import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.Locale;
import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.EventLog;
@@ -131,7 +132,7 @@ public class Contribution extends Media {
public String getPageContents() {
StringBuffer buffer = new StringBuffer();
- SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd");
+ SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
buffer
.append("== {{int:filedesc}} ==\n")
diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java
index ffe93edc6..9adbdb882 100644
--- a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java
+++ b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java
@@ -143,7 +143,7 @@ public class MediaDetailPagerFragment extends Fragment implements ViewPager.OnPa
// View in browser
Intent viewIntent = new Intent();
viewIntent.setAction(Intent.ACTION_VIEW);
- viewIntent.setData(Uri.parse(m.getDescriptionUrl()));
+ viewIntent.setData(Uri.parse(m.getMobileDescriptionUrl()));
startActivity(viewIntent);
return true;
case R.id.menu_download_current_image:
diff --git a/app/src/main/java/fr/free/nrw/commons/modifications/ModificationsSyncAdapter.java b/app/src/main/java/fr/free/nrw/commons/modifications/ModificationsSyncAdapter.java
index e91b52a93..b17162705 100644
--- a/app/src/main/java/fr/free/nrw/commons/modifications/ModificationsSyncAdapter.java
+++ b/app/src/main/java/fr/free/nrw/commons/modifications/ModificationsSyncAdapter.java
@@ -49,13 +49,16 @@ public class ModificationsSyncAdapter extends AbstractThreadedSyncAdapter {
String authCookie;
try {
authCookie = AccountManager.get(getContext()).blockingGetAuthToken(account, "", false);
- } catch (OperationCanceledException e) {
+ } catch (OperationCanceledException | AuthenticatorException e) {
throw new RuntimeException(e);
} catch (IOException e) {
Log.d("Commons", "Could not authenticate :(");
return;
- } catch (AuthenticatorException e) {
- throw new RuntimeException(e);
+ }
+
+ if(Utils.isNullOrWhiteSpace(authCookie)) {
+ Log.d("Commons", "Could not authenticate :(");
+ return;
}
MWApi api = CommonsApplication.createMWApi();
diff --git a/app/src/main/java/fr/free/nrw/commons/upload/SingleUploadFragment.java b/app/src/main/java/fr/free/nrw/commons/upload/SingleUploadFragment.java
index 64a969933..5f4ff14d6 100644
--- a/app/src/main/java/fr/free/nrw/commons/upload/SingleUploadFragment.java
+++ b/app/src/main/java/fr/free/nrw/commons/upload/SingleUploadFragment.java
@@ -130,7 +130,7 @@ public class SingleUploadFragment extends Fragment {
setLicenseSummary(license);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(Prefs.DEFAULT_LICENSE, license);
- editor.commit();
+ editor.apply();
}
@Override
diff --git a/app/src/main/res/layout-land/welcome_final.xml b/app/src/main/res/layout-land/welcome_final.xml
index e6277bf49..62d2a9e00 100644
--- a/app/src/main/res/layout-land/welcome_final.xml
+++ b/app/src/main/res/layout-land/welcome_final.xml
@@ -41,8 +41,7 @@
android:textStyle="bold"
android:textAlignment="center"
android:gravity="center_horizontal"
- android:textColor="@android:color/white"
- android:singleLine="false"/>
+ android:textColor="@android:color/white"/>