Store best app and evaluate it with concurrent

This commit is contained in:
Thomas 2020-04-19 19:41:18 +02:00
parent 731af9893e
commit df9fd63b70
6 changed files with 341 additions and 34 deletions

View File

@ -15,17 +15,20 @@ package app.fedilab.nitterizeme.activities;
* see <http://www.gnu.org/licenses>. */
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.GridView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import androidx.constraintlayout.widget.ConstraintLayout;
import java.util.ArrayList;
import java.util.Arrays;
@ -35,6 +38,9 @@ import java.util.Objects;
import app.fedilab.nitterizeme.R;
import app.fedilab.nitterizeme.adapters.AppPickerAdapter;
import app.fedilab.nitterizeme.entities.AppPicker;
import app.fedilab.nitterizeme.helpers.Utils;
import app.fedilab.nitterizeme.sqlite.DefaultAppDAO;
import app.fedilab.nitterizeme.sqlite.Sqlite;
import static app.fedilab.nitterizeme.activities.CheckAppActivity.invidious_instances;
import static app.fedilab.nitterizeme.helpers.Utils.KILL_ACTIVITY;
@ -48,12 +54,12 @@ public class AppsPickerActivity extends Activity {
private String url;
private String appToUse;
private String appName;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pickup_app);
SharedPreferences sharedpreferences = getSharedPreferences(MainActivity.APP_PREFS, Context.MODE_PRIVATE);
if (getIntent() == null) {
finish();
}
@ -75,15 +81,13 @@ public class AppsPickerActivity extends Activity {
delegate.setDataAndType(Uri.parse(url), "text/html");
delegate.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
List<ResolveInfo> activities;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
activities = getPackageManager().queryIntentActivities(delegate, PackageManager.MATCH_ALL);
} else {
activities = getPackageManager().queryIntentActivities(delegate, 0);
}
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
RelativeLayout blank = findViewById(R.id.blank);
blank.setOnClickListener(v -> finish());
@ -101,13 +105,16 @@ public class AppsPickerActivity extends Activity {
if (i == 0) {
appPicker.setSelected(true);
appToUse = packageName;
appName = String.valueOf(currentInfo.loadLabel(getPackageManager()));
}
appPickers.add(appPicker);
packages.add(packageName);
}
i++;
}
if (isAppInstalled(AppsPickerActivity.this, "org.schabi.newpipe") && Arrays.asList(invidious_instances).contains(Objects.requireNonNull(Uri.parse(url)).getHost()) && !packages.contains("org.schabi.newpipe")) {
if (isAppInstalled(AppsPickerActivity.this, "org.schabi.newpipe")
&& Arrays.asList(invidious_instances).contains(Objects.requireNonNull(Uri.parse(url)).getHost())
&& !packages.contains("org.schabi.newpipe")) {
PackageInfo packageInfo = getPackageInfo(AppsPickerActivity.this, "org.schabi.newpipe");
if (packageInfo != null) {
AppPicker appPicker = new AppPicker();
@ -115,43 +122,69 @@ public class AppsPickerActivity extends Activity {
appPicker.setName(String.valueOf(packageInfo.applicationInfo.loadLabel(getPackageManager())));
appPicker.setPackageName(packageInfo.applicationInfo.packageName);
appPickers.add(appPicker);
packages.add("org.schabi.newpipe");
}
}
GridView gridView = findViewById(R.id.app_list);
AppPickerAdapter appPickerAdapter = new AppPickerAdapter(appPickers);
gridView.setAdapter(appPickerAdapter);
gridView.setNumColumns(3);
gridView.setOnItemClickListener((parent, view1, position, id) -> {
for (AppPicker ap : appPickers) {
ap.setSelected(false);
}
appPickers.get(position).setSelected(true);
appToUse = appPickers.get(position).getPackageName();
appPickerAdapter.notifyDataSetChanged();
});
String defaultApp = new DefaultAppDAO(AppsPickerActivity.this, db).getDefault(packages);
Button always = findViewById(R.id.always);
Button once = findViewById(R.id.once);
always.setOnClickListener(v -> {
if (defaultApp != null) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
intent.setPackage(appToUse);
intent.setPackage(defaultApp);
startActivity(intent);
finish();
});
} else {
ConstraintLayout app_container = findViewById(R.id.app_container);
app_container.setVisibility(View.VISIBLE);
GridView gridView = findViewById(R.id.app_list);
AppPickerAdapter appPickerAdapter = new AppPickerAdapter(appPickers);
gridView.setAdapter(appPickerAdapter);
gridView.setNumColumns(3);
gridView.setOnItemClickListener((parent, view1, position, id) -> {
for (AppPicker ap : appPickers) {
ap.setSelected(false);
}
appPickers.get(position).setSelected(true);
appToUse = appPickers.get(position).getPackageName();
appName = appPickers.get(position).getName();
appPickerAdapter.notifyDataSetChanged();
});
Button always = findViewById(R.id.always);
Button once = findViewById(R.id.once);
always.setOnClickListener(v -> {
boolean isPresent = new DefaultAppDAO(AppsPickerActivity.this, db).isPresent(appToUse);
long val = -1;
if (isPresent) {
ArrayList<String> oldConcurrent = new DefaultAppDAO(AppsPickerActivity.this, db).getConcurrent(appToUse);
ArrayList<String> newConcurrent = Utils.union(oldConcurrent, packages);
new DefaultAppDAO(AppsPickerActivity.this, db).update(appToUse, newConcurrent);
} else {
val = new DefaultAppDAO(AppsPickerActivity.this, db).insert(appToUse, packages);
}
if (val > 0) {
Toast.makeText(AppsPickerActivity.this, getString(R.string.default_app_indication, appName), Toast.LENGTH_LONG).show();
}
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
intent.setPackage(appToUse);
startActivity(intent);
finish();
});
once.setOnClickListener(v -> {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
intent.setPackage(appToUse);
startActivity(intent);
finish();
});
}
once.setOnClickListener(v -> {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
intent.setPackage(appToUse);
startActivity(intent);
finish();
});
}
@Override
protected void onDestroy() {
super.onDestroy();
}

View File

@ -33,10 +33,12 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -368,4 +370,56 @@ public class Utils {
}
return packageInfo;
}
/**
* Convert an ArrayList to a string using coma
*
* @param arrayList ArrayList<String>
* @return String
*/
public static String arrayToString(ArrayList<String> arrayList) {
if (arrayList == null || arrayList.size() == 0) {
return null;
}
StringBuilder result = new StringBuilder();
for (String item : arrayList) {
result.append("\"").append(item).append("\"").append(",");
}
return result.substring(0, result.length() - 1);
}
/**
* Convert String items to Array
*
* @param items String
* @return ArrayList<String>
*/
public static ArrayList<String> stringToArray(String items) {
if (items == null) {
return null;
}
String[] result = items.split(",");
return new ArrayList<>(Arrays.asList(result));
}
public static <T> ArrayList<T> union(ArrayList<T> list1, ArrayList<T> list2) {
Set<T> set = new HashSet<T>();
set.addAll(list1);
set.addAll(list2);
return new ArrayList<T>(set);
}
public static <T> ArrayList<T> intersection(ArrayList<T> list1, ArrayList<T> list2) {
ArrayList<T> list = new ArrayList<T>();
for (T t : list1) {
if (list2.contains(t)) {
list.add(t);
}
}
return list;
}
}

View File

@ -0,0 +1,151 @@
package app.fedilab.nitterizeme.sqlite;
/* Copyright 2020 Thomas Schneider
*
* This file is a part of UntrackMe
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* UntrackMe is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with UntrackMe; if not,
* see <http://www.gnu.org/licenses>. */
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import java.util.ArrayList;
import app.fedilab.nitterizeme.helpers.Utils;
public class DefaultAppDAO {
public Context context;
private SQLiteDatabase db;
public DefaultAppDAO(Context context, SQLiteDatabase db) {
this.context = context;
this.db = db;
}
public long insert(String packageName, ArrayList<String> concurrentPackages) {
ContentValues values = new ContentValues();
values.put(Sqlite.COL_DEFAULT_PACKAGE, packageName.trim());
values.put(Sqlite.COL_CONCURRENT_PACKAGES, Utils.arrayToString(concurrentPackages));
try {
return db.insert(Sqlite.TABLE_DEFAULT_APPS, null, values);
} catch (Exception ignored) {
return -1;
}
}
public void update(String packageName, ArrayList<String> concurrentPackages) {
ContentValues values = new ContentValues();
values.put(Sqlite.COL_CONCURRENT_PACKAGES, Utils.arrayToString(concurrentPackages));
try {
db.update(Sqlite.TABLE_DEFAULT_APPS, values, Sqlite.COL_DEFAULT_PACKAGE + " = ? ", new String[]{packageName});
} catch (Exception ignored) {
}
}
public int removeApp(String packageName) {
return db.delete(Sqlite.TABLE_DEFAULT_APPS, Sqlite.COL_DEFAULT_PACKAGE + " = \"" + packageName + "\"", null);
}
public int removeAll() {
return db.delete(Sqlite.TABLE_DEFAULT_APPS, null, null);
}
public ArrayList<String> getConcurrent(String packageName) {
try {
Cursor c = db.query(Sqlite.TABLE_DEFAULT_APPS, null, Sqlite.COL_DEFAULT_PACKAGE + " = '" + packageName + "'", null, null, null, null, null);
return cursorGetConcurrent(c);
} catch (Exception e) {
return null;
}
}
public ArrayList<String> getDefault() {
try {
Cursor c = db.query(Sqlite.TABLE_DEFAULT_APPS, null, null, null, null, null, null, null);
return cursorGetDefaults(c);
} catch (Exception e) {
return null;
}
}
public String getDefault(ArrayList<String> packageNames) {
try {
Cursor c = db.query(Sqlite.TABLE_DEFAULT_APPS, null, Sqlite.COL_DEFAULT_PACKAGE + " IN ( " + Utils.arrayToString(packageNames) + ")", null, null, null, null, null);
return getBestMatchIfExists(c, packageNames);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public boolean isPresent(String packageName) {
Cursor mCount = db.rawQuery("select count(*) from " + Sqlite.TABLE_DEFAULT_APPS
+ " where " + Sqlite.COL_DEFAULT_PACKAGE + " = '" + packageName + "'", null);
mCount.moveToFirst();
int count = mCount.getInt(0);
mCount.close();
return count > 0;
}
private ArrayList<String> cursorGetConcurrent(Cursor c) {
if (c.getCount() == 0) {
c.close();
return null;
}
ArrayList<String> items = null;
if (c.moveToFirst()) {
String concurrentStr = c.getString(c.getColumnIndex(Sqlite.COL_CONCURRENT_PACKAGES));
items = Utils.stringToArray(concurrentStr);
}
c.close();
return items;
}
private ArrayList<String> cursorGetDefaults(Cursor c) {
if (c.getCount() == 0) {
c.close();
return null;
}
ArrayList<String> items = new ArrayList<>();
while (c.moveToNext()) {
String packageName = c.getString(c.getColumnIndex(Sqlite.COL_DEFAULT_PACKAGE));
items.add(packageName);
}
c.close();
return items;
}
private String getBestMatchIfExists(Cursor c, ArrayList<String> allPackages) {
if (c.getCount() == 0) {
c.close();
return null;
}
ArrayList<String> concurrent = new ArrayList<>();
while (c.moveToNext()) {
String packageName = c.getString(c.getColumnIndex(Sqlite.COL_DEFAULT_PACKAGE));
concurrent.addAll(Utils.stringToArray(packageName));
}
c.close();
//Items will only returns concurrent for default apps.
ArrayList<String> best = Utils.intersection(allPackages, concurrent);
//The winner will be the one not in concurrent
if (best.size() == 1) {
return best.get(0);
} else return null;
}
}

View File

@ -0,0 +1,67 @@
package app.fedilab.nitterizeme.sqlite;
/* Copyright 2020 Thomas Schneider
*
* This file is a part of UntrackMe
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* UntrackMe is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with UntrackMe; if not,
* see <http://www.gnu.org/licenses>. */
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class Sqlite extends SQLiteOpenHelper {
public static final int DB_VERSION = 1;
public static final String DB_NAME = "untrackme_db";
static final String TABLE_DEFAULT_APPS = "DEFAULT_APPS";
static final String COL_DEFAULT_PACKAGE = "DEFAULT_PACKAGE";
static final String COL_CONCURRENT_PACKAGES = "CONCURRENT_PACKAGES";
private static final String COL_ID = "ID";
private static final String CREATE_TABLE_DEFAULT_APPS = "CREATE TABLE " + TABLE_DEFAULT_APPS + " ("
+ COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ COL_DEFAULT_PACKAGE + " TEXT NOT NULL UNIQUE, " + COL_CONCURRENT_PACKAGES + " TEXT)";
private static SQLiteDatabase db;
private static Sqlite sInstance;
private Sqlite(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
public static synchronized Sqlite getInstance(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
if (sInstance == null) {
sInstance = new Sqlite(context, name, factory, version);
}
return sInstance;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_TABLE_DEFAULT_APPS);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public SQLiteDatabase open() {
db = getWritableDatabase();
return db;
}
public void close() {
if (db != null && db.isOpen()) {
db.close();
}
}
}

View File

@ -32,6 +32,7 @@
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.ConstraintLayout
android:visibility="invisible"
android:id="@+id/app_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"

View File

@ -57,7 +57,8 @@
<string name="share_with">Share with</string>
<string name="check_apps">Check apps</string>
<string name="select_instances">Select instances</string>
<string name="continue_with">Continue with...</string>
<string name="continue_with">Continue with</string>
<string name="just_once">Just once</string>
<string name="always">Always</string>
<string name="default_app_indication">%1$s has been set by default.\nYou can remove this behavior from the app settings.</string>
</resources>