First baby steps into the world of dependency injection using Dagger.

This commit is contained in:
Paul Hawke 2017-08-25 00:57:17 -05:00
parent 04f676c320
commit 8fe2816ca9
32 changed files with 351 additions and 115 deletions

View file

@ -55,6 +55,7 @@ dependencies {
compile 'com.google.dagger:dagger:2.11' compile 'com.google.dagger:dagger:2.11'
compile 'com.google.dagger:dagger-android-support:2.11' compile 'com.google.dagger:dagger-android-support:2.11'
annotationProcessor 'com.google.dagger:dagger-compiler:2.11' annotationProcessor 'com.google.dagger:dagger-compiler:2.11'
annotationProcessor 'com.google.dagger:dagger-android-processor:2.11'
} }
android { android {

View file

@ -4,7 +4,9 @@ import android.accounts.Account;
import android.accounts.AccountManager; import android.accounts.AccountManager;
import android.accounts.AuthenticatorException; import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException; import android.accounts.OperationCanceledException;
import android.app.Activity;
import android.app.Application; import android.app.Application;
import android.content.ContentProvider;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
@ -23,11 +25,21 @@ import org.acra.annotation.ReportsCrashes;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import javax.inject.Inject;
import dagger.android.AndroidInjector;
import dagger.android.DaggerApplication;
import dagger.android.DispatchingAndroidInjector;
import dagger.android.HasActivityInjector;
import dagger.android.HasContentProviderInjector;
import fr.free.nrw.commons.auth.AccountUtil; import fr.free.nrw.commons.auth.AccountUtil;
import fr.free.nrw.commons.caching.CacheController; import fr.free.nrw.commons.caching.CacheController;
import fr.free.nrw.commons.contributions.Contribution; import fr.free.nrw.commons.contributions.Contribution;
import fr.free.nrw.commons.data.Category; import fr.free.nrw.commons.data.Category;
import fr.free.nrw.commons.data.DBOpenHelper; import fr.free.nrw.commons.data.DBOpenHelper;
import fr.free.nrw.commons.di.CommonsApplicationComponent;
import fr.free.nrw.commons.di.CommonsApplicationModule;
import fr.free.nrw.commons.di.DaggerCommonsApplicationComponent;
import fr.free.nrw.commons.modifications.ModifierSequence; import fr.free.nrw.commons.modifications.ModifierSequence;
import fr.free.nrw.commons.mwapi.ApacheHttpClientMediaWikiApi; import fr.free.nrw.commons.mwapi.ApacheHttpClientMediaWikiApi;
import fr.free.nrw.commons.mwapi.MediaWikiApi; import fr.free.nrw.commons.mwapi.MediaWikiApi;
@ -44,7 +56,10 @@ import timber.log.Timber;
resDialogCommentPrompt = R.string.crash_dialog_comment_prompt, resDialogCommentPrompt = R.string.crash_dialog_comment_prompt,
resDialogOkToast = R.string.crash_dialog_ok_toast resDialogOkToast = R.string.crash_dialog_ok_toast
) )
public class CommonsApplication extends Application { public class CommonsApplication extends DaggerApplication {
@Inject MediaWikiApi mediaWikiApi;
@Inject AccountUtil accountUtil;
private Account currentAccount = null; // Unlike a savings account... private Account currentAccount = null; // Unlike a savings account...
public static final String API_URL = "https://commons.wikimedia.org/w/api.php"; public static final String API_URL = "https://commons.wikimedia.org/w/api.php";
@ -70,6 +85,7 @@ public class CommonsApplication extends Application {
private CacheController cacheData = null; private CacheController cacheData = null;
private DBOpenHelper dbOpenHelper = null; private DBOpenHelper dbOpenHelper = null;
private NearbyPlaces nearbyPlaces = null; private NearbyPlaces nearbyPlaces = null;
private CommonsApplicationComponent component;
/** /**
* This should not be called by ANY application code (other than the magic Android glue) * This should not be called by ANY application code (other than the magic Android glue)
@ -121,6 +137,7 @@ public class CommonsApplication extends Application {
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
if (LeakCanary.isInAnalyzerProcess(this)) { if (LeakCanary.isInAnalyzerProcess(this)) {
// This process is dedicated to LeakCanary for heap analysis. // This process is dedicated to LeakCanary for heap analysis.
// You should not init your app in this process. // You should not init your app in this process.
@ -130,8 +147,6 @@ public class CommonsApplication extends Application {
Timber.plant(new Timber.DebugTree()); Timber.plant(new Timber.DebugTree());
if (!BuildConfig.DEBUG) { if (!BuildConfig.DEBUG) {
ACRA.init(this); ACRA.init(this);
} else { } else {
@ -147,13 +162,27 @@ public class CommonsApplication extends Application {
cacheData = new CacheController(); cacheData = new CacheController();
} }
@Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
return injector();
}
public CommonsApplicationComponent injector() {
if (component == null) {
component = DaggerCommonsApplicationComponent.builder()
.appModule(new CommonsApplicationModule(this))
.build();
}
return component;
}
/** /**
* @return Account|null * @return Account|null
*/ */
public Account getCurrentAccount() { public Account getCurrentAccount() {
if(currentAccount == null) { if(currentAccount == null) {
AccountManager accountManager = AccountManager.get(this); AccountManager accountManager = AccountManager.get(this);
Account[] allAccounts = accountManager.getAccountsByType(AccountUtil.accountType()); Account[] allAccounts = accountManager.getAccountsByType(accountUtil.accountType());
if(allAccounts.length != 0) { if(allAccounts.length != 0) {
currentAccount = allAccounts[0]; currentAccount = allAccounts[0];
} }
@ -169,10 +198,10 @@ public class CommonsApplication extends Application {
return false; // This should never happen return false; // This should never happen
} }
accountManager.invalidateAuthToken(AccountUtil.accountType(), getMWApi().getAuthCookie()); accountManager.invalidateAuthToken(accountUtil.accountType(), mediaWikiApi.getAuthCookie());
try { try {
String authCookie = accountManager.blockingGetAuthToken(curAccount, "", false); String authCookie = accountManager.blockingGetAuthToken(curAccount, "", false);
getMWApi().setAuthCookie(authCookie); mediaWikiApi.setAuthCookie(authCookie);
return true; return true;
} catch (OperationCanceledException | NullPointerException | IOException | AuthenticatorException e) { } catch (OperationCanceledException | NullPointerException | IOException | AuthenticatorException e) {
e.printStackTrace(); e.printStackTrace();
@ -199,13 +228,13 @@ public class CommonsApplication extends Application {
} }
AccountManager accountManager = AccountManager.get(this); AccountManager accountManager = AccountManager.get(this);
Account[] allAccounts = accountManager.getAccountsByType(AccountUtil.accountType()); Account[] allAccounts = accountManager.getAccountsByType(accountUtil.accountType());
for (Account allAccount : allAccounts) { for (Account allAccount : allAccounts) {
accountManager.removeAccount(allAccount, null, null); accountManager.removeAccount(allAccount, null, null);
} }
//TODO: fix preference manager //TODO: fix preference manager
PreferenceManager.getDefaultSharedPreferences(getInstance()).edit().clear().commit(); PreferenceManager.getDefaultSharedPreferences(this).edit().clear().commit();
SharedPreferences preferences = context SharedPreferences preferences = context
.getSharedPreferences("fr.free.nrw.commons", MODE_PRIVATE); .getSharedPreferences("fr.free.nrw.commons", MODE_PRIVATE);
preferences.edit().clear().commit(); preferences.edit().clear().commit();
@ -219,7 +248,7 @@ public class CommonsApplication extends Application {
* Deletes all tables and re-creates them. * Deletes all tables and re-creates them.
*/ */
public void updateAllDatabases() { public void updateAllDatabases() {
DBOpenHelper dbOpenHelper = CommonsApplication.getInstance().getDBOpenHelper(); DBOpenHelper dbOpenHelper = getDBOpenHelper();
dbOpenHelper.getReadableDatabase().close(); dbOpenHelper.getReadableDatabase().close();
SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); SQLiteDatabase db = dbOpenHelper.getWritableDatabase();

View file

@ -2,7 +2,6 @@ package fr.free.nrw.commons;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import org.mediawiki.api.ApiResult;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.Node; import org.w3c.dom.Node;
@ -34,6 +33,7 @@ import timber.log.Timber;
* which are not intrinsic to the media and may change due to editing. * which are not intrinsic to the media and may change due to editing.
*/ */
public class MediaDataExtractor { public class MediaDataExtractor {
private final MediaWikiApi mediaWikiApi;
private boolean fetched; private boolean fetched;
private String filename; private String filename;
@ -45,14 +45,16 @@ public class MediaDataExtractor {
private LicenseList licenseList; private LicenseList licenseList;
/** /**
* @param mwApi instance of MediaWikiApi
* @param filename of the target media object, should include 'File:' prefix * @param filename of the target media object, should include 'File:' prefix
*/ */
public MediaDataExtractor(String filename, LicenseList licenseList) { public MediaDataExtractor(String filename, LicenseList licenseList, MediaWikiApi mwApi) {
this.filename = filename; this.filename = filename;
categories = new ArrayList<>(); this.categories = new ArrayList<>();
descriptions = new HashMap<>(); this.descriptions = new HashMap<>();
fetched = false; this.fetched = false;
this.licenseList = licenseList; this.licenseList = licenseList;
this.mediaWikiApi = mwApi;
} }
/** /**
@ -66,8 +68,7 @@ public class MediaDataExtractor {
throw new IllegalStateException("Tried to call MediaDataExtractor.fetch() again."); throw new IllegalStateException("Tried to call MediaDataExtractor.fetch() again.");
} }
MediaWikiApi api = CommonsApplication.getInstance().getMWApi(); MediaResult result = mediaWikiApi.fetchMediaByFilename(filename);
MediaResult result = api.fetchMediaByFilename(filename);
// In-page category links are extracted from source, as XML doesn't cover [[links]] // In-page category links are extracted from source, as XML doesn't cover [[links]]
extractCategories(result.getWikiSource()); extractCategories(result.getWikiSource());

View file

@ -7,16 +7,17 @@ import fr.free.nrw.commons.mwapi.MediaWikiApi;
class MediaThumbnailFetchTask extends AsyncTask<String, String, String> { class MediaThumbnailFetchTask extends AsyncTask<String, String, String> {
protected final Media media; protected final Media media;
private MediaWikiApi mediaWikiApi;
public MediaThumbnailFetchTask(@NonNull Media media) { public MediaThumbnailFetchTask(@NonNull Media media, MediaWikiApi mwApi) {
this.media = media; this.media = media;
this.mediaWikiApi = mwApi;
} }
@Override @Override
protected String doInBackground(String... params) { protected String doInBackground(String... params) {
try { try {
MediaWikiApi api = CommonsApplication.getInstance().getMWApi(); return mediaWikiApi.findThumbnailByFilename(params[0]);
return api.findThumbnailByFilename(params[0]);
} catch (Exception e) { } catch (Exception e) {
// Do something better! // Do something better!
} }

View file

@ -11,6 +11,7 @@ import android.widget.Toast;
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder; import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
import com.facebook.drawee.view.SimpleDraweeView; import com.facebook.drawee.view.SimpleDraweeView;
import fr.free.nrw.commons.mwapi.MediaWikiApi;
import timber.log.Timber; import timber.log.Timber;
public class MediaWikiImageView extends SimpleDraweeView { public class MediaWikiImageView extends SimpleDraweeView {
@ -43,7 +44,8 @@ public class MediaWikiImageView extends SimpleDraweeView {
setImageUrl(CommonsApplication.getInstance().getThumbnailUrlCache().get(media.getFilename())); setImageUrl(CommonsApplication.getInstance().getThumbnailUrlCache().get(media.getFilename()));
} else { } else {
setImageUrl(null); setImageUrl(null);
currentThumbnailTask = new ThumbnailFetchTask(media); MediaWikiApi mediaWikiApi = CommonsApplication.getInstance().getMWApi();
currentThumbnailTask = new ThumbnailFetchTask(media, mediaWikiApi);
currentThumbnailTask.execute(media.getFilename()); currentThumbnailTask.execute(media.getFilename());
} }
} }
@ -71,8 +73,8 @@ public class MediaWikiImageView extends SimpleDraweeView {
} }
private class ThumbnailFetchTask extends MediaThumbnailFetchTask { private class ThumbnailFetchTask extends MediaThumbnailFetchTask {
ThumbnailFetchTask(@NonNull Media media) { ThumbnailFetchTask(@NonNull Media media, @NonNull MediaWikiApi mwApi) {
super(media); super(media, mwApi);
} }
@Override @Override

View file

@ -8,6 +8,8 @@ import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import javax.inject.Inject;
import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.contributions.ContributionsContentProvider; import fr.free.nrw.commons.contributions.ContributionsContentProvider;
import fr.free.nrw.commons.modifications.ModificationsContentProvider; import fr.free.nrw.commons.modifications.ModificationsContentProvider;
@ -15,8 +17,15 @@ import timber.log.Timber;
public class AccountUtil { public class AccountUtil {
public static void createAccount(@Nullable AccountAuthenticatorResponse response, private final CommonsApplication application;
String username, String password) {
@Inject
public AccountUtil(CommonsApplication application) {
this.application = application;
}
public void createAccount(@Nullable AccountAuthenticatorResponse response,
String username, String password) {
Account account = new Account(username, accountType()); Account account = new Account(username, accountType());
boolean created = accountManager().addAccountExplicitly(account, password, null); boolean created = accountManager().addAccountExplicitly(account, password, null);
@ -46,17 +55,12 @@ public class AccountUtil {
} }
@NonNull @NonNull
public static String accountType() { public String accountType() {
return "fr.free.nrw.commons"; return "fr.free.nrw.commons";
} }
private static AccountManager accountManager() { private AccountManager accountManager() {
return AccountManager.get(app()); return AccountManager.get(application);
}
@NonNull
private static CommonsApplication app() {
return CommonsApplication.getInstance();
} }
} }

View file

@ -5,6 +5,9 @@ import android.accounts.AccountManager;
import android.accounts.AccountManagerFuture; import android.accounts.AccountManagerFuture;
import android.os.Bundle; import android.os.Bundle;
import javax.inject.Inject;
import dagger.android.AndroidInjection;
import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.theme.NavigationBaseActivity; import fr.free.nrw.commons.theme.NavigationBaseActivity;
import io.reactivex.Single; import io.reactivex.Single;
@ -14,27 +17,23 @@ import timber.log.Timber;
public abstract class AuthenticatedActivity extends NavigationBaseActivity { public abstract class AuthenticatedActivity extends NavigationBaseActivity {
String accountType; @Inject CommonsApplication app;
CommonsApplication app; @Inject AccountUtil accountUtil;
private String authCookie; private String authCookie;
public AuthenticatedActivity() {
this.accountType = AccountUtil.accountType();
}
private void getAuthCookie(Account account, AccountManager accountManager) { private void getAuthCookie(Account account, AccountManager accountManager) {
Single.fromCallable(() -> accountManager.blockingGetAuthToken(account, "", false)) Single.fromCallable(() -> accountManager.blockingGetAuthToken(account, "", false))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.doOnError(Timber::e) .doOnError(Timber::e)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe( .subscribe(
cookie -> onAuthCookieAcquired(cookie), this::onAuthCookieAcquired,
throwable -> onAuthFailure()); throwable -> onAuthFailure());
} }
private void addAccount(AccountManager accountManager) { private void addAccount(AccountManager accountManager) {
Single.just(accountManager.addAccount(accountType, null, null, null, AuthenticatedActivity.this, null, null)) Single.just(accountManager.addAccount(accountUtil.accountType(), null, null, null, AuthenticatedActivity.this, null, null))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.map(AccountManagerFuture::getResult) .map(AccountManagerFuture::getResult)
.doOnEvent((bundle, throwable) -> { .doOnEvent((bundle, throwable) -> {
@ -47,7 +46,7 @@ public abstract class AuthenticatedActivity extends NavigationBaseActivity {
.doOnError(Timber::e) .doOnError(Timber::e)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(s -> { .subscribe(s -> {
Account[] allAccounts = accountManager.getAccountsByType(accountType); Account[] allAccounts = accountManager.getAccountsByType(accountUtil.accountType());
Account curAccount = allAccounts[0]; Account curAccount = allAccounts[0];
getAuthCookie(curAccount, accountManager); getAuthCookie(curAccount, accountManager);
}, },
@ -71,7 +70,7 @@ public abstract class AuthenticatedActivity extends NavigationBaseActivity {
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
app = CommonsApplication.getInstance();
if(savedInstanceState != null) { if(savedInstanceState != null) {
authCookie = savedInstanceState.getString("authCookie"); authCookie = savedInstanceState.getString("authCookie");
} }

View file

@ -8,15 +8,16 @@ import android.os.Bundle;
import android.support.v4.app.NavUtils; import android.support.v4.app.NavUtils;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import javax.inject.Inject;
import dagger.android.AndroidInjection;
import fr.free.nrw.commons.BuildConfig; import fr.free.nrw.commons.BuildConfig;
import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
@ -34,6 +35,9 @@ public class LoginActivity extends AccountAuthenticatorActivity {
public static final String PARAM_USERNAME = "fr.free.nrw.commons.login.username"; public static final String PARAM_USERNAME = "fr.free.nrw.commons.login.username";
@Inject CommonsApplication application;
@Inject AccountUtil accountUtil;
private SharedPreferences prefs = null; private SharedPreferences prefs = null;
private Button loginButton; private Button loginButton;
@ -43,14 +47,11 @@ public class LoginActivity extends AccountAuthenticatorActivity {
ProgressDialog progressDialog; ProgressDialog progressDialog;
private LoginTextWatcher textWatcher = new LoginTextWatcher(); private LoginTextWatcher textWatcher = new LoginTextWatcher();
private CommonsApplication app;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
AndroidInjection.inject(this);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
app = CommonsApplication.getInstance();
setContentView(R.layout.activity_login); setContentView(R.layout.activity_login);
loginButton = (Button) findViewById(R.id.loginButton); loginButton = (Button) findViewById(R.id.loginButton);
@ -111,7 +112,7 @@ public class LoginActivity extends AccountAuthenticatorActivity {
WelcomeActivity.startYourself(this); WelcomeActivity.startYourself(this);
prefs.edit().putBoolean("firstrun", false).apply(); prefs.edit().putBoolean("firstrun", false).apply();
} }
if (app.getCurrentAccount() != null) { if (application.getCurrentAccount() != null) {
startMainActivity(); startMainActivity();
} }
} }
@ -143,7 +144,8 @@ public class LoginActivity extends AccountAuthenticatorActivity {
this, this,
canonicializeUsername(usernameEdit.getText().toString()), canonicializeUsername(usernameEdit.getText().toString()),
passwordEdit.getText().toString(), passwordEdit.getText().toString(),
twoFactorEdit.getText().toString() twoFactorEdit.getText().toString(),
accountUtil, application
); );
} }

View file

@ -19,14 +19,16 @@ class LoginTask extends AsyncTask<String, String, String> {
private String username; private String username;
private String password; private String password;
private String twoFactorCode = ""; private String twoFactorCode = "";
private AccountUtil accountUtil;
private CommonsApplication app; private CommonsApplication app;
public LoginTask(LoginActivity loginActivity, String username, String password, String twoFactorCode) { public LoginTask(LoginActivity loginActivity, String username, String password, String twoFactorCode, AccountUtil accountUtil, CommonsApplication application) {
this.loginActivity = loginActivity; this.loginActivity = loginActivity;
this.username = username; this.username = username;
this.password = password; this.password = password;
this.twoFactorCode = twoFactorCode; this.twoFactorCode = twoFactorCode;
app = CommonsApplication.getInstance(); this.accountUtil = accountUtil;
this.app = application;
} }
@Override @Override
@ -59,7 +61,7 @@ class LoginTask extends AsyncTask<String, String, String> {
super.onPostExecute(result); super.onPostExecute(result);
Timber.d("Login done!"); Timber.d("Login done!");
EventLog.schema(CommonsApplication.EVENT_LOGIN_ATTEMPT) EventLog.schema(CommonsApplication.EVENT_LOGIN_ATTEMPT, app)
.param("username", username) .param("username", username)
.param("result", result) .param("result", result)
.log(); .log();
@ -83,12 +85,12 @@ class LoginTask extends AsyncTask<String, String, String> {
if (response != null) { if (response != null) {
Bundle authResult = new Bundle(); Bundle authResult = new Bundle();
authResult.putString(AccountManager.KEY_ACCOUNT_NAME, username); authResult.putString(AccountManager.KEY_ACCOUNT_NAME, username);
authResult.putString(AccountManager.KEY_ACCOUNT_TYPE, AccountUtil.accountType()); authResult.putString(AccountManager.KEY_ACCOUNT_TYPE, accountUtil.accountType());
response.onResult(authResult); response.onResult(authResult);
} }
} }
AccountUtil.createAccount(response, username, password); accountUtil.createAccount(response, username, password);
loginActivity.startMainActivity(); loginActivity.startMainActivity();
} }

View file

@ -6,12 +6,16 @@ import android.webkit.WebView;
import android.webkit.WebViewClient; import android.webkit.WebViewClient;
import android.widget.Toast; import android.widget.Toast;
import javax.inject.Inject;
import dagger.android.AndroidInjection;
import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.theme.BaseActivity; import fr.free.nrw.commons.theme.BaseActivity;
import timber.log.Timber; import timber.log.Timber;
public class SignupActivity extends BaseActivity { public class SignupActivity extends BaseActivity {
@Inject CommonsApplication application;
private WebView webView; private WebView webView;
@Override @Override
@ -38,7 +42,7 @@ public class SignupActivity extends BaseActivity {
Timber.d("Overriding URL %s", url); Timber.d("Overriding URL %s", url);
Toast toast = Toast.makeText( Toast toast = Toast.makeText(
CommonsApplication.getInstance(), application,
"Account created!", "Account created!",
Toast.LENGTH_LONG Toast.LENGTH_LONG
); );

View file

@ -13,16 +13,19 @@ import android.support.annotation.Nullable;
import java.io.IOException; import java.io.IOException;
import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.mwapi.MediaWikiApi; import fr.free.nrw.commons.mwapi.MediaWikiApi;
public class WikiAccountAuthenticator extends AbstractAccountAuthenticator { public class WikiAccountAuthenticator extends AbstractAccountAuthenticator {
private Context context; private final Context context;
private final AccountUtil accountUtil;
private MediaWikiApi mediaWikiApi;
public WikiAccountAuthenticator(Context context) { public WikiAccountAuthenticator(Context context, AccountUtil accountUtil, MediaWikiApi mwApi) {
super(context); super(context);
this.context = context; this.context = context;
this.accountUtil = accountUtil;
this.mediaWikiApi = mwApi;
} }
private Bundle unsupportedOperation() { private Bundle unsupportedOperation() {
@ -36,7 +39,7 @@ public class WikiAccountAuthenticator extends AbstractAccountAuthenticator {
} }
private boolean supportedAccountType(@Nullable String type) { private boolean supportedAccountType(@Nullable String type) {
return AccountUtil.accountType().equals(type); return accountUtil.accountType().equals(type);
} }
@Override @Override
@ -75,11 +78,10 @@ public class WikiAccountAuthenticator extends AbstractAccountAuthenticator {
} }
private String getAuthCookie(String username, String password) throws IOException { private String getAuthCookie(String username, String password) throws IOException {
MediaWikiApi api = CommonsApplication.getInstance().getMWApi();
//TODO add 2fa support here //TODO add 2fa support here
String result = api.login(username, password); String result = mediaWikiApi.login(username, password);
if(result.equals("PASS")) { if(result.equals("PASS")) {
return api.getAuthCookie(); return mediaWikiApi.getAuthCookie();
} else { } else {
return null; return null;
} }
@ -102,7 +104,7 @@ public class WikiAccountAuthenticator extends AbstractAccountAuthenticator {
if (authCookie != null) { if (authCookie != null) {
final Bundle result = new Bundle(); final Bundle result = new Bundle();
result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name); result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, AccountUtil.accountType()); result.putString(AccountManager.KEY_ACCOUNT_TYPE, accountUtil.accountType());
result.putString(AccountManager.KEY_AUTHTOKEN, authCookie); result.putString(AccountManager.KEY_AUTHTOKEN, authCookie);
return result; return result;
} }

View file

@ -5,18 +5,25 @@ import android.app.Service;
import android.content.Intent; import android.content.Intent;
import android.os.IBinder; import android.os.IBinder;
import javax.inject.Inject;
import fr.free.nrw.commons.CommonsApplication;
public class WikiAccountAuthenticatorService extends Service { public class WikiAccountAuthenticatorService extends Service {
private static WikiAccountAuthenticator wikiAccountAuthenticator = null; @Inject CommonsApplication application;
@Inject AccountUtil accountUtil;
private WikiAccountAuthenticator wikiAccountAuthenticator = null;
@Override @Override
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
if (!intent.getAction().equals(AccountManager.ACTION_AUTHENTICATOR_INTENT)) { if (!intent.getAction().equals(AccountManager.ACTION_AUTHENTICATOR_INTENT)) {
return null; return null;
} }
((CommonsApplication)getApplication()).injector().inject(this);
if (wikiAccountAuthenticator == null) { if (wikiAccountAuthenticator == null) {
wikiAccountAuthenticator = new WikiAccountAuthenticator(this); wikiAccountAuthenticator = new WikiAccountAuthenticator(this, accountUtil, application.getMWApi());
} }
return wikiAccountAuthenticator.getIBinder(); return wikiAccountAuthenticator.getIBinder();
} }

View file

@ -10,6 +10,9 @@ import android.net.Uri;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.text.TextUtils; import android.text.TextUtils;
import javax.inject.Inject;
import dagger.android.AndroidInjection;
import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.data.Category; import fr.free.nrw.commons.data.Category;
import fr.free.nrw.commons.data.DBOpenHelper; import fr.free.nrw.commons.data.DBOpenHelper;
@ -36,10 +39,14 @@ public class CategoryContentProvider extends ContentProvider {
return Uri.parse(BASE_URI.toString() + "/" + id); return Uri.parse(BASE_URI.toString() + "/" + id);
} }
@Inject CommonsApplication application;
private DBOpenHelper dbOpenHelper; private DBOpenHelper dbOpenHelper;
@Override @Override
public boolean onCreate() { public boolean onCreate() {
dbOpenHelper = CommonsApplication.getInstance().getDBOpenHelper(); AndroidInjection.inject(this);
dbOpenHelper = application.getDBOpenHelper();
return false; return false;
} }

View file

@ -24,13 +24,17 @@ import android.widget.AdapterView;
import java.util.ArrayList; import java.util.ArrayList;
import javax.inject.Inject;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import dagger.android.AndroidInjection;
import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.HandlerService; import fr.free.nrw.commons.HandlerService;
import fr.free.nrw.commons.Media; import fr.free.nrw.commons.Media;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.auth.AuthenticatedActivity; import fr.free.nrw.commons.auth.AuthenticatedActivity;
import fr.free.nrw.commons.media.MediaDetailPagerFragment; import fr.free.nrw.commons.media.MediaDetailPagerFragment;
import fr.free.nrw.commons.mwapi.MediaWikiApi;
import fr.free.nrw.commons.settings.Prefs; import fr.free.nrw.commons.settings.Prefs;
import fr.free.nrw.commons.upload.UploadService; import fr.free.nrw.commons.upload.UploadService;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
@ -46,6 +50,9 @@ public class ContributionsActivity
FragmentManager.OnBackStackChangedListener, FragmentManager.OnBackStackChangedListener,
ContributionsListFragment.SourceRefresher { ContributionsListFragment.SourceRefresher {
@Inject CommonsApplication application;
@Inject MediaWikiApi mediaWikiApi;
private Cursor allContributions; private Cursor allContributions;
private ContributionsListFragment contributionsList; private ContributionsListFragment contributionsList;
private MediaDetailPagerFragment mediaDetails; private MediaDetailPagerFragment mediaDetails;
@ -108,7 +115,7 @@ public class ContributionsActivity
@Override @Override
protected void onAuthCookieAcquired(String authCookie) { protected void onAuthCookieAcquired(String authCookie) {
// Do a sync everytime we get here! // Do a sync everytime we get here!
ContentResolver.requestSync(CommonsApplication.getInstance().getCurrentAccount(), ContributionsContentProvider.AUTHORITY, new Bundle()); ContentResolver.requestSync(application.getCurrentAccount(), ContributionsContentProvider.AUTHORITY, new Bundle());
Intent uploadServiceIntent = new Intent(this, UploadService.class); Intent uploadServiceIntent = new Intent(this, UploadService.class);
uploadServiceIntent.setAction(UploadService.ACTION_START_SERVICE); uploadServiceIntent.setAction(UploadService.ACTION_START_SERVICE);
startService(uploadServiceIntent); startService(uploadServiceIntent);
@ -263,10 +270,8 @@ public class ContributionsActivity
} }
private void setUploadCount() { private void setUploadCount() {
CommonsApplication application = CommonsApplication.getInstance();
compositeDisposable.add( compositeDisposable.add(
CommonsApplication.getInstance().getMWApi() mediaWikiApi
.getUploadCount(application.getCurrentAccount().name) .getUploadCount(application.getCurrentAccount().name)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())

View file

@ -10,6 +10,9 @@ import android.net.Uri;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.text.TextUtils; import android.text.TextUtils;
import javax.inject.Inject;
import dagger.android.AndroidInjection;
import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.CommonsApplication;
import timber.log.Timber; import timber.log.Timber;
@ -33,9 +36,12 @@ public class ContributionsContentProvider extends ContentProvider{
return Uri.parse(BASE_URI.toString() + "/" + id); return Uri.parse(BASE_URI.toString() + "/" + id);
} }
@Inject CommonsApplication application;
@Override @Override
public boolean onCreate() { public boolean onCreate() {
return false; AndroidInjection.inject(this);
return true;
} }
@Override @Override
@ -45,7 +51,7 @@ public class ContributionsContentProvider extends ContentProvider{
int uriType = uriMatcher.match(uri); int uriType = uriMatcher.match(uri);
SQLiteDatabase db = CommonsApplication.getInstance().getDBOpenHelper().getReadableDatabase(); SQLiteDatabase db = application.getDBOpenHelper().getReadableDatabase();
Cursor cursor; Cursor cursor;
switch(uriType) { switch(uriType) {
@ -79,7 +85,7 @@ public class ContributionsContentProvider extends ContentProvider{
@Override @Override
public Uri insert(@NonNull Uri uri, ContentValues contentValues) { public Uri insert(@NonNull Uri uri, ContentValues contentValues) {
int uriType = uriMatcher.match(uri); int uriType = uriMatcher.match(uri);
SQLiteDatabase sqlDB = CommonsApplication.getInstance().getDBOpenHelper().getWritableDatabase(); SQLiteDatabase sqlDB = application.getDBOpenHelper().getWritableDatabase();
long id = 0; long id = 0;
switch (uriType) { switch (uriType) {
case CONTRIBUTIONS: case CONTRIBUTIONS:
@ -97,7 +103,7 @@ public class ContributionsContentProvider extends ContentProvider{
int rows = 0; int rows = 0;
int uriType = uriMatcher.match(uri); int uriType = uriMatcher.match(uri);
SQLiteDatabase db = CommonsApplication.getInstance().getDBOpenHelper().getReadableDatabase(); SQLiteDatabase db = application.getDBOpenHelper().getReadableDatabase();
switch(uriType) { switch(uriType) {
case CONTRIBUTIONS_ID: case CONTRIBUTIONS_ID:
@ -118,7 +124,7 @@ public class ContributionsContentProvider extends ContentProvider{
public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) { public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) {
Timber.d("Hello, bulk insert! (ContributionsContentProvider)"); Timber.d("Hello, bulk insert! (ContributionsContentProvider)");
int uriType = uriMatcher.match(uri); int uriType = uriMatcher.match(uri);
SQLiteDatabase sqlDB = CommonsApplication.getInstance().getDBOpenHelper().getWritableDatabase(); SQLiteDatabase sqlDB = application.getDBOpenHelper().getWritableDatabase();
sqlDB.beginTransaction(); sqlDB.beginTransaction();
switch (uriType) { switch (uriType) {
case CONTRIBUTIONS: case CONTRIBUTIONS:
@ -146,7 +152,7 @@ public class ContributionsContentProvider extends ContentProvider{
In here, the only concat created argument is for id. It is cast to an int, and will error out otherwise. In here, the only concat created argument is for id. It is cast to an int, and will error out otherwise.
*/ */
int uriType = uriMatcher.match(uri); int uriType = uriMatcher.match(uri);
SQLiteDatabase sqlDB = CommonsApplication.getInstance().getDBOpenHelper().getWritableDatabase(); SQLiteDatabase sqlDB = application.getDBOpenHelper().getWritableDatabase();
int rowsUpdated = 0; int rowsUpdated = 0;
switch (uriType) { switch (uriType) {
case CONTRIBUTIONS: case CONTRIBUTIONS:

View file

@ -17,6 +17,8 @@ import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import javax.inject.Inject;
import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.Utils; import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.mwapi.LogEventResult; import fr.free.nrw.commons.mwapi.LogEventResult;
@ -25,6 +27,9 @@ import timber.log.Timber;
public class ContributionsSyncAdapter extends AbstractThreadedSyncAdapter { public class ContributionsSyncAdapter extends AbstractThreadedSyncAdapter {
private static int COMMIT_THRESHOLD = 10; private static int COMMIT_THRESHOLD = 10;
@Inject CommonsApplication application;
public ContributionsSyncAdapter(Context context, boolean autoInitialize) { public ContributionsSyncAdapter(Context context, boolean autoInitialize) {
super(context, autoInitialize); super(context, autoInitialize);
} }
@ -59,10 +64,12 @@ public class ContributionsSyncAdapter extends AbstractThreadedSyncAdapter {
@Override @Override
public void onPerformSync(Account account, Bundle bundle, String s, ContentProviderClient contentProviderClient, SyncResult syncResult) { public void onPerformSync(Account account, Bundle bundle, String s, ContentProviderClient contentProviderClient, SyncResult syncResult) {
((CommonsApplication)getContext().getApplicationContext()).injector().inject(this);
// This code is fraught with possibilities of race conditions, but lalalalala I can't hear you! // This code is fraught with possibilities of race conditions, but lalalalala I can't hear you!
String user = account.name; String user = account.name;
MediaWikiApi api = CommonsApplication.getInstance().getMWApi(); MediaWikiApi api = application.getMWApi();
SharedPreferences prefs = this.getContext().getSharedPreferences("prefs", Context.MODE_PRIVATE); SharedPreferences prefs = getContext().getSharedPreferences("prefs", Context.MODE_PRIVATE);
String lastModified = prefs.getString("lastSyncTimestamp", ""); String lastModified = prefs.getString("lastSyncTimestamp", "");
Date curTime = new Date(); Date curTime = new Date();
LogEventResult result; LogEventResult result;

View file

@ -0,0 +1,45 @@
package fr.free.nrw.commons.di;
import dagger.Module;
import dagger.android.ContributesAndroidInjector;
import fr.free.nrw.commons.AboutActivity;
import fr.free.nrw.commons.WelcomeActivity;
import fr.free.nrw.commons.auth.LoginActivity;
import fr.free.nrw.commons.auth.SignupActivity;
import fr.free.nrw.commons.contributions.ContributionsActivity;
import fr.free.nrw.commons.nearby.NearbyActivity;
import fr.free.nrw.commons.settings.SettingsActivity;
import fr.free.nrw.commons.upload.MultipleShareActivity;
import fr.free.nrw.commons.upload.ShareActivity;
@Module
public abstract class ActivityBuilderModule {
@ContributesAndroidInjector
abstract ContributionsActivity bindContributionsActivity();
@ContributesAndroidInjector
abstract MultipleShareActivity bindMultipleShareActivity();
@ContributesAndroidInjector
abstract ShareActivity bindShareActivity();
@ContributesAndroidInjector
abstract LoginActivity bindLoginActivity();
@ContributesAndroidInjector
abstract SignupActivity bindSignupActivity();
@ContributesAndroidInjector
abstract NearbyActivity bindNearbyActivity();
@ContributesAndroidInjector
abstract AboutActivity bindAboutActivity();
@ContributesAndroidInjector
abstract SettingsActivity bindSettingsActivity();
@ContributesAndroidInjector
abstract WelcomeActivity bindWelcomeActivity();
}

View file

@ -0,0 +1,35 @@
package fr.free.nrw.commons.di;
import javax.inject.Singleton;
import dagger.Component;
import dagger.android.AndroidInjectionModule;
import dagger.android.AndroidInjector;
import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.auth.WikiAccountAuthenticatorService;
import fr.free.nrw.commons.contributions.ContributionsSyncAdapter;
import fr.free.nrw.commons.modifications.ModificationsSyncAdapter;
@Singleton
@Component(modules = {
CommonsApplicationModule.class,
AndroidInjectionModule.class,
ActivityBuilderModule.class,
ContentProviderBuilderModule.class
})
public interface CommonsApplicationComponent extends AndroidInjector<CommonsApplication> {
void inject(CommonsApplication application);
void inject(WikiAccountAuthenticatorService service);
void inject(ContributionsSyncAdapter syncAdapter);
void inject(ModificationsSyncAdapter syncAdapter);
@Component.Builder
interface Builder {
Builder appModule(CommonsApplicationModule applicationModule);
CommonsApplicationComponent build();
}
}

View file

@ -0,0 +1,29 @@
package fr.free.nrw.commons.di;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.mwapi.ApacheHttpClientMediaWikiApi;
import fr.free.nrw.commons.mwapi.MediaWikiApi;
@Module
public class CommonsApplicationModule {
private CommonsApplication application;
public CommonsApplicationModule(CommonsApplication application) {
this.application = application;
}
@Provides
public CommonsApplication providesCommonsApplication() {
return application;
}
@Provides
@Singleton
public MediaWikiApi provideMediaWikiApi() {
return new ApacheHttpClientMediaWikiApi(CommonsApplication.API_URL);
}
}

View file

@ -0,0 +1,24 @@
package fr.free.nrw.commons.di;
import dagger.Module;
import dagger.android.ContributesAndroidInjector;
import fr.free.nrw.commons.auth.LoginActivity;
import fr.free.nrw.commons.auth.SignupActivity;
import fr.free.nrw.commons.category.CategoryContentProvider;
import fr.free.nrw.commons.contributions.ContributionsActivity;
import fr.free.nrw.commons.contributions.ContributionsContentProvider;
import fr.free.nrw.commons.modifications.ModificationsContentProvider;
@Module
public abstract class ContentProviderBuilderModule {
@ContributesAndroidInjector
abstract CategoryContentProvider bindCategoryContentProvider();
@ContributesAndroidInjector
abstract ContributionsContentProvider bindContributionsContentProvider();
@ContributesAndroidInjector
abstract ModificationsContentProvider bindModificationsContentProvider();
}

View file

@ -22,6 +22,7 @@ import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.Locale; import java.util.Locale;
import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.License; import fr.free.nrw.commons.License;
import fr.free.nrw.commons.LicenseList; import fr.free.nrw.commons.LicenseList;
import fr.free.nrw.commons.Media; import fr.free.nrw.commons.Media;
@ -188,7 +189,7 @@ public class MediaDetailFragment extends Fragment {
@Override @Override
protected void onPreExecute() { protected void onPreExecute() {
extractor = new MediaDataExtractor(media.getFilename(), licenseList); extractor = new MediaDataExtractor(media.getFilename(), licenseList, CommonsApplication.getInstance().getMWApi());
} }
@Override @Override

View file

@ -131,7 +131,7 @@ public class MediaDetailPagerFragment extends Fragment implements ViewPager.OnPa
switch(item.getItemId()) { switch(item.getItemId()) {
case R.id.menu_share_current_image: case R.id.menu_share_current_image:
// Share - this is just logs it, intent set in onCreateOptionsMenu, around line 252 // Share - this is just logs it, intent set in onCreateOptionsMenu, around line 252
EventLog.schema(CommonsApplication.EVENT_SHARE_ATTEMPT) EventLog.schema(CommonsApplication.EVENT_SHARE_ATTEMPT, CommonsApplication.getInstance())
.param("username", app.getCurrentAccount().name) .param("username", app.getCurrentAccount().name)
.param("filename", m.getFilename()) .param("filename", m.getFilename())
.log(); .log();

View file

@ -10,6 +10,9 @@ import android.net.Uri;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.text.TextUtils; import android.text.TextUtils;
import javax.inject.Inject;
import dagger.android.AndroidInjection;
import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.CommonsApplication;
import timber.log.Timber; import timber.log.Timber;
@ -33,10 +36,12 @@ public class ModificationsContentProvider extends ContentProvider{
return Uri.parse(BASE_URI.toString() + "/" + id); return Uri.parse(BASE_URI.toString() + "/" + id);
} }
@Inject CommonsApplication application;
@Override @Override
public boolean onCreate() { public boolean onCreate() {
return false; AndroidInjection.inject(this);
return true;
} }
@Override @Override
@ -53,7 +58,7 @@ public class ModificationsContentProvider extends ContentProvider{
throw new IllegalArgumentException("Unknown URI" + uri); throw new IllegalArgumentException("Unknown URI" + uri);
} }
SQLiteDatabase db = CommonsApplication.getInstance().getDBOpenHelper().getReadableDatabase(); SQLiteDatabase db = application.getDBOpenHelper().getReadableDatabase();
Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder); Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(), uri); cursor.setNotificationUri(getContext().getContentResolver(), uri);
@ -69,7 +74,7 @@ public class ModificationsContentProvider extends ContentProvider{
@Override @Override
public Uri insert(@NonNull Uri uri, ContentValues contentValues) { public Uri insert(@NonNull Uri uri, ContentValues contentValues) {
int uriType = uriMatcher.match(uri); int uriType = uriMatcher.match(uri);
SQLiteDatabase sqlDB = CommonsApplication.getInstance().getDBOpenHelper().getWritableDatabase(); SQLiteDatabase sqlDB = application.getDBOpenHelper().getWritableDatabase();
long id = 0; long id = 0;
switch (uriType) { switch (uriType) {
case MODIFICATIONS: case MODIFICATIONS:
@ -85,7 +90,7 @@ public class ModificationsContentProvider extends ContentProvider{
@Override @Override
public int delete(@NonNull Uri uri, String s, String[] strings) { public int delete(@NonNull Uri uri, String s, String[] strings) {
int uriType = uriMatcher.match(uri); int uriType = uriMatcher.match(uri);
SQLiteDatabase sqlDB = CommonsApplication.getInstance().getDBOpenHelper().getWritableDatabase(); SQLiteDatabase sqlDB = application.getDBOpenHelper().getWritableDatabase();
switch (uriType) { switch (uriType) {
case MODIFICATIONS_ID: case MODIFICATIONS_ID:
String id = uri.getLastPathSegment(); String id = uri.getLastPathSegment();
@ -103,7 +108,7 @@ public class ModificationsContentProvider extends ContentProvider{
public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) { public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) {
Timber.d("Hello, bulk insert! (ModificationsContentProvider)"); Timber.d("Hello, bulk insert! (ModificationsContentProvider)");
int uriType = uriMatcher.match(uri); int uriType = uriMatcher.match(uri);
SQLiteDatabase sqlDB = CommonsApplication.getInstance().getDBOpenHelper().getWritableDatabase(); SQLiteDatabase sqlDB = application.getDBOpenHelper().getWritableDatabase();
sqlDB.beginTransaction(); sqlDB.beginTransaction();
switch (uriType) { switch (uriType) {
case MODIFICATIONS: case MODIFICATIONS:
@ -131,7 +136,7 @@ public class ModificationsContentProvider extends ContentProvider{
In here, the only concat created argument is for id. It is cast to an int, and will error out otherwise. In here, the only concat created argument is for id. It is cast to an int, and will error out otherwise.
*/ */
int uriType = uriMatcher.match(uri); int uriType = uriMatcher.match(uri);
SQLiteDatabase sqlDB = CommonsApplication.getInstance().getDBOpenHelper().getWritableDatabase(); SQLiteDatabase sqlDB = application.getDBOpenHelper().getWritableDatabase();
int rowsUpdated = 0; int rowsUpdated = 0;
switch (uriType) { switch (uriType) {
case MODIFICATIONS: case MODIFICATIONS:

View file

@ -14,6 +14,8 @@ import android.os.RemoteException;
import java.io.IOException; import java.io.IOException;
import javax.inject.Inject;
import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.Utils; import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.contributions.Contribution; import fr.free.nrw.commons.contributions.Contribution;
@ -23,6 +25,8 @@ import timber.log.Timber;
public class ModificationsSyncAdapter extends AbstractThreadedSyncAdapter { public class ModificationsSyncAdapter extends AbstractThreadedSyncAdapter {
@Inject CommonsApplication application;
public ModificationsSyncAdapter(Context context, boolean autoInitialize) { public ModificationsSyncAdapter(Context context, boolean autoInitialize) {
super(context, autoInitialize); super(context, autoInitialize);
} }
@ -30,6 +34,7 @@ public class ModificationsSyncAdapter extends AbstractThreadedSyncAdapter {
@Override @Override
public void onPerformSync(Account account, Bundle bundle, String s, ContentProviderClient contentProviderClient, SyncResult syncResult) { public void onPerformSync(Account account, Bundle bundle, String s, ContentProviderClient contentProviderClient, SyncResult syncResult) {
// This code is fraught with possibilities of race conditions, but lalalalala I can't hear you! // This code is fraught with possibilities of race conditions, but lalalalala I can't hear you!
((CommonsApplication)getContext().getApplicationContext()).injector().inject(this);
Cursor allModifications; Cursor allModifications;
try { try {
@ -59,7 +64,7 @@ public class ModificationsSyncAdapter extends AbstractThreadedSyncAdapter {
return; return;
} }
MediaWikiApi api = CommonsApplication.getInstance().getMWApi(); MediaWikiApi api = application.getMWApi();
api.setAuthCookie(authCookie); api.setAuthCookie(authCookie);
String editToken; String editToken;

View file

@ -2,6 +2,7 @@ package fr.free.nrw.commons.mwapi;
import android.os.Build; import android.os.Build;
import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.Utils; import fr.free.nrw.commons.Utils;
public class EventLog { public class EventLog {
@ -15,14 +16,14 @@ public class EventLog {
} }
} }
private static LogBuilder schema(String schema, long revision) { private static LogBuilder schema(String schema, long revision, CommonsApplication application) {
return new LogBuilder(schema, revision); return new LogBuilder(schema, revision, application);
} }
public static LogBuilder schema(Object[] scid) { public static LogBuilder schema(Object[] scid, CommonsApplication application) {
if (scid.length != 2) { if (scid.length != 2) {
throw new IllegalArgumentException("Needs an object array with schema as first param and revision as second"); throw new IllegalArgumentException("Needs an object array with schema as first param and revision as second");
} }
return schema((String) scid[0], (Long) scid[1]); return schema((String) scid[0], (Long) scid[1], application);
} }
} }

View file

@ -17,14 +17,16 @@ import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.settings.Prefs; import fr.free.nrw.commons.settings.Prefs;
public class LogBuilder { public class LogBuilder {
private final CommonsApplication application;
private JSONObject data; private JSONObject data;
private long rev; private long rev;
private String schema; private String schema;
LogBuilder(String schema, long revision) { LogBuilder(String schema, long revision, CommonsApplication application) {
data = new JSONObject(); data = new JSONObject();
this.schema = schema; this.schema = schema;
this.rev = revision; this.rev = revision;
this.application = application;
} }
public LogBuilder param(String key, Object value) { public LogBuilder param(String key, Object value) {
@ -56,11 +58,11 @@ public class LogBuilder {
// Use *only* for tracking the user preference change for EventLogging // Use *only* for tracking the user preference change for EventLogging
// Attempting to use anywhere else will cause kitten explosions // Attempting to use anywhere else will cause kitten explosions
public void log(boolean force) { public void log(boolean force) {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(CommonsApplication.getInstance()); SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(application);
if (!settings.getBoolean(Prefs.TRACKING_ENABLED, true) && !force) { if (!settings.getBoolean(Prefs.TRACKING_ENABLED, true) && !force) {
return; // User has disabled tracking return; // User has disabled tracking
} }
LogTask logTask = new LogTask(); LogTask logTask = new LogTask(application.getMWApi());
logTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, this); logTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, this);
} }

View file

@ -2,11 +2,16 @@ package fr.free.nrw.commons.mwapi;
import android.os.AsyncTask; import android.os.AsyncTask;
import fr.free.nrw.commons.CommonsApplication;
class LogTask extends AsyncTask<LogBuilder, Void, Boolean> { class LogTask extends AsyncTask<LogBuilder, Void, Boolean> {
private final MediaWikiApi mwApi;
public LogTask(MediaWikiApi mwApi) {
this.mwApi = mwApi;
}
@Override @Override
protected Boolean doInBackground(LogBuilder... logBuilders) { protected Boolean doInBackground(LogBuilder... logBuilders) {
return CommonsApplication.getInstance().getMWApi().logEvents(logBuilders); return mwApi.logEvents(logBuilders);
} }
} }

View file

@ -27,8 +27,11 @@ import com.google.gson.GsonBuilder;
import java.util.List; import java.util.List;
import javax.inject.Inject;
import butterknife.BindView; import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import dagger.android.AndroidInjection;
import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.location.LatLng; import fr.free.nrw.commons.location.LatLng;
@ -37,11 +40,12 @@ import fr.free.nrw.commons.theme.NavigationBaseActivity;
import fr.free.nrw.commons.utils.UriSerializer; import fr.free.nrw.commons.utils.UriSerializer;
import timber.log.Timber; import timber.log.Timber;
public class NearbyActivity extends NavigationBaseActivity { public class NearbyActivity extends NavigationBaseActivity {
@BindView(R.id.progressBar) @BindView(R.id.progressBar)
ProgressBar progressBar; ProgressBar progressBar;
@Inject CommonsApplication application;
private boolean isMapViewActive = false; private boolean isMapViewActive = false;
private static final int LOCATION_REQUEST = 1; private static final int LOCATION_REQUEST = 1;
@ -91,7 +95,7 @@ public class NearbyActivity extends NavigationBaseActivity {
locationManager = new LocationServiceManager(this); locationManager = new LocationServiceManager(this);
locationManager.registerLocationManager(); locationManager.registerLocationManager();
curLatLang = locationManager.getLatestLocation(); curLatLang = locationManager.getLatestLocation();
nearbyAsyncTask = new NearbyAsyncTask(this); nearbyAsyncTask = new NearbyAsyncTask(this, application);
nearbyAsyncTask.execute(); nearbyAsyncTask.execute();
} }
@ -230,7 +234,7 @@ public class NearbyActivity extends NavigationBaseActivity {
} }
private void refreshView() { private void refreshView() {
nearbyAsyncTask = new NearbyAsyncTask(this); nearbyAsyncTask = new NearbyAsyncTask(this, application);
nearbyAsyncTask.execute(); nearbyAsyncTask.execute();
} }
@ -245,9 +249,11 @@ public class NearbyActivity extends NavigationBaseActivity {
private class NearbyAsyncTask extends AsyncTask<Void, Integer, List<Place>> { private class NearbyAsyncTask extends AsyncTask<Void, Integer, List<Place>> {
private final Context mContext; private final Context mContext;
private final CommonsApplication application;
private NearbyAsyncTask(Context context) { private NearbyAsyncTask(Context context, CommonsApplication application) {
mContext = context; mContext = context;
this.application = application;
} }
@Override @Override
@ -258,8 +264,7 @@ public class NearbyActivity extends NavigationBaseActivity {
@Override @Override
protected List<Place> doInBackground(Void... params) { protected List<Place> doInBackground(Void... params) {
return NearbyController return NearbyController
.loadAttractionsFromLocation(curLatLang, CommonsApplication.getInstance() .loadAttractionsFromLocation(curLatLang, application);
);
} }
@Override @Override

View file

@ -5,15 +5,16 @@ import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import dagger.android.AndroidInjection;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.Utils; import fr.free.nrw.commons.Utils;
public class BaseActivity extends AppCompatActivity { public class BaseActivity extends AppCompatActivity {
boolean currentTheme; boolean currentTheme;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
AndroidInjection.inject(this);
if(Utils.isDarkTheme(this)){ if(Utils.isDarkTheme(this)){
currentTheme = true; currentTheme = true;
setTheme(R.style.DarkAppTheme); setTheme(R.style.DarkAppTheme);

View file

@ -177,7 +177,7 @@ public class MultipleShareActivity
// FIXME: Make sure that the content provider is up // FIXME: Make sure that the content provider is up
// This is the wrong place for it, but bleh - better than not having it turned on by default for people who don't go throughl ogin // This is the wrong place for it, but bleh - better than not having it turned on by default for people who don't go throughl ogin
ContentResolver.setSyncAutomatically(app.getCurrentAccount(), ModificationsContentProvider.AUTHORITY, true); // Enable sync by default! ContentResolver.setSyncAutomatically(app.getCurrentAccount(), ModificationsContentProvider.AUTHORITY, true); // Enable sync by default!
EventLog.schema(CommonsApplication.EVENT_CATEGORIZATION_ATTEMPT) EventLog.schema(CommonsApplication.EVENT_CATEGORIZATION_ATTEMPT, CommonsApplication.getInstance())
.param("username", app.getCurrentAccount().name) .param("username", app.getCurrentAccount().name)
.param("categories-count", categories.size()) .param("categories-count", categories.size())
.param("files-count", photosList.size()) .param("files-count", photosList.size())
@ -288,7 +288,7 @@ public class MultipleShareActivity
public void onBackPressed() { public void onBackPressed() {
super.onBackPressed(); super.onBackPressed();
if(categorizationFragment != null && categorizationFragment.isVisible()) { if(categorizationFragment != null && categorizationFragment.isVisible()) {
EventLog.schema(CommonsApplication.EVENT_CATEGORIZATION_ATTEMPT) EventLog.schema(CommonsApplication.EVENT_CATEGORIZATION_ATTEMPT, CommonsApplication.getInstance())
.param("username", app.getCurrentAccount().name) .param("username", app.getCurrentAccount().name)
.param("categories-count", categorizationFragment.getCurrentSelectedCount()) .param("categories-count", categorizationFragment.getCurrentSelectedCount())
.param("files-count", photosList.size()) .param("files-count", photosList.size())
@ -296,7 +296,7 @@ public class MultipleShareActivity
.param("result", "cancelled") .param("result", "cancelled")
.log(); .log();
} else { } else {
EventLog.schema(CommonsApplication.EVENT_UPLOAD_ATTEMPT) EventLog.schema(CommonsApplication.EVENT_UPLOAD_ATTEMPT, CommonsApplication.getInstance())
.param("username", app.getCurrentAccount().name) .param("username", app.getCurrentAccount().name)
.param("source", getIntent().getStringExtra(UploadService.EXTRA_SOURCE)) .param("source", getIntent().getStringExtra(UploadService.EXTRA_SOURCE))
.param("multiple", true) .param("multiple", true)

View file

@ -27,7 +27,6 @@ import com.facebook.drawee.view.SimpleDraweeView;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -168,7 +167,7 @@ public class ShareActivity
// This is the wrong place for it, but bleh - better than not having it turned on by default for people who don't go throughl ogin // This is the wrong place for it, but bleh - better than not having it turned on by default for people who don't go throughl ogin
ContentResolver.setSyncAutomatically(app.getCurrentAccount(), ModificationsContentProvider.AUTHORITY, true); // Enable sync by default! ContentResolver.setSyncAutomatically(app.getCurrentAccount(), ModificationsContentProvider.AUTHORITY, true); // Enable sync by default!
EventLog.schema(CommonsApplication.EVENT_CATEGORIZATION_ATTEMPT) EventLog.schema(CommonsApplication.EVENT_CATEGORIZATION_ATTEMPT, CommonsApplication.getInstance())
.param("username", app.getCurrentAccount().name) .param("username", app.getCurrentAccount().name)
.param("categories-count", categories.size()) .param("categories-count", categories.size())
.param("files-count", 1) .param("files-count", 1)
@ -190,7 +189,7 @@ public class ShareActivity
public void onBackPressed() { public void onBackPressed() {
super.onBackPressed(); super.onBackPressed();
if(categorizationFragment != null && categorizationFragment.isVisible()) { if(categorizationFragment != null && categorizationFragment.isVisible()) {
EventLog.schema(CommonsApplication.EVENT_CATEGORIZATION_ATTEMPT) EventLog.schema(CommonsApplication.EVENT_CATEGORIZATION_ATTEMPT, CommonsApplication.getInstance())
.param("username", app.getCurrentAccount().name) .param("username", app.getCurrentAccount().name)
.param("categories-count", categorizationFragment.getCurrentSelectedCount()) .param("categories-count", categorizationFragment.getCurrentSelectedCount())
.param("files-count", 1) .param("files-count", 1)
@ -198,7 +197,7 @@ public class ShareActivity
.param("result", "cancelled") .param("result", "cancelled")
.log(); .log();
} else { } else {
EventLog.schema(CommonsApplication.EVENT_UPLOAD_ATTEMPT) EventLog.schema(CommonsApplication.EVENT_UPLOAD_ATTEMPT, CommonsApplication.getInstance())
.param("username", app.getCurrentAccount().name) .param("username", app.getCurrentAccount().name)
.param("source", getIntent().getStringExtra(UploadService.EXTRA_SOURCE)) .param("source", getIntent().getStringExtra(UploadService.EXTRA_SOURCE))
.param("multiple", true) .param("multiple", true)

View file

@ -247,7 +247,7 @@ public class UploadService extends HandlerService<Contribution> {
String resultStatus = uploadResult.getResultStatus(); String resultStatus = uploadResult.getResultStatus();
if (!resultStatus.equals("Success")) { if (!resultStatus.equals("Success")) {
showFailedNotification(contribution); showFailedNotification(contribution);
EventLog.schema(CommonsApplication.EVENT_UPLOAD_ATTEMPT) EventLog.schema(CommonsApplication.EVENT_UPLOAD_ATTEMPT, CommonsApplication.getInstance())
.param("username", app.getCurrentAccount().name) .param("username", app.getCurrentAccount().name)
.param("source", contribution.getSource()) .param("source", contribution.getSource())
.param("multiple", contribution.getMultiple()) .param("multiple", contribution.getMultiple())
@ -261,7 +261,7 @@ public class UploadService extends HandlerService<Contribution> {
contribution.setDateUploaded(uploadResult.getDateUploaded()); contribution.setDateUploaded(uploadResult.getDateUploaded());
contribution.save(); contribution.save();
EventLog.schema(CommonsApplication.EVENT_UPLOAD_ATTEMPT) EventLog.schema(CommonsApplication.EVENT_UPLOAD_ATTEMPT, CommonsApplication.getInstance())
.param("username", app.getCurrentAccount().name) .param("username", app.getCurrentAccount().name)
.param("source", contribution.getSource()) //FIXME .param("source", contribution.getSource()) //FIXME
.param("filename", contribution.getFilename()) .param("filename", contribution.getFilename())