mirror of
https://gitlab.com/xynngh/YetAnotherCallBlocker.git
synced 2025-06-05 22:19:12 +02:00
Refactoring
Decouple SIA from other stuff. Move SIA-related initialization to a separate class.
This commit is contained in:
@@ -4,8 +4,7 @@ import android.app.Application;
|
|||||||
|
|
||||||
import org.greenrobot.eventbus.EventBus;
|
import org.greenrobot.eventbus.EventBus;
|
||||||
|
|
||||||
import dummydomain.yetanothercallblocker.data.ContactsHelper;
|
import dummydomain.yetanothercallblocker.data.Config;
|
||||||
import dummydomain.yetanothercallblocker.data.DatabaseSingleton;
|
|
||||||
|
|
||||||
public class App extends Application {
|
public class App extends Application {
|
||||||
|
|
||||||
@@ -31,8 +30,7 @@ public class App extends Application {
|
|||||||
|
|
||||||
NotificationHelper.createNotificationChannels(this);
|
NotificationHelper.createNotificationChannels(this);
|
||||||
|
|
||||||
DatabaseSingleton.setContactsProvider(
|
Config.init(this, settings);
|
||||||
ContactsHelper.getContactsProvider(this, settings));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static App getInstance() {
|
public static App getInstance() {
|
||||||
|
@@ -0,0 +1,46 @@
|
|||||||
|
package dummydomain.yetanothercallblocker;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
|
||||||
|
public class GenericSettings {
|
||||||
|
|
||||||
|
protected final SharedPreferences pref;
|
||||||
|
|
||||||
|
public GenericSettings(Context context, String name) {
|
||||||
|
this(context.getSharedPreferences(name, Context.MODE_PRIVATE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public GenericSettings(SharedPreferences pref) {
|
||||||
|
this.pref = pref;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getBoolean(String key) {
|
||||||
|
return getBoolean(key, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getBoolean(String key, boolean defValue) {
|
||||||
|
return pref.getBoolean(key, defValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBoolean(String key, boolean value) {
|
||||||
|
pref.edit().putBoolean(key, value).apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getInt(String key, int defValue) {
|
||||||
|
return pref.getInt(key, defValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInt(String key, int value) {
|
||||||
|
pref.edit().putInt(key, value).apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLong(String key, long defValue) {
|
||||||
|
return pref.getLong(key, defValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLong(String key, long value) {
|
||||||
|
pref.edit().putLong(key, value).apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -15,8 +15,8 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import dummydomain.yetanothercallblocker.data.DatabaseSingleton;
|
||||||
import dummydomain.yetanothercallblocker.sia.model.CommunityReview;
|
import dummydomain.yetanothercallblocker.sia.model.CommunityReview;
|
||||||
import dummydomain.yetanothercallblocker.sia.model.CommunityReviewsLoader;
|
|
||||||
|
|
||||||
public class ReviewsActivity extends AppCompatActivity {
|
public class ReviewsActivity extends AppCompatActivity {
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ public class ReviewsActivity extends AppCompatActivity {
|
|||||||
= new AsyncTask<Void, Void, List<CommunityReview>>() {
|
= new AsyncTask<Void, Void, List<CommunityReview>>() {
|
||||||
@Override
|
@Override
|
||||||
protected List<CommunityReview> doInBackground(Void... voids) {
|
protected List<CommunityReview> doInBackground(Void... voids) {
|
||||||
return CommunityReviewsLoader.loadReviews(paramNumber);
|
return DatabaseSingleton.getCommunityReviewsLoader().loadReviews(paramNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -1,9 +1,8 @@
|
|||||||
package dummydomain.yetanothercallblocker;
|
package dummydomain.yetanothercallblocker;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
|
|
||||||
public class Settings {
|
public class Settings extends GenericSettings {
|
||||||
|
|
||||||
private static final String PREF_INCOMING_CALL_NOTIFICATIONS = "incomingCallNotifications";
|
private static final String PREF_INCOMING_CALL_NOTIFICATIONS = "incomingCallNotifications";
|
||||||
private static final String PREF_BLOCK_CALLS = "blockCalls";
|
private static final String PREF_BLOCK_CALLS = "blockCalls";
|
||||||
@@ -11,10 +10,8 @@ public class Settings {
|
|||||||
private static final String PREF_LAST_UPDATE_TIME = "lastUpdateTime";
|
private static final String PREF_LAST_UPDATE_TIME = "lastUpdateTime";
|
||||||
private static final String PREF_LAST_UPDATE_CHECK_TIME = "lastUpdateCheckTime";
|
private static final String PREF_LAST_UPDATE_CHECK_TIME = "lastUpdateCheckTime";
|
||||||
|
|
||||||
private final SharedPreferences pref;
|
|
||||||
|
|
||||||
Settings(Context context) {
|
Settings(Context context) {
|
||||||
pref = context.getSharedPreferences("yacb_preferences", Context.MODE_PRIVATE);
|
super(context, "yacb_preferences");
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getIncomingCallNotifications() {
|
public boolean getIncomingCallNotifications() {
|
||||||
@@ -57,24 +54,4 @@ public class Settings {
|
|||||||
setLong(PREF_LAST_UPDATE_CHECK_TIME, timestamp);
|
setLong(PREF_LAST_UPDATE_CHECK_TIME, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getBoolean(String key) {
|
|
||||||
return getBoolean(key, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getBoolean(String key, boolean defValue) {
|
|
||||||
return pref.getBoolean(key, defValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBoolean(String key, boolean value) {
|
|
||||||
pref.edit().putBoolean(key, value).apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getLong(String key, long defValue) {
|
|
||||||
return pref.getLong(key, defValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLong(String key, long value) {
|
|
||||||
pref.edit().putLong(key, value).apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,14 @@
|
|||||||
|
package dummydomain.yetanothercallblocker.data;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import dummydomain.yetanothercallblocker.GenericSettings;
|
||||||
|
import dummydomain.yetanothercallblocker.sia.Properties;
|
||||||
|
|
||||||
|
public class AndroidProperties extends GenericSettings implements Properties {
|
||||||
|
|
||||||
|
public AndroidProperties(Context context, String name) {
|
||||||
|
super(context, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,38 @@
|
|||||||
|
package dummydomain.yetanothercallblocker.data;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import dummydomain.yetanothercallblocker.sia.Storage;
|
||||||
|
|
||||||
|
public class AndroidStorage implements Storage {
|
||||||
|
|
||||||
|
private final Context context;
|
||||||
|
|
||||||
|
public AndroidStorage(Context context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDataDirPath() {
|
||||||
|
return context.getFilesDir().getAbsolutePath() + "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCacheDirPath() {
|
||||||
|
return context.getCacheDir().getAbsolutePath() + "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream openFile(String fileName, boolean internal) throws IOException {
|
||||||
|
if (internal) {
|
||||||
|
return context.getAssets().open(fileName);
|
||||||
|
} else {
|
||||||
|
return new FileInputStream(getDataDirPath() + fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,78 @@
|
|||||||
|
package dummydomain.yetanothercallblocker.data;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import dummydomain.yetanothercallblocker.PermissionHelper;
|
||||||
|
import dummydomain.yetanothercallblocker.sia.Settings;
|
||||||
|
import dummydomain.yetanothercallblocker.sia.SettingsImpl;
|
||||||
|
import dummydomain.yetanothercallblocker.sia.Storage;
|
||||||
|
import dummydomain.yetanothercallblocker.sia.model.CommunityReviewsLoader;
|
||||||
|
import dummydomain.yetanothercallblocker.sia.model.database.AbstractDatabase;
|
||||||
|
import dummydomain.yetanothercallblocker.sia.model.database.CommunityDatabase;
|
||||||
|
import dummydomain.yetanothercallblocker.sia.model.database.DbManager;
|
||||||
|
import dummydomain.yetanothercallblocker.sia.model.database.FeaturedDatabase;
|
||||||
|
import dummydomain.yetanothercallblocker.sia.network.WebService;
|
||||||
|
|
||||||
|
import static dummydomain.yetanothercallblocker.data.SiaConstants.SIA_PATH_PREFIX;
|
||||||
|
import static dummydomain.yetanothercallblocker.data.SiaConstants.SIA_PROPERTIES;
|
||||||
|
import static dummydomain.yetanothercallblocker.data.SiaConstants.SIA_SECONDARY_PATH_PREFIX;
|
||||||
|
|
||||||
|
public class Config {
|
||||||
|
|
||||||
|
private static class WSParameterProvider extends WebService.DefaultWSParameterProvider {
|
||||||
|
CommunityDatabase communityDatabase;
|
||||||
|
|
||||||
|
void setCommunityDatabase(CommunityDatabase communityDatabase) {
|
||||||
|
this.communityDatabase = communityDatabase;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAppId() {
|
||||||
|
return "qQq0O9nCRNy_aVdPgU9WOA";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAppVersion() {
|
||||||
|
return communityDatabase.getSiaAppVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDbVersion() {
|
||||||
|
return communityDatabase.getEffectiveDbVersion();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void init(Context context, dummydomain.yetanothercallblocker.Settings settings) {
|
||||||
|
Storage storage = new AndroidStorage(context);
|
||||||
|
Settings siaSettings
|
||||||
|
= new SettingsImpl(new AndroidProperties(context, SIA_PROPERTIES));
|
||||||
|
|
||||||
|
WSParameterProvider wsParameterProvider = new WSParameterProvider();
|
||||||
|
WebService webService = new WebService(wsParameterProvider);
|
||||||
|
|
||||||
|
DatabaseSingleton.setDbManager(new DbManager(storage, SIA_PATH_PREFIX));
|
||||||
|
|
||||||
|
CommunityDatabase communityDatabase = new CommunityDatabase(
|
||||||
|
storage, AbstractDatabase.Source.ANY, SIA_PATH_PREFIX,
|
||||||
|
SIA_SECONDARY_PATH_PREFIX, siaSettings, webService);
|
||||||
|
|
||||||
|
wsParameterProvider.setCommunityDatabase(communityDatabase);
|
||||||
|
DatabaseSingleton.setCommunityDatabase(communityDatabase);
|
||||||
|
|
||||||
|
DatabaseSingleton.setFeaturedDatabase(new FeaturedDatabase(
|
||||||
|
storage, AbstractDatabase.Source.ANY, SIA_PATH_PREFIX));
|
||||||
|
|
||||||
|
DatabaseSingleton.setCommunityReviewsLoader(
|
||||||
|
new CommunityReviewsLoader(webService, "US"));
|
||||||
|
|
||||||
|
DatabaseSingleton.setContactsProvider(number -> {
|
||||||
|
if (settings.getUseContacts() && PermissionHelper.hasContactsPermission(context)) {
|
||||||
|
String contactName = ContactsHelper.getContactName(context, number);
|
||||||
|
if (!TextUtils.isEmpty(contactName)) return new ContactItem(contactName);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -5,10 +5,6 @@ import android.content.Context;
|
|||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.provider.ContactsContract;
|
import android.provider.ContactsContract;
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import dummydomain.yetanothercallblocker.PermissionHelper;
|
|
||||||
import dummydomain.yetanothercallblocker.Settings;
|
|
||||||
|
|
||||||
public class ContactsHelper {
|
public class ContactsHelper {
|
||||||
|
|
||||||
@@ -16,16 +12,6 @@ public class ContactsHelper {
|
|||||||
ContactsContract.PhoneLookup.DISPLAY_NAME
|
ContactsContract.PhoneLookup.DISPLAY_NAME
|
||||||
};
|
};
|
||||||
|
|
||||||
public static ContactsProvider getContactsProvider(Context context, Settings settings) {
|
|
||||||
return number -> {
|
|
||||||
if (settings.getUseContacts() && PermissionHelper.hasContactsPermission(context)) {
|
|
||||||
String contactName = getContactName(context, number);
|
|
||||||
if (!TextUtils.isEmpty(contactName)) return new ContactItem(contactName);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getContactName(Context context, String number) {
|
public static String getContactName(Context context, String number) {
|
||||||
Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
|
Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
|
||||||
Uri.encode(number));
|
Uri.encode(number));
|
||||||
|
@@ -5,33 +5,61 @@ import android.text.TextUtils;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import dummydomain.yetanothercallblocker.sia.model.CommunityReviewsLoader;
|
||||||
import dummydomain.yetanothercallblocker.sia.model.database.CommunityDatabase;
|
import dummydomain.yetanothercallblocker.sia.model.database.CommunityDatabase;
|
||||||
import dummydomain.yetanothercallblocker.sia.model.database.CommunityDatabaseItem;
|
import dummydomain.yetanothercallblocker.sia.model.database.CommunityDatabaseItem;
|
||||||
|
import dummydomain.yetanothercallblocker.sia.model.database.DbManager;
|
||||||
import dummydomain.yetanothercallblocker.sia.model.database.FeaturedDatabase;
|
import dummydomain.yetanothercallblocker.sia.model.database.FeaturedDatabase;
|
||||||
import dummydomain.yetanothercallblocker.sia.model.database.FeaturedDatabaseItem;
|
import dummydomain.yetanothercallblocker.sia.model.database.FeaturedDatabaseItem;
|
||||||
|
|
||||||
import static dummydomain.yetanothercallblocker.sia.SiaConstants.SIA_PATH_PREFIX;
|
public class DatabaseSingleton {
|
||||||
import static dummydomain.yetanothercallblocker.sia.SiaConstants.SIA_SECONDARY_PATH_PREFIX;
|
|
||||||
|
|
||||||
public class DatabaseSingleton { // TODO: rewrite
|
|
||||||
|
|
||||||
private static final CommunityDatabase COMMUNITY_DATABASE = new CommunityDatabase(SIA_PATH_PREFIX, SIA_SECONDARY_PATH_PREFIX);
|
|
||||||
private static final FeaturedDatabase FEATURED_DATABASE = new FeaturedDatabase(SIA_PATH_PREFIX);
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(DatabaseSingleton.class);
|
private static final Logger LOG = LoggerFactory.getLogger(DatabaseSingleton.class);
|
||||||
|
|
||||||
|
private static DbManager dbManager;
|
||||||
|
|
||||||
|
private static CommunityDatabase communityDatabase;
|
||||||
|
|
||||||
|
private static FeaturedDatabase featuredDatabase;
|
||||||
|
|
||||||
|
private static CommunityReviewsLoader communityReviewsLoader;
|
||||||
|
|
||||||
private static ContactsProvider contactsProvider;
|
private static ContactsProvider contactsProvider;
|
||||||
|
|
||||||
|
static void setDbManager(DbManager dbManager) {
|
||||||
|
DatabaseSingleton.dbManager = dbManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setCommunityDatabase(CommunityDatabase communityDatabase) {
|
||||||
|
DatabaseSingleton.communityDatabase = communityDatabase;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setFeaturedDatabase(FeaturedDatabase featuredDatabase) {
|
||||||
|
DatabaseSingleton.featuredDatabase = featuredDatabase;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setCommunityReviewsLoader(CommunityReviewsLoader communityReviewsLoader) {
|
||||||
|
DatabaseSingleton.communityReviewsLoader = communityReviewsLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setContactsProvider(ContactsProvider contactsProvider) {
|
||||||
|
DatabaseSingleton.contactsProvider = contactsProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DbManager getDbManager() {
|
||||||
|
return dbManager;
|
||||||
|
}
|
||||||
|
|
||||||
public static CommunityDatabase getCommunityDatabase() {
|
public static CommunityDatabase getCommunityDatabase() {
|
||||||
return COMMUNITY_DATABASE;
|
return communityDatabase;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FeaturedDatabase getFeaturedDatabase() {
|
public static FeaturedDatabase getFeaturedDatabase() {
|
||||||
return FEATURED_DATABASE;
|
return featuredDatabase;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setContactsProvider(ContactsProvider contactsProvider) {
|
public static CommunityReviewsLoader getCommunityReviewsLoader() {
|
||||||
DatabaseSingleton.contactsProvider = contactsProvider;
|
return communityReviewsLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NumberInfo getNumberInfo(String number) {
|
public static NumberInfo getNumberInfo(String number) {
|
||||||
@@ -46,7 +74,7 @@ public class DatabaseSingleton { // TODO: rewrite
|
|||||||
.getDbItemByNumber(number);
|
.getDbItemByNumber(number);
|
||||||
LOG.trace("getNumberInfo() featuredItem={}", featuredItem);
|
LOG.trace("getNumberInfo() featuredItem={}", featuredItem);
|
||||||
|
|
||||||
ContactItem contactItem = contactsProvider != null ? contactsProvider.get(number) : null;
|
ContactItem contactItem = DatabaseSingleton.contactsProvider.get(number);
|
||||||
LOG.trace("getNumberInfo() contactItem={}", contactItem);
|
LOG.trace("getNumberInfo() contactItem={}", contactItem);
|
||||||
|
|
||||||
NumberInfo numberInfo = new NumberInfo();
|
NumberInfo numberInfo = new NumberInfo();
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
package dummydomain.yetanothercallblocker.sia;
|
package dummydomain.yetanothercallblocker.data;
|
||||||
|
|
||||||
public interface SiaConstants {
|
public interface SiaConstants {
|
||||||
|
|
||||||
|
String SIA_PROPERTIES = "sia_preferences";
|
||||||
String SIA_PATH_PREFIX = "sia/";
|
String SIA_PATH_PREFIX = "sia/";
|
||||||
String SIA_SECONDARY_PATH_PREFIX = "sia-secondary/";
|
String SIA_SECONDARY_PATH_PREFIX = "sia-secondary/";
|
||||||
|
|
@@ -0,0 +1,9 @@
|
|||||||
|
package dummydomain.yetanothercallblocker.sia;
|
||||||
|
|
||||||
|
public interface Properties {
|
||||||
|
|
||||||
|
int getInt(String key, int defValue);
|
||||||
|
|
||||||
|
void setInt(String key, int value);
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,13 @@
|
|||||||
|
package dummydomain.yetanothercallblocker.sia;
|
||||||
|
|
||||||
|
public interface Settings {
|
||||||
|
|
||||||
|
int getBaseDbVersion();
|
||||||
|
|
||||||
|
void setBaseDbVersion(int version);
|
||||||
|
|
||||||
|
int getSecondaryDbVersion();
|
||||||
|
|
||||||
|
void setSecondaryDbVersion(int version);
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,34 @@
|
|||||||
|
package dummydomain.yetanothercallblocker.sia;
|
||||||
|
|
||||||
|
public class SettingsImpl implements Settings {
|
||||||
|
|
||||||
|
private static final String PREF_BASE_DB_VERSION = "baseDbVersion";
|
||||||
|
private static final String PREF_SECONDARY_DB_VERSION = "secondaryDbVersion";
|
||||||
|
|
||||||
|
private final Properties props;
|
||||||
|
|
||||||
|
public SettingsImpl(Properties props) {
|
||||||
|
this.props = props;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBaseDbVersion() {
|
||||||
|
return props.getInt(PREF_BASE_DB_VERSION, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBaseDbVersion(int version) {
|
||||||
|
props.setInt(PREF_BASE_DB_VERSION, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSecondaryDbVersion() {
|
||||||
|
return props.getInt(PREF_SECONDARY_DB_VERSION, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSecondaryDbVersion(int version) {
|
||||||
|
props.setInt(PREF_SECONDARY_DB_VERSION, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,33 +0,0 @@
|
|||||||
package dummydomain.yetanothercallblocker.sia;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
|
|
||||||
public class SiaSettings {
|
|
||||||
|
|
||||||
private static final String PREF_BASE_DB_VERSION = "baseDbVersion";
|
|
||||||
private static final String PREF_SECONDARY_DB_VERSION = "secondaryDbVersion";
|
|
||||||
|
|
||||||
private final SharedPreferences pref;
|
|
||||||
|
|
||||||
public SiaSettings(Context context) {
|
|
||||||
pref = context.getSharedPreferences("sia_preferences", Context.MODE_PRIVATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getBaseDbVersion() {
|
|
||||||
return pref.getInt(PREF_BASE_DB_VERSION, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBaseDbVersion(int version) {
|
|
||||||
pref.edit().putInt(PREF_BASE_DB_VERSION, version).apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSecondaryDbVersion() {
|
|
||||||
return pref.getInt(PREF_SECONDARY_DB_VERSION, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSecondaryDbVersion(int version) {
|
|
||||||
pref.edit().putInt(PREF_SECONDARY_DB_VERSION, version).apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -0,0 +1,14 @@
|
|||||||
|
package dummydomain.yetanothercallblocker.sia;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public interface Storage {
|
||||||
|
|
||||||
|
String getDataDirPath();
|
||||||
|
|
||||||
|
String getCacheDirPath();
|
||||||
|
|
||||||
|
InputStream openFile(String fileName, boolean internal) throws IOException;
|
||||||
|
|
||||||
|
}
|
@@ -17,7 +17,15 @@ public class CommunityReviewsLoader {
|
|||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(CommunityReviewsLoader.class);
|
private static final Logger LOG = LoggerFactory.getLogger(CommunityReviewsLoader.class);
|
||||||
|
|
||||||
public static List<CommunityReview> loadReviews(String number) {
|
private final WebService webService;
|
||||||
|
private final String country;
|
||||||
|
|
||||||
|
public CommunityReviewsLoader(WebService webService, String country) {
|
||||||
|
this.webService = webService;
|
||||||
|
this.country = country;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<CommunityReview> loadReviews(String number) {
|
||||||
LOG.debug("loadReviews({}) started", number);
|
LOG.debug("loadReviews({}) started", number);
|
||||||
|
|
||||||
if (number.startsWith("+")) {
|
if (number.startsWith("+")) {
|
||||||
@@ -26,9 +34,9 @@ public class CommunityReviewsLoader {
|
|||||||
|
|
||||||
Map<String, String> params = new HashMap<>();
|
Map<String, String> params = new HashMap<>();
|
||||||
params.put("number", number);
|
params.put("number", number);
|
||||||
params.put("country", "RU"); // TODO: fix: hardcode
|
params.put("country", country);
|
||||||
|
|
||||||
WebService.WSResponse response = WebService.callForJson(WebService.getGetReviewsUrlPart(), params);
|
WebService.WSResponse response = webService.callForJson(webService.getGetReviewsUrlPart(), params);
|
||||||
|
|
||||||
List<CommunityReview> reviews = new ArrayList<>();
|
List<CommunityReview> reviews = new ArrayList<>();
|
||||||
|
|
||||||
|
@@ -11,15 +11,21 @@ import java.io.FileNotFoundException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
import static dummydomain.yetanothercallblocker.sia.utils.FileUtils.openFile;
|
import dummydomain.yetanothercallblocker.sia.Storage;
|
||||||
|
|
||||||
public abstract class AbstractDatabase<T extends AbstractDatabaseDataSlice<V>, V> {
|
public abstract class AbstractDatabase<T extends AbstractDatabaseDataSlice<V>, V> {
|
||||||
|
|
||||||
|
public enum Source {
|
||||||
|
INTERNAL, EXTERNAL, ANY
|
||||||
|
}
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(AbstractDatabase.class);
|
private static final Logger LOG = LoggerFactory.getLogger(AbstractDatabase.class);
|
||||||
|
|
||||||
|
protected final Storage storage;
|
||||||
|
protected final Source source;
|
||||||
protected final String pathPrefix;
|
protected final String pathPrefix;
|
||||||
|
|
||||||
protected boolean useAssets;
|
protected boolean useInternal;
|
||||||
|
|
||||||
protected int baseDatabaseVersion;
|
protected int baseDatabaseVersion;
|
||||||
protected int numberOfItems;
|
protected int numberOfItems;
|
||||||
@@ -31,7 +37,9 @@ public abstract class AbstractDatabase<T extends AbstractDatabaseDataSlice<V>, V
|
|||||||
protected boolean loaded;
|
protected boolean loaded;
|
||||||
protected boolean failedToLoad;
|
protected boolean failedToLoad;
|
||||||
|
|
||||||
public AbstractDatabase(String pathPrefix) {
|
public AbstractDatabase(Storage storage, Source source, String pathPrefix) {
|
||||||
|
this.storage = storage;
|
||||||
|
this.source = source;
|
||||||
this.pathPrefix = pathPrefix;
|
this.pathPrefix = pathPrefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,12 +80,12 @@ public abstract class AbstractDatabase<T extends AbstractDatabaseDataSlice<V>, V
|
|||||||
|
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
if (load(true)) {
|
if ((source == Source.ANY || source == Source.INTERNAL) && load(true)) {
|
||||||
useAssets = true;
|
useInternal = true;
|
||||||
loaded = true;
|
loaded = true;
|
||||||
return true;
|
return true;
|
||||||
} else if (load(false)) {
|
} else if ((source == Source.ANY || source == Source.EXTERNAL) && load(false)) {
|
||||||
useAssets = false;
|
useInternal = false;
|
||||||
loaded = true;
|
loaded = true;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@@ -87,10 +95,10 @@ public abstract class AbstractDatabase<T extends AbstractDatabaseDataSlice<V>, V
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean load(boolean useAssets) {
|
protected boolean load(boolean useInternal) {
|
||||||
if (loadInfoData(useAssets) && loadSliceListData(useAssets)) {
|
if (loadInfoData(useInternal) && loadSliceListData(useInternal)) {
|
||||||
LOG.info("load() loaded DB useAssets={}, baseDatabaseVersion={}, numberOfItems={}",
|
LOG.info("load() loaded DB useInternal={}, baseDatabaseVersion={}, numberOfItems={}",
|
||||||
useAssets, this.baseDatabaseVersion, this.numberOfItems);
|
useInternal, this.baseDatabaseVersion, this.numberOfItems);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -102,12 +110,12 @@ public abstract class AbstractDatabase<T extends AbstractDatabaseDataSlice<V>, V
|
|||||||
|
|
||||||
protected abstract String getNamePrefix();
|
protected abstract String getNamePrefix();
|
||||||
|
|
||||||
protected boolean loadInfoData(boolean useAssets) {
|
protected boolean loadInfoData(boolean useInternal) {
|
||||||
LOG.debug("loadInfoData() started; useAssets: {}", useAssets);
|
LOG.debug("loadInfoData() started; useInternal: {}", useInternal);
|
||||||
|
|
||||||
String fileName = getPathPrefix() + getNamePrefix() + "info.dat";
|
String fileName = getPathPrefix() + getNamePrefix() + "info.dat";
|
||||||
|
|
||||||
try (InputStream is = openFile(fileName, useAssets);
|
try (InputStream is = storage.openFile(fileName, useInternal);
|
||||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is))) {
|
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is))) {
|
||||||
|
|
||||||
String headerString = bufferedReader.readLine();
|
String headerString = bufferedReader.readLine();
|
||||||
@@ -130,7 +138,7 @@ public abstract class AbstractDatabase<T extends AbstractDatabaseDataSlice<V>, V
|
|||||||
LOG.debug("loadInfoData() loaded MDI, baseDatabaseVersion={}, numberOfItems={}",
|
LOG.debug("loadInfoData() loaded MDI, baseDatabaseVersion={}, numberOfItems={}",
|
||||||
this.baseDatabaseVersion, this.numberOfItems);
|
this.baseDatabaseVersion, this.numberOfItems);
|
||||||
|
|
||||||
loadInfoDataAfterLoadedHook(useAssets);
|
loadInfoDataAfterLoadedHook(useInternal);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
@@ -142,13 +150,13 @@ public abstract class AbstractDatabase<T extends AbstractDatabaseDataSlice<V>, V
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void loadInfoDataAfterLoadedHook(boolean useAssets) {}
|
protected void loadInfoDataAfterLoadedHook(boolean useInternal) {}
|
||||||
|
|
||||||
protected boolean loadSliceListData(boolean useAssets) {
|
protected boolean loadSliceListData(boolean useInternal) {
|
||||||
LOG.debug("loadSliceListData() started");
|
LOG.debug("loadSliceListData() started");
|
||||||
|
|
||||||
String fileName = getPathPrefix() + getNamePrefix() + "list.dat";
|
String fileName = getPathPrefix() + getNamePrefix() + "list.dat";
|
||||||
try (InputStream is = openFile(fileName, useAssets);
|
try (InputStream is = storage.openFile(fileName, useInternal);
|
||||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is))) {
|
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is))) {
|
||||||
String nodes = bufferedReader.readLine();
|
String nodes = bufferedReader.readLine();
|
||||||
|
|
||||||
@@ -221,13 +229,13 @@ public abstract class AbstractDatabase<T extends AbstractDatabaseDataSlice<V>, V
|
|||||||
LOG.debug("loadSlice() started with sliceId={}", sliceId);
|
LOG.debug("loadSlice() started with sliceId={}", sliceId);
|
||||||
|
|
||||||
String fileName = getPathPrefix() + getNamePrefix() + sliceId + ".dat";
|
String fileName = getPathPrefix() + getNamePrefix() + sliceId + ".dat";
|
||||||
loadSlice(slice, fileName, useAssets);
|
loadSlice(slice, fileName, useInternal);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void loadSlice(T slice, String fileName, boolean useAssets) {
|
protected void loadSlice(T slice, String fileName, boolean useInternal) {
|
||||||
LOG.debug("loadSlice() started with fileName={}, useAssets={}", fileName, useAssets);
|
LOG.debug("loadSlice() started with fileName={}, useInternal={}", fileName, useInternal);
|
||||||
|
|
||||||
try (InputStream is = openFile(fileName, useAssets);
|
try (InputStream is = storage.openFile(fileName, useInternal);
|
||||||
BufferedInputStream stream = new BufferedInputStream(is)) {
|
BufferedInputStream stream = new BufferedInputStream(is)) {
|
||||||
|
|
||||||
slice.loadFromStream(stream);
|
slice.loadFromStream(stream);
|
||||||
|
@@ -1,9 +1,10 @@
|
|||||||
package dummydomain.yetanothercallblocker.sia.model.database;
|
package dummydomain.yetanothercallblocker.sia.model.database;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -22,17 +23,14 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.GZIPInputStream;
|
||||||
|
|
||||||
|
import dummydomain.yetanothercallblocker.sia.Settings;
|
||||||
|
import dummydomain.yetanothercallblocker.sia.Storage;
|
||||||
import dummydomain.yetanothercallblocker.sia.network.WebService;
|
import dummydomain.yetanothercallblocker.sia.network.WebService;
|
||||||
import dummydomain.yetanothercallblocker.sia.utils.FileUtils;
|
import dummydomain.yetanothercallblocker.sia.utils.FileUtils;
|
||||||
import dummydomain.yetanothercallblocker.sia.utils.Utils;
|
|
||||||
import okhttp3.MediaType;
|
import okhttp3.MediaType;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
import okhttp3.ResponseBody;
|
import okhttp3.ResponseBody;
|
||||||
|
|
||||||
import static dummydomain.yetanothercallblocker.sia.utils.FileUtils.getDataDir;
|
|
||||||
import static dummydomain.yetanothercallblocker.sia.utils.FileUtils.getDataDirPath;
|
|
||||||
import static dummydomain.yetanothercallblocker.sia.utils.FileUtils.openFile;
|
|
||||||
|
|
||||||
public class CommunityDatabase extends AbstractDatabase<CommunityDatabaseDataSlice, CommunityDatabaseItem> {
|
public class CommunityDatabase extends AbstractDatabase<CommunityDatabaseDataSlice, CommunityDatabaseItem> {
|
||||||
|
|
||||||
private enum UpdateResult {
|
private enum UpdateResult {
|
||||||
@@ -45,22 +43,28 @@ public class CommunityDatabase extends AbstractDatabase<CommunityDatabaseDataSli
|
|||||||
|
|
||||||
private int siaAppVersion = FALLBACK_APP_VERSION;
|
private int siaAppVersion = FALLBACK_APP_VERSION;
|
||||||
|
|
||||||
protected final String secondaryPathPrefix;
|
private final String secondaryPathPrefix;
|
||||||
|
private final Settings settings;
|
||||||
|
private final WebService webService;
|
||||||
|
|
||||||
private SparseArray<CommunityDatabaseDataSlice> secondarySliceCache = new SparseArray<>();
|
private SparseArray<CommunityDatabaseDataSlice> secondarySliceCache = new SparseArray<>();
|
||||||
|
|
||||||
@SuppressLint("UseSparseArrays") // uses null as a special value
|
@SuppressLint("UseSparseArrays") // uses null as a special value
|
||||||
private SparseArray<Boolean> existingSecondarySliceFiles = new SparseArray<>();
|
private SparseArray<Boolean> existingSecondarySliceFiles = new SparseArray<>();
|
||||||
|
|
||||||
public CommunityDatabase(String pathPrefix, String secondaryPathPrefix) {
|
public CommunityDatabase(Storage storage, Source source,
|
||||||
super(pathPrefix);
|
String pathPrefix, String secondaryPathPrefix,
|
||||||
|
Settings settings, WebService webService) {
|
||||||
|
super(storage, source, pathPrefix);
|
||||||
this.secondaryPathPrefix = secondaryPathPrefix;
|
this.secondaryPathPrefix = secondaryPathPrefix;
|
||||||
|
this.settings = settings;
|
||||||
|
this.webService = webService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getEffectiveDbVersion() {
|
public int getEffectiveDbVersion() {
|
||||||
checkLoaded();
|
checkLoaded();
|
||||||
|
|
||||||
int secondaryDbVersion = Utils.getSettings().getSecondaryDbVersion();
|
int secondaryDbVersion = settings.getSecondaryDbVersion();
|
||||||
return secondaryDbVersion > 0 ? secondaryDbVersion : baseDatabaseVersion;
|
return secondaryDbVersion > 0 ? secondaryDbVersion : baseDatabaseVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,13 +87,13 @@ public class CommunityDatabase extends AbstractDatabase<CommunityDatabaseDataSli
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean load(boolean useAssets) {
|
protected boolean load(boolean useInternal) {
|
||||||
if (!super.load(useAssets)) return false;
|
if (!super.load(useInternal)) return false;
|
||||||
|
|
||||||
LOG.debug("load() started; useAssets={}", useAssets);
|
LOG.debug("load() started; useInternal={}", useInternal);
|
||||||
|
|
||||||
String fileName = getPathPrefix() + "sia_info.dat";
|
String fileName = getPathPrefix() + "sia_info.dat";
|
||||||
try (InputStream is = openFile(fileName, useAssets);
|
try (InputStream is = storage.openFile(fileName, useInternal);
|
||||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is))) {
|
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is))) {
|
||||||
|
|
||||||
if (!"SIA".equals(bufferedReader.readLine())) {
|
if (!"SIA".equals(bufferedReader.readLine())) {
|
||||||
@@ -109,13 +113,13 @@ public class CommunityDatabase extends AbstractDatabase<CommunityDatabaseDataSli
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void loadInfoDataAfterLoadedHook(boolean useAssets) {
|
protected void loadInfoDataAfterLoadedHook(boolean useInternal) {
|
||||||
int oldDbVersion = Utils.getSettings().getBaseDbVersion();
|
int oldDbVersion = settings.getBaseDbVersion();
|
||||||
if (baseDatabaseVersion != oldDbVersion) {
|
if (baseDatabaseVersion != oldDbVersion) {
|
||||||
LOG.info("loadInfoDataAfterLoadedHook() base version changed; resetting secondary DB;" +
|
LOG.info("loadInfoDataAfterLoadedHook() base version changed; resetting secondary DB;" +
|
||||||
" oldDbVersion={}, baseDatabaseVersion={}", oldDbVersion, baseDatabaseVersion);
|
" oldDbVersion={}, baseDatabaseVersion={}", oldDbVersion, baseDatabaseVersion);
|
||||||
resetSecondaryDatabase();
|
resetSecondaryDatabase();
|
||||||
Utils.getSettings().setBaseDbVersion(baseDatabaseVersion);
|
settings.setBaseDbVersion(baseDatabaseVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,7 +186,7 @@ public class CommunityDatabase extends AbstractDatabase<CommunityDatabaseDataSli
|
|||||||
String path = getSecondarySliceFilePath(id);
|
String path = getSecondarySliceFilePath(id);
|
||||||
Boolean exists = existingSecondarySliceFiles.get(id, null);
|
Boolean exists = existingSecondarySliceFiles.get(id, null);
|
||||||
if (exists == null) {
|
if (exists == null) {
|
||||||
exists = new File(getDataDirPath() + path).exists();
|
exists = new File(storage.getDataDirPath() + path).exists();
|
||||||
existingSecondarySliceFiles.put(id, exists);
|
existingSecondarySliceFiles.put(id, exists);
|
||||||
}
|
}
|
||||||
return exists ? path : null;
|
return exists ? path : null;
|
||||||
@@ -195,7 +199,7 @@ public class CommunityDatabase extends AbstractDatabase<CommunityDatabaseDataSli
|
|||||||
public void resetSecondaryDatabase() {
|
public void resetSecondaryDatabase() {
|
||||||
LOG.debug("resetSecondaryDatabase() started");
|
LOG.debug("resetSecondaryDatabase() started");
|
||||||
|
|
||||||
File dir = new File(getDataDir(), getSecondaryDbPathPrefix());
|
File dir = new File(storage.getDataDirPath(), getSecondaryDbPathPrefix());
|
||||||
if (dir.exists()) {
|
if (dir.exists()) {
|
||||||
for (File file : dir.listFiles()) {
|
for (File file : dir.listFiles()) {
|
||||||
if (!file.delete()) {
|
if (!file.delete()) {
|
||||||
@@ -206,17 +210,17 @@ public class CommunityDatabase extends AbstractDatabase<CommunityDatabaseDataSli
|
|||||||
|
|
||||||
secondarySliceCache.clear();
|
secondarySliceCache.clear();
|
||||||
existingSecondarySliceFiles.clear();
|
existingSecondarySliceFiles.clear();
|
||||||
Utils.getSettings().setSecondaryDbVersion(0);
|
settings.setSecondaryDbVersion(0);
|
||||||
|
|
||||||
LOG.info("resetSecondaryDatabase() secondary DB was reset");
|
LOG.info("resetSecondaryDatabase() secondary DB was reset");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getSecondaryDbPathPrefix() {
|
private String getSecondaryDbPathPrefix() {
|
||||||
return secondaryPathPrefix;
|
return secondaryPathPrefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void createSecondaryDbDirectory() {
|
private void createSecondaryDbDirectory() {
|
||||||
FileUtils.createDirectory(getDataDir(), getSecondaryDbPathPrefix());
|
FileUtils.createDirectory(storage.getDataDirPath(), getSecondaryDbPathPrefix());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean updateSecondaryDb() {
|
public boolean updateSecondaryDb() {
|
||||||
@@ -262,10 +266,10 @@ public class CommunityDatabase extends AbstractDatabase<CommunityDatabaseDataSli
|
|||||||
LOG.debug("updateSecondaryDbInternal() effectiveDbVersion={}", effectiveDbVersion);
|
LOG.debug("updateSecondaryDbInternal() effectiveDbVersion={}", effectiveDbVersion);
|
||||||
|
|
||||||
String dbVersionParam = "_dbVer=" + effectiveDbVersion;
|
String dbVersionParam = "_dbVer=" + effectiveDbVersion;
|
||||||
String urlPath = WebService.getGetDatabaseUrlPart() + "/cached?" + dbVersionParam;
|
String urlPath = webService.getGetDatabaseUrlPart() + "/cached?" + dbVersionParam;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Response response = WebService.call(urlPath, new HashMap<>());
|
Response response = webService.call(urlPath, new HashMap<>());
|
||||||
if (response != null) {
|
if (response != null) {
|
||||||
ResponseBody body = response.body();
|
ResponseBody body = response.body();
|
||||||
MediaType contentType = body.contentType();
|
MediaType contentType = body.contentType();
|
||||||
@@ -274,7 +278,8 @@ public class CommunityDatabase extends AbstractDatabase<CommunityDatabaseDataSli
|
|||||||
if (contentType != null && "application".equals(contentType.type())) {
|
if (contentType != null && "application".equals(contentType.type())) {
|
||||||
LOG.trace("updateSecondaryDbInternal() saving response data to file");
|
LOG.trace("updateSecondaryDbInternal() saving response data to file");
|
||||||
|
|
||||||
File tempFile = File.createTempFile("sia", "database", Utils.getContext().getCacheDir());
|
File tempFile = File.createTempFile("sia", "database",
|
||||||
|
new File(storage.getCacheDirPath()));
|
||||||
|
|
||||||
int totalRead = 0;
|
int totalRead = 0;
|
||||||
try (InputStream in = body.byteStream();
|
try (InputStream in = body.byteStream();
|
||||||
@@ -371,7 +376,7 @@ public class CommunityDatabase extends AbstractDatabase<CommunityDatabaseDataSli
|
|||||||
}
|
}
|
||||||
|
|
||||||
try (BufferedOutputStream stream = new BufferedOutputStream(
|
try (BufferedOutputStream stream = new BufferedOutputStream(
|
||||||
new FileOutputStream(getDataDirPath() + filePath + ".update", false))) {
|
new FileOutputStream(storage.getDataDirPath() + filePath + ".update", false))) {
|
||||||
sliceFromExistingFile.writeMerged(newSlice, stream);
|
sliceFromExistingFile.writeMerged(newSlice, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,7 +389,7 @@ public class CommunityDatabase extends AbstractDatabase<CommunityDatabaseDataSli
|
|||||||
LOG.debug("updateSecondaryWithSlice() update files created, renaming files");
|
LOG.debug("updateSecondaryWithSlice() update files created, renaming files");
|
||||||
|
|
||||||
for (int sliceId : updatedIndexes) {
|
for (int sliceId : updatedIndexes) {
|
||||||
String filePath = getDataDirPath() + getSecondarySliceFilePath(sliceId);
|
String filePath = storage.getDataDirPath() + getSecondarySliceFilePath(sliceId);
|
||||||
|
|
||||||
File updatedFile = new File(filePath + ".update");
|
File updatedFile = new File(filePath + ".update");
|
||||||
File oldFile = new File(filePath);
|
File oldFile = new File(filePath);
|
||||||
@@ -396,7 +401,7 @@ public class CommunityDatabase extends AbstractDatabase<CommunityDatabaseDataSli
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils.getSettings().setSecondaryDbVersion(dataSlice.getDbVersion());
|
settings.setSecondaryDbVersion(dataSlice.getDbVersion());
|
||||||
secondarySliceCache.clear();
|
secondarySliceCache.clear();
|
||||||
existingSecondarySliceFiles.clear();
|
existingSecondarySliceFiles.clear();
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
import dummydomain.yetanothercallblocker.sia.SiaConstants;
|
import dummydomain.yetanothercallblocker.sia.Storage;
|
||||||
import dummydomain.yetanothercallblocker.sia.network.DbDownloader;
|
import dummydomain.yetanothercallblocker.sia.network.DbDownloader;
|
||||||
import dummydomain.yetanothercallblocker.sia.utils.FileUtils;
|
import dummydomain.yetanothercallblocker.sia.utils.FileUtils;
|
||||||
|
|
||||||
@@ -13,17 +13,26 @@ public class DbManager {
|
|||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(DbManager.class);
|
private static final Logger LOG = LoggerFactory.getLogger(DbManager.class);
|
||||||
|
|
||||||
public static boolean downloadMainDb() {
|
private static final String DEFAULT_URL = "https://gitlab.com/xynngh/YetAnotherCallBlocker_data/raw/zip_v1/archives/sia.zip";
|
||||||
String url = "https://gitlab.com/xynngh/YetAnotherCallBlocker_data/raw/zip_v1/archives/sia.zip";
|
|
||||||
return downloadMainDb(url);
|
private final Storage storage;
|
||||||
|
private final String pathPrefix;
|
||||||
|
|
||||||
|
public DbManager(Storage storage, String pathPrefix) {
|
||||||
|
this.storage = storage;
|
||||||
|
this.pathPrefix = pathPrefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean downloadMainDb(String url) {
|
public boolean downloadMainDb() {
|
||||||
|
return downloadMainDb(DEFAULT_URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean downloadMainDb(String url) {
|
||||||
LOG.debug("downloadMainDb() started");
|
LOG.debug("downloadMainDb() started");
|
||||||
|
|
||||||
File dataDir = FileUtils.getDataDir();
|
File dataDir = new File(storage.getDataDirPath());
|
||||||
|
|
||||||
String siaDir = SiaConstants.SIA_PATH_PREFIX;
|
String siaDir = pathPrefix;
|
||||||
String tmpUpdateDir = siaDir.substring(0, siaDir.indexOf('/')) + "-tmp/";
|
String tmpUpdateDir = siaDir.substring(0, siaDir.indexOf('/')) + "-tmp/";
|
||||||
String oldDir = siaDir.substring(0, siaDir.indexOf('/')) + "-old/";
|
String oldDir = siaDir.substring(0, siaDir.indexOf('/')) + "-old/";
|
||||||
|
|
||||||
@@ -31,7 +40,7 @@ public class DbManager {
|
|||||||
FileUtils.createDirectory(dataDir, tmpUpdateDir);
|
FileUtils.createDirectory(dataDir, tmpUpdateDir);
|
||||||
LOG.debug("downloadMainDb() prepared dirs");
|
LOG.debug("downloadMainDb() prepared dirs");
|
||||||
|
|
||||||
if (DbDownloader.download(url, FileUtils.getDataDirPath() + tmpUpdateDir)) {
|
if (DbDownloader.download(url, storage.getDataDirPath() + tmpUpdateDir)) {
|
||||||
LOG.debug("downloadMainDb() downloaded and unpacked");
|
LOG.debug("downloadMainDb() downloaded and unpacked");
|
||||||
|
|
||||||
File old = new File(dataDir, siaDir);
|
File old = new File(dataDir, siaDir);
|
||||||
|
@@ -1,9 +1,11 @@
|
|||||||
package dummydomain.yetanothercallblocker.sia.model.database;
|
package dummydomain.yetanothercallblocker.sia.model.database;
|
||||||
|
|
||||||
|
import dummydomain.yetanothercallblocker.sia.Storage;
|
||||||
|
|
||||||
public class FeaturedDatabase extends AbstractDatabase<FeaturedDatabaseDataSlice, FeaturedDatabaseItem> {
|
public class FeaturedDatabase extends AbstractDatabase<FeaturedDatabaseDataSlice, FeaturedDatabaseItem> {
|
||||||
|
|
||||||
public FeaturedDatabase(String pathPrefix) {
|
public FeaturedDatabase(Storage storage, Source source, String pathPrefix) {
|
||||||
super(pathPrefix);
|
super(storage, source, pathPrefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -1,7 +1,5 @@
|
|||||||
package dummydomain.yetanothercallblocker.sia.network;
|
package dummydomain.yetanothercallblocker.sia.network;
|
||||||
|
|
||||||
import android.os.Build;
|
|
||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -20,6 +18,52 @@ import okhttp3.ResponseBody;
|
|||||||
|
|
||||||
public class WebService {
|
public class WebService {
|
||||||
|
|
||||||
|
public interface WSParameterProvider {
|
||||||
|
String getAppId();
|
||||||
|
|
||||||
|
String getDevice();
|
||||||
|
String getModel();
|
||||||
|
String getManufacturer();
|
||||||
|
int getAndroidApi();
|
||||||
|
|
||||||
|
String getAppFamily();
|
||||||
|
int getAppVersion();
|
||||||
|
int getDbVersion();
|
||||||
|
String getCountry();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static abstract class DefaultWSParameterProvider implements WSParameterProvider {
|
||||||
|
@Override
|
||||||
|
public String getDevice() {
|
||||||
|
return "dreamlte";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getModel() {
|
||||||
|
return "SM-G950F";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getManufacturer() {
|
||||||
|
return "Samsung";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAndroidApi() {
|
||||||
|
return 26;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAppFamily() {
|
||||||
|
return "SIA-NEXT";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCountry() {
|
||||||
|
return "US";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class WSResponse {
|
public static class WSResponse {
|
||||||
private boolean successful;
|
private boolean successful;
|
||||||
private int responseCode;
|
private int responseCode;
|
||||||
@@ -60,15 +104,21 @@ public class WebService {
|
|||||||
private static final String GET_DATABASE_URL_PART = "/get-database";
|
private static final String GET_DATABASE_URL_PART = "/get-database";
|
||||||
private static final String GET_REVIEWS_URL_PART = "/get-reviews";
|
private static final String GET_REVIEWS_URL_PART = "/get-reviews";
|
||||||
|
|
||||||
public static String getGetDatabaseUrlPart() {
|
private final WSParameterProvider parameterProvider;
|
||||||
|
|
||||||
|
public WebService(WSParameterProvider parameterProvider) {
|
||||||
|
this.parameterProvider = parameterProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGetDatabaseUrlPart() {
|
||||||
return GET_DATABASE_URL_PART;
|
return GET_DATABASE_URL_PART;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getGetReviewsUrlPart() {
|
public String getGetReviewsUrlPart() {
|
||||||
return GET_REVIEWS_URL_PART;
|
return GET_REVIEWS_URL_PART;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Response call(String path, Map<String, String> params) {
|
public Response call(String path, Map<String, String> params) {
|
||||||
LOG.debug("call() started; path={}", path);
|
LOG.debug("call() started; path={}", path);
|
||||||
|
|
||||||
// TODO: retries
|
// TODO: retries
|
||||||
@@ -82,7 +132,7 @@ public class WebService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static WSResponse callForJson(String path, Map<String, String> params) {
|
public WSResponse callForJson(String path, Map<String, String> params) {
|
||||||
LOG.debug("callForJson() started; path={}", path);
|
LOG.debug("callForJson() started; path={}", path);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -118,24 +168,24 @@ public class WebService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String addHostname(String path) {
|
private String addHostname(String path) {
|
||||||
return "https://aapi.shouldianswer.net/srvapp" + path;
|
return "https://aapi.shouldianswer.net/srvapp" + path;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static RequestBody createRequestBody(Map<String, String> params) {
|
private RequestBody createRequestBody(Map<String, String> params) {
|
||||||
if (params == null) params = new HashMap<>();
|
if (params == null) params = new HashMap<>();
|
||||||
|
|
||||||
params.put("_appId", Utils.getAppId());
|
params.put("_appId", parameterProvider.getAppId());
|
||||||
|
|
||||||
params.put("_device", "dreamlte");
|
params.put("_device", parameterProvider.getDevice());
|
||||||
params.put("_model", "SM-G950F");
|
params.put("_model", parameterProvider.getModel());
|
||||||
params.put("_manufacturer", "Samsung");
|
params.put("_manufacturer", parameterProvider.getManufacturer());
|
||||||
params.put("_api", String.valueOf(Build.VERSION_CODES.O));
|
params.put("_api", String.valueOf(parameterProvider.getAndroidApi()));
|
||||||
|
|
||||||
params.put("_appFamily", "SIA-NEXT");
|
params.put("_appFamily", parameterProvider.getAppFamily());
|
||||||
params.put("_appVer", String.valueOf(Utils.getAppVersion()));
|
params.put("_appVer", String.valueOf(parameterProvider.getAppVersion()));
|
||||||
params.put("_dbVer", String.valueOf(Utils.getEffectiveDbVersion()));
|
params.put("_dbVer", String.valueOf(parameterProvider.getDbVersion()));
|
||||||
params.put("_country", "US"); // TODO: remove hardcode
|
params.put("_country", parameterProvider.getCountry());
|
||||||
|
|
||||||
MultipartBody.Builder bodyBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM);
|
MultipartBody.Builder bodyBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM);
|
||||||
|
|
||||||
|
@@ -4,34 +4,19 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
public class FileUtils {
|
public class FileUtils {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(FileUtils.class);
|
private static final Logger LOG = LoggerFactory.getLogger(FileUtils.class);
|
||||||
|
|
||||||
public static File getDataDir() {
|
|
||||||
return Utils.getContext().getFilesDir();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getDataDirPath() {
|
|
||||||
return getDataDir().getAbsolutePath() + "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static InputStream openFile(String fileName, boolean asset) throws IOException {
|
|
||||||
if (asset) {
|
|
||||||
return Utils.getContext().getAssets().open(fileName);
|
|
||||||
} else {
|
|
||||||
return new FileInputStream(getDataDirPath() + fileName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static File createDirectory(String path) {
|
public static File createDirectory(String path) {
|
||||||
return createDirectory(new File(path));
|
return createDirectory(new File(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static File createDirectory(String base, String dir) {
|
||||||
|
return createDirectory(new File(base, dir));
|
||||||
|
}
|
||||||
|
|
||||||
public static File createDirectory(File base, String dir) {
|
public static File createDirectory(File base, String dir) {
|
||||||
return createDirectory(new File(base, dir));
|
return createDirectory(new File(base, dir));
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
package dummydomain.yetanothercallblocker.sia.utils;
|
package dummydomain.yetanothercallblocker.sia.utils;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Hex;
|
import org.apache.commons.codec.binary.Hex;
|
||||||
@@ -9,36 +8,12 @@ import org.apache.commons.codec.digest.DigestUtils;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import dummydomain.yetanothercallblocker.App;
|
|
||||||
import dummydomain.yetanothercallblocker.data.DatabaseSingleton;
|
|
||||||
import dummydomain.yetanothercallblocker.sia.SiaSettings;
|
|
||||||
|
|
||||||
public class Utils {
|
public class Utils {
|
||||||
|
|
||||||
public static Context getContext() {
|
|
||||||
return App.getInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SiaSettings getSettings() {
|
|
||||||
return new SiaSettings(getContext());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String md5String(String str) {
|
public static String md5String(String str) {
|
||||||
return new String(Hex.encodeHex(DigestUtils.md5(str)));
|
return new String(Hex.encodeHex(DigestUtils.md5(str)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getAppVersion() {
|
|
||||||
return DatabaseSingleton.getCommunityDatabase().getSiaAppVersion();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getEffectiveDbVersion() {
|
|
||||||
return DatabaseSingleton.getCommunityDatabase().getEffectiveDbVersion();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getAppId() {
|
|
||||||
return "qQq0O9nCRNy_aVdPgU9WOA";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String generateAppId() {
|
public static String generateAppId() {
|
||||||
UUID randomUUID = UUID.randomUUID();
|
UUID randomUUID = UUID.randomUUID();
|
||||||
|
|
||||||
|
@@ -22,7 +22,6 @@ import dummydomain.yetanothercallblocker.event.MainDbDownloadFinishedEvent;
|
|||||||
import dummydomain.yetanothercallblocker.event.MainDbDownloadingEvent;
|
import dummydomain.yetanothercallblocker.event.MainDbDownloadingEvent;
|
||||||
import dummydomain.yetanothercallblocker.event.SecondaryDbUpdateFinished;
|
import dummydomain.yetanothercallblocker.event.SecondaryDbUpdateFinished;
|
||||||
import dummydomain.yetanothercallblocker.event.SecondaryDbUpdatingEvent;
|
import dummydomain.yetanothercallblocker.event.SecondaryDbUpdatingEvent;
|
||||||
import dummydomain.yetanothercallblocker.sia.model.database.DbManager;
|
|
||||||
|
|
||||||
import static dummydomain.yetanothercallblocker.EventUtils.postEvent;
|
import static dummydomain.yetanothercallblocker.EventUtils.postEvent;
|
||||||
import static dummydomain.yetanothercallblocker.EventUtils.postStickyEvent;
|
import static dummydomain.yetanothercallblocker.EventUtils.postStickyEvent;
|
||||||
@@ -89,7 +88,7 @@ public class TaskService extends IntentService {
|
|||||||
|
|
||||||
postStickyEvent(sticky);
|
postStickyEvent(sticky);
|
||||||
try {
|
try {
|
||||||
DbManager.downloadMainDb();
|
DatabaseSingleton.getDbManager().downloadMainDb();
|
||||||
DatabaseSingleton.getCommunityDatabase().reload();
|
DatabaseSingleton.getCommunityDatabase().reload();
|
||||||
DatabaseSingleton.getFeaturedDatabase().reload();
|
DatabaseSingleton.getFeaturedDatabase().reload();
|
||||||
} finally {
|
} finally {
|
||||||
|
Reference in New Issue
Block a user