Bug fixes
This commit is contained in:
parent
4ee0d48af6
commit
cc938da982
|
|
@ -16,11 +16,11 @@ import static de.robv.android.xposed.installer.util.InstallZipUtil.parseXposedPr
|
|||
public class XposedApp extends Application {
|
||||
public static final String TAG = "XposedApp";
|
||||
private static final File EDXPOSED_PROP_FILE = new File("/system/framework/edconfig.jar");
|
||||
private static XposedApp mInstance = null;
|
||||
public InstallZipUtil.XposedProp mXposedProp;
|
||||
private static XposedApp instance = null;
|
||||
public InstallZipUtil.XposedProp xposedProp;
|
||||
|
||||
public static XposedApp getInstance() {
|
||||
return mInstance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
// This method is hooked by XposedBridge to return the current version
|
||||
|
|
@ -31,7 +31,7 @@ public class XposedApp extends Application {
|
|||
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
mInstance = this;
|
||||
instance = this;
|
||||
reloadXposedProp();
|
||||
}
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ public class XposedApp extends Application {
|
|||
}
|
||||
}
|
||||
synchronized (this) {
|
||||
mXposedProp = prop;
|
||||
xposedProp = prop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ public class BaseActivity extends AppCompatActivity {
|
|||
protected void setupWindowInsets(View rootView, View secondView) {
|
||||
rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
|
||||
ViewCompat.setOnApplyWindowInsetsListener(rootView, (v, insets) -> {
|
||||
if (secondView != null) {
|
||||
if (secondView != null && insets.getTappableElementInsets().bottom != insets.getSystemWindowInsetBottom()) {
|
||||
secondView.setPadding(0, 0, 0, insets.getSystemWindowInsetBottom());
|
||||
}
|
||||
rootView.setPadding(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), insets.getSystemWindowInsetRight(), insets.getTappableElementInsets().bottom);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package org.meowcat.edxposed.manager;
|
|||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.view.Menu;
|
||||
import android.view.View;
|
||||
|
||||
|
|
@ -17,15 +18,22 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
|||
|
||||
import org.meowcat.edxposed.manager.adapters.AppAdapter;
|
||||
import org.meowcat.edxposed.manager.adapters.AppHelper;
|
||||
import org.meowcat.edxposed.manager.adapters.CompatListAdapter;
|
||||
import org.meowcat.edxposed.manager.adapters.BlackListAdapter;
|
||||
import org.meowcat.edxposed.manager.databinding.ActivityBlackListBinding;
|
||||
|
||||
public class BlackListActivity extends BaseActivity implements AppAdapter.Callback {
|
||||
private SearchView searchView;
|
||||
private CompatListAdapter appAdapter;
|
||||
private BlackListAdapter appAdapter;
|
||||
|
||||
private SearchView.OnQueryTextListener searchListener;
|
||||
private ActivityBlackListBinding binding;
|
||||
private Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
binding.swipeRefreshLayout.setRefreshing(true);
|
||||
}
|
||||
};
|
||||
private Handler handler = new Handler();
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
|
|
@ -40,16 +48,17 @@ public class BlackListActivity extends BaseActivity implements AppAdapter.Callba
|
|||
}
|
||||
setupWindowInsets(binding.snackbar, binding.recyclerView);
|
||||
binding.recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||
appAdapter = new CompatListAdapter(this);
|
||||
final boolean isWhiteListMode = isWhiteListMode();
|
||||
appAdapter = new BlackListAdapter(this, isWhiteListMode, binding);
|
||||
binding.recyclerView.setAdapter(appAdapter);
|
||||
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(this,
|
||||
DividerItemDecoration.VERTICAL);
|
||||
binding.recyclerView.addItemDecoration(dividerItemDecoration);
|
||||
appAdapter.setCallback(this);
|
||||
|
||||
binding.swipeRefreshLayout.setRefreshing(true);
|
||||
handler.postDelayed(runnable, 300);
|
||||
binding.swipeRefreshLayout.setOnRefreshListener(appAdapter::refresh);
|
||||
|
||||
|
||||
searchListener = new SearchView.OnQueryTextListener() {
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(String query) {
|
||||
|
|
@ -110,6 +119,7 @@ public class BlackListActivity extends BaseActivity implements AppAdapter.Callba
|
|||
|
||||
@Override
|
||||
public void onDataReady() {
|
||||
handler.removeCallbacks(runnable);
|
||||
binding.swipeRefreshLayout.setRefreshing(false);
|
||||
String queryStr = searchView != null ? searchView.getQuery().toString() : "";
|
||||
appAdapter.filter(queryStr);
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ public class CompatListActivity extends BaseActivity implements AppAdapter.Callb
|
|||
}
|
||||
setupWindowInsets(binding.snackbar, binding.recyclerView);
|
||||
binding.recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||
appAdapter = new CompatListAdapter(this);
|
||||
appAdapter = new CompatListAdapter(this, binding);
|
||||
binding.recyclerView.setAdapter(appAdapter);
|
||||
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(this,
|
||||
DividerItemDecoration.VERTICAL);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import androidx.appcompat.widget.SearchView;
|
|||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.transition.TransitionManager;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.timehop.stickyheadersrecyclerview.StickyRecyclerHeadersAdapter;
|
||||
|
|
@ -173,6 +174,7 @@ public class DownloadActivity extends BaseActivity implements RepoLoader.RepoLis
|
|||
private void reloadItems() {
|
||||
runOnUiThread(() -> {
|
||||
adapter.swapCursor(RepoDb.queryModuleOverview(sortingOrder, filterText));
|
||||
TransitionManager.beginDelayedTransition(binding.recyclerView);
|
||||
adapter.notifyDataSetChanged();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,9 @@ public class DownloadDetailsFragment extends Fragment {
|
|||
}
|
||||
DownloadDetailsBinding binding = DownloadDetailsBinding.inflate(inflater, container, false);
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.getRoot(), (v, insets) -> {
|
||||
binding.getRoot().setPadding(0, 0, 0, insets.getSystemWindowInsetBottom());
|
||||
if (insets.getTappableElementInsets().bottom != insets.getSystemWindowInsetBottom()) {
|
||||
binding.getRoot().setPadding(0, 0, 0, insets.getSystemWindowInsetBottom());
|
||||
}
|
||||
return insets;
|
||||
});
|
||||
binding.downloadTitle.setText(module.name);
|
||||
|
|
|
|||
|
|
@ -92,7 +92,9 @@ public class DownloadDetailsVersionsFragment extends ListFragment {
|
|||
getListView().setClipToPadding(false);
|
||||
getListView().setClipToPadding(false);
|
||||
ViewCompat.setOnApplyWindowInsetsListener(view, (v, insets) -> {
|
||||
getListView().setPadding(0, 0, 0, insets.getSystemWindowInsetBottom());
|
||||
if (insets.getTappableElementInsets().bottom != insets.getSystemWindowInsetBottom()) {
|
||||
getListView().setPadding(0, 0, 0, insets.getSystemWindowInsetBottom());
|
||||
}
|
||||
return insets;
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import androidx.appcompat.app.ActionBar;
|
|||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentPagerAdapter;
|
||||
import androidx.transition.TransitionManager;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.gson.Gson;
|
||||
|
|
@ -93,6 +94,7 @@ public class EdDownloadActivity extends BaseActivity {
|
|||
try {
|
||||
final JSONUtils.XposedJson xposedJson = new Gson().fromJson(result, JSONUtils.XposedJson.class);
|
||||
|
||||
TransitionManager.beginDelayedTransition(binding.tabLayout);
|
||||
for (XposedTab tab : xposedJson.tabs) {
|
||||
if (tab.sdks.contains(Build.VERSION.SDK_INT)) {
|
||||
tabsAdapter.addFragment(tab.name, BaseAdvancedInstaller.newInstance(tab));
|
||||
|
|
|
|||
|
|
@ -237,7 +237,7 @@ public class LogsActivity extends BaseActivity {
|
|||
mProgressDialog = new MaterialAlertDialogBuilder(LogsActivity.this).create();
|
||||
mProgressDialog.setMessage(getString(R.string.loading));
|
||||
mProgressDialog.setCancelable(false);
|
||||
handler.postDelayed(mRunnable, 500);
|
||||
handler.postDelayed(mRunnable, 300);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import org.meowcat.edxposed.manager.util.RepoLoader;
|
|||
|
||||
public class MainActivity extends BaseActivity implements RepoLoader.RepoListener, ModuleUtil.ModuleListener {
|
||||
ActivityMainBinding binding;
|
||||
private RepoLoader mRepoLoader;
|
||||
private RepoLoader repoLoader;
|
||||
|
||||
@SuppressLint("PrivateResource")
|
||||
@Override
|
||||
|
|
@ -21,10 +21,10 @@ public class MainActivity extends BaseActivity implements RepoLoader.RepoListene
|
|||
super.onCreate(savedInstanceState);
|
||||
binding = ActivityMainBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
|
||||
mRepoLoader = RepoLoader.getInstance();
|
||||
setupWindowInsets(binding.snackbar, binding.nestedScrollView);
|
||||
repoLoader = RepoLoader.getInstance();
|
||||
ModuleUtil.getInstance().addListener(this);
|
||||
mRepoLoader.addListener(this, false);
|
||||
repoLoader.addListener(this, false);
|
||||
binding.modules.setOnClickListener(v -> {
|
||||
Intent intent = new Intent();
|
||||
intent.setClass(getApplicationContext(), ModulesActivity.class);
|
||||
|
|
@ -110,8 +110,8 @@ public class MainActivity extends BaseActivity implements RepoLoader.RepoListene
|
|||
|
||||
private void notifyDataSetChanged() {
|
||||
runOnUiThread(() -> {
|
||||
String frameworkUpdateVersion = mRepoLoader.getFrameworkUpdateVersion();
|
||||
boolean moduleUpdateAvailable = mRepoLoader.hasModuleUpdates();
|
||||
String frameworkUpdateVersion = repoLoader.getFrameworkUpdateVersion();
|
||||
boolean moduleUpdateAvailable = repoLoader.hasModuleUpdates();
|
||||
ModuleUtil.getInstance().getEnabledModules().size();
|
||||
binding.modulesSummary.setText(String.format(getString(R.string.ModulesDetail), ModuleUtil.getInstance().getEnabledModules().size()));
|
||||
if (frameworkUpdateVersion != null) {
|
||||
|
|
@ -145,7 +145,7 @@ public class MainActivity extends BaseActivity implements RepoLoader.RepoListene
|
|||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
ModuleUtil.getInstance().removeListener(this);
|
||||
mRepoLoader.removeListener(this);
|
||||
repoLoader.removeListener(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import androidx.appcompat.widget.SwitchCompat;
|
|||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.transition.TransitionManager;
|
||||
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
|
||||
|
|
@ -86,6 +87,7 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
|
|||
}
|
||||
}
|
||||
adapter.addAll(showList);
|
||||
TransitionManager.beginDelayedTransition(binding.recyclerView);
|
||||
adapter.notifyDataSetChanged();
|
||||
moduleUtil.updateModulesList(false);
|
||||
binding.swipeRefreshLayout.setRefreshing(false);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import android.annotation.SuppressLint;
|
|||
import android.app.Activity;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.os.FileUtils;
|
||||
import android.view.View;
|
||||
|
|
@ -344,7 +345,7 @@ public class SettingsActivity extends BaseActivity {
|
|||
transparent.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
boolean enabled = (Boolean) newValue;
|
||||
Activity activity = getActivity();
|
||||
if (activity != null && !XposedApp.getPreferences().getBoolean("black_dark_theme", false)) {
|
||||
if (activity != null && activity.getWindow().getStatusBarColor() != Color.BLACK) {
|
||||
if (enabled) {
|
||||
activity.getWindow().setStatusBarColor(ContextCompat.getColor(activity, R.color.colorActionBar));
|
||||
} else {
|
||||
|
|
@ -408,7 +409,9 @@ public class SettingsActivity extends BaseActivity {
|
|||
((FrameLayout) getListView().getParent()).setClipChildren(false);
|
||||
((FrameLayout) getListView().getParent()).setClipToPadding(false);
|
||||
ViewCompat.setOnApplyWindowInsetsListener(view, (v, insets) -> {
|
||||
getListView().setPadding(0, 0, 0, insets.getSystemWindowInsetBottom());
|
||||
if (insets.getTappableElementInsets().bottom != insets.getSystemWindowInsetBottom()) {
|
||||
getListView().setPadding(0, 0, 0, insets.getSystemWindowInsetBottom());
|
||||
}
|
||||
return insets;
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ public class XposedApp extends de.robv.android.xposed.installer.XposedApp implem
|
|||
}
|
||||
|
||||
public static InstallZipUtil.XposedProp getXposedProp() {
|
||||
return de.robv.android.xposed.installer.XposedApp.getInstance().mXposedProp;
|
||||
return de.robv.android.xposed.installer.XposedApp.getInstance().xposedProp;
|
||||
}
|
||||
|
||||
public static void runOnUiThread(Runnable action) {
|
||||
|
|
|
|||
|
|
@ -16,9 +16,11 @@ import android.widget.TextView;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.SwitchCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.transition.TransitionManager;
|
||||
|
||||
import org.meowcat.edxposed.manager.R;
|
||||
import org.meowcat.edxposed.manager.XposedApp;
|
||||
import org.meowcat.edxposed.manager.databinding.ActivityBlackListBinding;
|
||||
import org.meowcat.edxposed.manager.util.InstallApkUtil;
|
||||
|
||||
import java.text.DateFormat;
|
||||
|
|
@ -41,9 +43,11 @@ public class AppAdapter extends RecyclerView.Adapter<AppAdapter.ViewHolder> {
|
|||
private PackageManager pm;
|
||||
private ApplicationFilter filter;
|
||||
private Comparator<ApplicationInfo> cmp;
|
||||
private ActivityBlackListBinding binding;
|
||||
|
||||
AppAdapter(Context context) {
|
||||
AppAdapter(Context context, ActivityBlackListBinding binding) {
|
||||
this.context = context;
|
||||
this.binding = binding;
|
||||
fullList = showList = Collections.emptyList();
|
||||
checkedList = Collections.emptyList();
|
||||
filter = new ApplicationFilter();
|
||||
|
|
@ -262,6 +266,7 @@ public class AppAdapter extends RecyclerView.Adapter<AppAdapter.ViewHolder> {
|
|||
|
||||
@Override
|
||||
protected void publishResults(CharSequence constraint, FilterResults results) {
|
||||
TransitionManager.beginDelayedTransition(binding.recyclerView);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import android.widget.CompoundButton;
|
|||
|
||||
import org.meowcat.edxposed.manager.R;
|
||||
import org.meowcat.edxposed.manager.XposedApp;
|
||||
import org.meowcat.edxposed.manager.databinding.ActivityBlackListBinding;
|
||||
import org.meowcat.edxposed.manager.util.ModuleUtil;
|
||||
import org.meowcat.edxposed.manager.util.ToastUtil;
|
||||
|
||||
|
|
@ -18,8 +19,8 @@ public class BlackListAdapter extends AppAdapter {
|
|||
private volatile boolean isWhiteListMode;
|
||||
private List<String> checkedList;
|
||||
|
||||
public BlackListAdapter(Context context, boolean isWhiteListMode) {
|
||||
super(context);
|
||||
public BlackListAdapter(Context context, boolean isWhiteListMode, ActivityBlackListBinding binding) {
|
||||
super(context, binding);
|
||||
this.isWhiteListMode = isWhiteListMode;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import android.content.pm.ApplicationInfo;
|
|||
import android.widget.CompoundButton;
|
||||
|
||||
import org.meowcat.edxposed.manager.R;
|
||||
import org.meowcat.edxposed.manager.databinding.ActivityBlackListBinding;
|
||||
import org.meowcat.edxposed.manager.util.ToastUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
|
@ -13,8 +14,8 @@ public class CompatListAdapter extends AppAdapter {
|
|||
|
||||
private List<String> checkedList;
|
||||
|
||||
public CompatListAdapter(Context context) {
|
||||
super(context);
|
||||
public CompatListAdapter(Context context, ActivityBlackListBinding binding) {
|
||||
super(context, binding);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package org.meowcat.edxposed.manager.util;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.DownloadManager;
|
||||
import android.app.DownloadManager.Query;
|
||||
import android.app.DownloadManager.Request;
|
||||
|
|
@ -34,31 +33,28 @@ import java.util.Objects;
|
|||
public class DownloadsUtil {
|
||||
public static final String MIME_TYPE_APK = "application/vnd.android.package-archive";
|
||||
//private static final String MIME_TYPE_ZIP = "application/zip";
|
||||
private static final Map<String, DownloadFinishedCallback> mCallbacks = new HashMap<>();
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private static final XposedApp mApp = XposedApp.getInstance();
|
||||
private static final SharedPreferences mPref = mApp
|
||||
.getSharedPreferences("download_cache", Context.MODE_PRIVATE);
|
||||
private static final Map<String, DownloadFinishedCallback> callbacks = new HashMap<>();
|
||||
private static final SharedPreferences pref = XposedApp.getInstance().getSharedPreferences("download_cache", Context.MODE_PRIVATE);
|
||||
|
||||
private static DownloadInfo add(Builder b) {
|
||||
Context context = b.mContext;
|
||||
removeAllForUrl(context, b.mUrl);
|
||||
Context context = b.context;
|
||||
removeAllForUrl(context, b.url);
|
||||
|
||||
synchronized (mCallbacks) {
|
||||
mCallbacks.put(b.mUrl, b.mCallback);
|
||||
synchronized (callbacks) {
|
||||
callbacks.put(b.url, b.callback);
|
||||
}
|
||||
|
||||
Request request = new Request(Uri.parse(b.mUrl));
|
||||
request.setTitle(b.mTitle);
|
||||
request.setMimeType(b.mMimeType.toString());
|
||||
Request request = new Request(Uri.parse(b.url));
|
||||
request.setTitle(b.title);
|
||||
request.setMimeType(b.mimeType.toString());
|
||||
/*if (b.mSave) {
|
||||
try {
|
||||
request.setDestinationInExternalPublicDir(savePath, b.mTitle + b.mMimeType.getExtension());
|
||||
request.setDestinationInExternalPublicDir(savePath, b.title + b.mimeType.getExtension());
|
||||
} catch (IllegalStateException e) {
|
||||
Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
} else */
|
||||
File destination = new File(context.getExternalCacheDir(), "/downloads/" + b.mTitle + b.mMimeType.getExtension());
|
||||
File destination = new File(context.getExternalCacheDir(), "/downloads/" + b.title + b.mimeType.getExtension());
|
||||
removeAllForLocalFile(context, destination);
|
||||
request.setDestinationUri(Uri.fromFile(destination));
|
||||
request.setNotificationVisibility(Request.VISIBILITY_VISIBLE);
|
||||
|
|
@ -295,8 +291,8 @@ public class DownloadsUtil {
|
|||
return;
|
||||
|
||||
DownloadFinishedCallback callback;
|
||||
synchronized (mCallbacks) {
|
||||
callback = mCallbacks.get(info.url);
|
||||
synchronized (callbacks) {
|
||||
callback = callbacks.get(info.url);
|
||||
}
|
||||
|
||||
if (callback == null)
|
||||
|
|
@ -345,8 +341,8 @@ public class DownloadsUtil {
|
|||
}
|
||||
|
||||
if (useNotModifiedTags) {
|
||||
String modified = mPref.getString("download_" + url + "_modified", null);
|
||||
String etag = mPref.getString("download_" + url + "_etag", null);
|
||||
String modified = pref.getString("download_" + url + "_modified", null);
|
||||
String etag = pref.getString("download_" + url + "_etag", null);
|
||||
|
||||
if (modified != null) {
|
||||
connection.addRequestProperty("If-Modified-Since", modified);
|
||||
|
|
@ -366,7 +362,7 @@ public class DownloadsUtil {
|
|||
return new SyncDownloadInfo(SyncDownloadInfo.STATUS_NOT_MODIFIED, null);
|
||||
} else if (responseCode < 200 || responseCode >= 300) {
|
||||
return new SyncDownloadInfo(SyncDownloadInfo.STATUS_FAILED,
|
||||
mApp.getString(R.string.repo_download_failed_http,
|
||||
XposedApp.getInstance().getString(R.string.repo_download_failed_http,
|
||||
url, responseCode,
|
||||
httpConnection.getResponseMessage()));
|
||||
}
|
||||
|
|
@ -385,7 +381,7 @@ public class DownloadsUtil {
|
|||
String modified = httpConnection.getHeaderField("Last-Modified");
|
||||
String etag = httpConnection.getHeaderField("ETag");
|
||||
|
||||
mPref.edit()
|
||||
pref.edit()
|
||||
.putString("download_" + url + "_modified", modified)
|
||||
.putString("download_" + url + "_etag", etag).apply();
|
||||
}
|
||||
|
|
@ -394,7 +390,7 @@ public class DownloadsUtil {
|
|||
|
||||
} catch (Throwable t) {
|
||||
return new SyncDownloadInfo(SyncDownloadInfo.STATUS_FAILED,
|
||||
mApp.getString(R.string.repo_download_failed, url,
|
||||
XposedApp.getInstance().getString(R.string.repo_download_failed, url,
|
||||
t.getMessage()));
|
||||
|
||||
} finally {
|
||||
|
|
@ -415,10 +411,10 @@ public class DownloadsUtil {
|
|||
|
||||
static void clearCache(String url) {
|
||||
if (url != null) {
|
||||
mPref.edit().remove("download_" + url + "_modified")
|
||||
pref.edit().remove("download_" + url + "_modified")
|
||||
.remove("download_" + url + "_etag").apply();
|
||||
} else {
|
||||
mPref.edit().clear().apply();
|
||||
pref.edit().clear().apply();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -453,39 +449,39 @@ public class DownloadsUtil {
|
|||
}
|
||||
|
||||
public static class Builder {
|
||||
private final Context mContext;
|
||||
boolean mModule = false;
|
||||
private String mTitle = null;
|
||||
private String mUrl = null;
|
||||
private DownloadFinishedCallback mCallback = null;
|
||||
private MIME_TYPES mMimeType = MIME_TYPES.APK;
|
||||
private final Context context;
|
||||
boolean module = false;
|
||||
private String title = null;
|
||||
private String url = null;
|
||||
private DownloadFinishedCallback callback = null;
|
||||
private MIME_TYPES mimeType = MIME_TYPES.APK;
|
||||
|
||||
public Builder(Context context) {
|
||||
mContext = context;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public Builder setTitle(String title) {
|
||||
mTitle = title;
|
||||
this.title = title;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setUrl(String url) {
|
||||
mUrl = url;
|
||||
this.url = url;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setCallback(DownloadFinishedCallback callback) {
|
||||
mCallback = callback;
|
||||
this.callback = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder setMimeType(@SuppressWarnings("SameParameterValue") MIME_TYPES mimeType) {
|
||||
mMimeType = mimeType;
|
||||
Builder setMimeType(MIME_TYPES mimeType) {
|
||||
this.mimeType = mimeType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setModule(boolean module) {
|
||||
this.mModule = module;
|
||||
this.module = module;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,30 +35,28 @@ public final class ModuleUtil {
|
|||
private static final String MODULES_LIST_FILE = XposedApp.BASE_DIR + "conf/modules.list";
|
||||
private static final String PLAY_STORE_PACKAGE = "com.android.vending";
|
||||
public static int MIN_MODULE_VERSION = 2; // reject modules with
|
||||
private static ModuleUtil mInstance = null;
|
||||
private final XposedApp mApp;
|
||||
private final PackageManager mPm;
|
||||
private final String mFrameworkPackageName;
|
||||
private final List<ModuleListener> mListeners = new CopyOnWriteArrayList<>();
|
||||
private SharedPreferences mPref;
|
||||
private InstalledModule mFramework = null;
|
||||
private Map<String, InstalledModule> mInstalledModules;
|
||||
private boolean mIsReloading = false;
|
||||
private Toast mToast;
|
||||
private static ModuleUtil instance = null;
|
||||
private final PackageManager pm;
|
||||
private final String frameworkPackageName;
|
||||
private final List<ModuleListener> listeners = new CopyOnWriteArrayList<>();
|
||||
private SharedPreferences pref;
|
||||
private InstalledModule framework = null;
|
||||
private Map<String, InstalledModule> installedModules;
|
||||
private boolean isReloading = false;
|
||||
private Toast toast;
|
||||
|
||||
private ModuleUtil() {
|
||||
mApp = XposedApp.getInstance();
|
||||
mPref = mApp.getSharedPreferences("enabled_modules", Context.MODE_PRIVATE);
|
||||
mPm = mApp.getPackageManager();
|
||||
mFrameworkPackageName = mApp.getPackageName();
|
||||
pref = XposedApp.getInstance().getSharedPreferences("enabled_modules", Context.MODE_PRIVATE);
|
||||
pm = XposedApp.getInstance().getPackageManager();
|
||||
frameworkPackageName = XposedApp.getInstance().getPackageName();
|
||||
}
|
||||
|
||||
public static synchronized ModuleUtil getInstance() {
|
||||
if (mInstance == null) {
|
||||
mInstance = new ModuleUtil();
|
||||
mInstance.reloadInstalledModules();
|
||||
if (instance == null) {
|
||||
instance = new ModuleUtil();
|
||||
instance.reloadInstalledModules();
|
||||
}
|
||||
return mInstance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static int extractIntPart(String str) {
|
||||
|
|
@ -76,9 +74,9 @@ public final class ModuleUtil {
|
|||
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
|
||||
public void reloadInstalledModules() {
|
||||
synchronized (this) {
|
||||
if (mIsReloading)
|
||||
if (isReloading)
|
||||
return;
|
||||
mIsReloading = true;
|
||||
isReloading = true;
|
||||
}
|
||||
|
||||
Map<String, InstalledModule> modules = new HashMap<>();
|
||||
|
|
@ -86,7 +84,7 @@ public final class ModuleUtil {
|
|||
try {
|
||||
RepoDb.deleteAllInstalledModules();
|
||||
|
||||
for (PackageInfo pkg : mPm.getInstalledPackages(PackageManager.GET_META_DATA)) {
|
||||
for (PackageInfo pkg : pm.getInstalledPackages(PackageManager.GET_META_DATA)) {
|
||||
ApplicationInfo app = pkg.applicationInfo;
|
||||
if (!app.enabled)
|
||||
continue;
|
||||
|
|
@ -96,7 +94,7 @@ public final class ModuleUtil {
|
|||
installed = new InstalledModule(pkg, false);
|
||||
modules.put(pkg.packageName, installed);
|
||||
} else if (isFramework(pkg.packageName)) {
|
||||
mFramework = installed = new InstalledModule(pkg, true);
|
||||
framework = installed = new InstalledModule(pkg, true);
|
||||
}
|
||||
|
||||
if (installed != null)
|
||||
|
|
@ -108,25 +106,25 @@ public final class ModuleUtil {
|
|||
RepoDb.endTransation();
|
||||
}
|
||||
|
||||
mInstalledModules = modules;
|
||||
installedModules = modules;
|
||||
synchronized (this) {
|
||||
mIsReloading = false;
|
||||
isReloading = false;
|
||||
}
|
||||
for (ModuleListener listener : mListeners) {
|
||||
listener.onInstalledModulesReloaded(mInstance);
|
||||
for (ModuleListener listener : listeners) {
|
||||
listener.onInstalledModulesReloaded(instance);
|
||||
}
|
||||
}
|
||||
|
||||
public InstalledModule reloadSingleModule(String packageName) {
|
||||
PackageInfo pkg;
|
||||
try {
|
||||
pkg = mPm.getPackageInfo(packageName, PackageManager.GET_META_DATA);
|
||||
pkg = pm.getPackageInfo(packageName, PackageManager.GET_META_DATA);
|
||||
} catch (NameNotFoundException e) {
|
||||
RepoDb.deleteInstalledModule(packageName);
|
||||
InstalledModule old = mInstalledModules.remove(packageName);
|
||||
InstalledModule old = installedModules.remove(packageName);
|
||||
if (old != null) {
|
||||
for (ModuleListener listener : mListeners) {
|
||||
listener.onSingleInstalledModuleReloaded(mInstance, packageName, null);
|
||||
for (ModuleListener listener : listeners) {
|
||||
listener.onSingleInstalledModuleReloaded(instance, packageName, null);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
@ -136,18 +134,18 @@ public final class ModuleUtil {
|
|||
if (app.enabled && app.metaData != null && app.metaData.containsKey("xposedmodule")) {
|
||||
InstalledModule module = new InstalledModule(pkg, false);
|
||||
RepoDb.insertInstalledModule(module);
|
||||
mInstalledModules.put(packageName, module);
|
||||
for (ModuleListener listener : mListeners) {
|
||||
listener.onSingleInstalledModuleReloaded(mInstance, packageName,
|
||||
installedModules.put(packageName, module);
|
||||
for (ModuleListener listener : listeners) {
|
||||
listener.onSingleInstalledModuleReloaded(instance, packageName,
|
||||
module);
|
||||
}
|
||||
return module;
|
||||
} else {
|
||||
RepoDb.deleteInstalledModule(packageName);
|
||||
InstalledModule old = mInstalledModules.remove(packageName);
|
||||
InstalledModule old = installedModules.remove(packageName);
|
||||
if (old != null) {
|
||||
for (ModuleListener listener : mListeners) {
|
||||
listener.onSingleInstalledModuleReloaded(mInstance, packageName, null);
|
||||
for (ModuleListener listener : listeners) {
|
||||
listener.onSingleInstalledModuleReloaded(instance, packageName, null);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
@ -155,49 +153,49 @@ public final class ModuleUtil {
|
|||
}
|
||||
|
||||
public synchronized boolean isLoading() {
|
||||
return mIsReloading;
|
||||
return isReloading;
|
||||
}
|
||||
|
||||
public InstalledModule getFramework() {
|
||||
return mFramework;
|
||||
return framework;
|
||||
}
|
||||
|
||||
public String getFrameworkPackageName() {
|
||||
return mFrameworkPackageName;
|
||||
return frameworkPackageName;
|
||||
}
|
||||
|
||||
private boolean isFramework(String packageName) {
|
||||
return mFrameworkPackageName.equals(packageName);
|
||||
return frameworkPackageName.equals(packageName);
|
||||
}
|
||||
|
||||
// public boolean isInstalled(String packageName) {
|
||||
// return mInstalledModules.containsKey(packageName) || isFramework(packageName);
|
||||
// return installedModules.containsKey(packageName) || isFramework(packageName);
|
||||
// }
|
||||
|
||||
public InstalledModule getModule(String packageName) {
|
||||
return mInstalledModules.get(packageName);
|
||||
return installedModules.get(packageName);
|
||||
}
|
||||
|
||||
public Map<String, InstalledModule> getModules() {
|
||||
return mInstalledModules;
|
||||
return installedModules;
|
||||
}
|
||||
|
||||
public void setModuleEnabled(String packageName, boolean enabled) {
|
||||
if (enabled) {
|
||||
mPref.edit().putInt(packageName, 1).apply();
|
||||
pref.edit().putInt(packageName, 1).apply();
|
||||
} else {
|
||||
mPref.edit().remove(packageName).apply();
|
||||
pref.edit().remove(packageName).apply();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isModuleEnabled(String packageName) {
|
||||
return mPref.contains(packageName);
|
||||
return pref.contains(packageName);
|
||||
}
|
||||
|
||||
public List<InstalledModule> getEnabledModules() {
|
||||
LinkedList<InstalledModule> result = new LinkedList<>();
|
||||
|
||||
for (String packageName : mPref.getAll().keySet()) {
|
||||
for (String packageName : pref.getAll().keySet()) {
|
||||
InstalledModule module = getModule(packageName);
|
||||
if (module != null)
|
||||
result.add(module);
|
||||
|
|
@ -213,7 +211,7 @@ public final class ModuleUtil {
|
|||
Log.i(XposedApp.TAG, "ModuleUtil -> updating modules.list");
|
||||
int installedXposedVersion = XposedApp.getXposedVersion();
|
||||
if (!XposedApp.getPreferences().getBoolean("skip_xposedminversion_check", false) && installedXposedVersion <= 0 && showToast) {
|
||||
Toast.makeText(mApp, R.string.notinstalled, Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(XposedApp.getInstance(), R.string.notinstalled, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -223,14 +221,14 @@ public final class ModuleUtil {
|
|||
for (InstalledModule module : enabledModules) {
|
||||
|
||||
if (!XposedApp.getPreferences().getBoolean("skip_xposedminversion_check", false) && (module.minVersion > installedXposedVersion || module.minVersion < MIN_MODULE_VERSION) && showToast) {
|
||||
Toast.makeText(mApp, R.string.notinstalled, Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(XposedApp.getInstance(), R.string.notinstalled, Toast.LENGTH_SHORT).show();
|
||||
continue;
|
||||
}
|
||||
|
||||
modulesList.println(module.app.sourceDir);
|
||||
|
||||
try {
|
||||
String installer = mPm.getInstallerPackageName(module.app.packageName);
|
||||
String installer = pm.getInstallerPackageName(module.app.packageName);
|
||||
if (!PLAY_STORE_PACKAGE.equals(installer))
|
||||
enabledModulesList.println(module.app.packageName);
|
||||
} catch (Exception ignored) {
|
||||
|
|
@ -247,27 +245,27 @@ public final class ModuleUtil {
|
|||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(XposedApp.TAG, "ModuleUtil -> cannot write " + MODULES_LIST_FILE, e);
|
||||
Toast.makeText(mApp, "cannot write " + MODULES_LIST_FILE + e, Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(XposedApp.getInstance(), "cannot write " + MODULES_LIST_FILE + e, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
private void showToast(int message) {
|
||||
if (mToast != null) {
|
||||
mToast.cancel();
|
||||
mToast = null;
|
||||
if (toast != null) {
|
||||
toast.cancel();
|
||||
toast = null;
|
||||
}
|
||||
mToast = Toast.makeText(mApp, mApp.getString(message), Toast.LENGTH_SHORT);
|
||||
mToast.show();
|
||||
toast = Toast.makeText(XposedApp.getInstance(), XposedApp.getInstance().getString(message), Toast.LENGTH_SHORT);
|
||||
toast.show();
|
||||
}
|
||||
|
||||
public void addListener(ModuleListener listener) {
|
||||
if (!mListeners.contains(listener))
|
||||
mListeners.add(listener);
|
||||
if (!listeners.contains(listener))
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeListener(ModuleListener listener) {
|
||||
mListeners.remove(listener);
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
public interface ModuleListener {
|
||||
|
|
@ -337,7 +335,7 @@ public final class ModuleUtil {
|
|||
|
||||
public String getAppName() {
|
||||
if (appName == null)
|
||||
appName = app.loadLabel(mPm).toString();
|
||||
appName = app.loadLabel(pm).toString();
|
||||
return appName;
|
||||
}
|
||||
|
||||
|
|
@ -351,7 +349,7 @@ public final class ModuleUtil {
|
|||
try {
|
||||
int resId = (Integer) descriptionRaw;
|
||||
if (resId != 0)
|
||||
descriptionTmp = mPm.getResourcesForApplication(app).getString(resId).trim();
|
||||
descriptionTmp = pm.getResourcesForApplication(app).getString(resId).trim();
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
|
@ -371,13 +369,13 @@ public final class ModuleUtil {
|
|||
Intent mIntent = new Intent(Intent.ACTION_MAIN);
|
||||
//mIntent.addCategory(ModulesFragment.SETTINGS_CATEGORY);
|
||||
mIntent.setPackage(app.packageName);
|
||||
List<ResolveInfo> ris = mPm.queryIntentActivities(mIntent, 0);
|
||||
List<ResolveInfo> ris = pm.queryIntentActivities(mIntent, 0);
|
||||
|
||||
Drawable result;
|
||||
if (ris == null || ris.size() <= 0)
|
||||
result = app.loadIcon(mPm);
|
||||
result = app.loadIcon(pm);
|
||||
else
|
||||
result = ris.get(0).activityInfo.loadIcon(mPm);
|
||||
result = ris.get(0).activityInfo.loadIcon(pm);
|
||||
iconCache = result.getConstantState();
|
||||
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package org.meowcat.edxposed.manager.util;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
|
|
@ -21,9 +22,6 @@ import org.meowcat.edxposed.manager.MainActivity;
|
|||
import org.meowcat.edxposed.manager.R;
|
||||
import org.meowcat.edxposed.manager.XposedApp;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public final class NotificationUtil {
|
||||
|
||||
public static final int NOTIFICATION_MODULE_NOT_ACTIVATED_YET = 0;
|
||||
|
|
@ -39,195 +37,188 @@ public final class NotificationUtil {
|
|||
private static final int PENDING_INTENT_ACTIVATE_MODULE = 5;
|
||||
private static final int PENDING_INTENT_INSTALL_APK = 6;
|
||||
|
||||
private static final String COLORED_NOTIFICATION = "colored_notification";
|
||||
private static final String HEADS_UP = "heads_up";
|
||||
private static final String FRAGMENT_ID = "fragment";
|
||||
|
||||
private static final String NOTIFICATION_UPDATE_CHANNEL = "app_update_channel";
|
||||
private static final String NOTIFICATION_MODULES_CHANNEL = "modules_channel";
|
||||
|
||||
private static Context sContext = null;
|
||||
private static NotificationManager sNotificationManager;
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private static Context context = null;
|
||||
private static NotificationManager notificationManager;
|
||||
private static SharedPreferences prefs;
|
||||
|
||||
public static void init() {
|
||||
if (sContext != null) return;
|
||||
if (context != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
sContext = XposedApp.getInstance();
|
||||
context = XposedApp.getInstance();
|
||||
prefs = XposedApp.getPreferences();
|
||||
sNotificationManager = (NotificationManager) sContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
NotificationChannel channel = new NotificationChannel(NOTIFICATION_UPDATE_CHANNEL, sContext.getString(R.string.download_section_update_available), NotificationManager.IMPORTANCE_DEFAULT);
|
||||
NotificationChannel channel1 = new NotificationChannel(NOTIFICATION_MODULES_CHANNEL, sContext.getString(R.string.nav_item_modules), NotificationManager.IMPORTANCE_DEFAULT);
|
||||
sNotificationManager.createNotificationChannel(channel);
|
||||
sNotificationManager.createNotificationChannel(channel1);
|
||||
NotificationChannel channelUpdate = new NotificationChannel(NOTIFICATION_UPDATE_CHANNEL, context.getString(R.string.download_section_update_available), NotificationManager.IMPORTANCE_DEFAULT);
|
||||
NotificationChannel channelModule = new NotificationChannel(NOTIFICATION_MODULES_CHANNEL, context.getString(R.string.nav_item_modules), NotificationManager.IMPORTANCE_DEFAULT);
|
||||
notificationManager.createNotificationChannel(channelUpdate);
|
||||
notificationManager.createNotificationChannel(channelModule);
|
||||
}
|
||||
}
|
||||
|
||||
public static void cancel(int id) {
|
||||
sNotificationManager.cancel(id);
|
||||
notificationManager.cancel(id);
|
||||
}
|
||||
|
||||
public static void cancel(String tag, int id) {
|
||||
sNotificationManager.cancel(tag, id);
|
||||
notificationManager.cancel(tag, id);
|
||||
}
|
||||
|
||||
public static void cancelAll() {
|
||||
sNotificationManager.cancelAll();
|
||||
notificationManager.cancelAll();
|
||||
}
|
||||
|
||||
public static void showNotActivatedNotification(String packageName, String appName) {
|
||||
Intent intent = new Intent(sContext, MainActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).putExtra(FRAGMENT_ID, 1);
|
||||
PendingIntent pModulesTab = PendingIntent.getActivity(sContext, PENDING_INTENT_OPEN_MODULES, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
Intent intent = new Intent(context, MainActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).putExtra(FRAGMENT_ID, 1);
|
||||
PendingIntent pModulesTab = PendingIntent.getActivity(context, PENDING_INTENT_OPEN_MODULES, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
String title = sContext.getString(R.string.module_is_not_activated_yet);
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(sContext).setContentTitle(title).setContentText(appName)
|
||||
.setTicker(title).setContentIntent(pModulesTab)
|
||||
.setVibrate(new long[]{0}).setAutoCancel(true)
|
||||
.setSmallIcon(R.drawable.ic_notification);
|
||||
|
||||
if (prefs.getBoolean(HEADS_UP, true) && Build.VERSION.SDK_INT >= 21)
|
||||
String title = context.getString(R.string.module_is_not_activated_yet);
|
||||
NotificationCompat.Builder builder = getNotificationBuilder(title, appName, NOTIFICATION_MODULES_CHANNEL)
|
||||
.setContentIntent(pModulesTab);
|
||||
if (prefs.getBoolean(HEADS_UP, true)) {
|
||||
builder.setPriority(2);
|
||||
builder.setColor(ContextCompat.getColor(sContext, R.color.colorPrimary));
|
||||
Intent iActivateAndReboot = new Intent(sContext, RebootReceiver.class);
|
||||
}
|
||||
Intent iActivateAndReboot = new Intent(context, RebootReceiver.class);
|
||||
iActivateAndReboot.putExtra(RebootReceiver.EXTRA_ACTIVATE_MODULE, packageName);
|
||||
PendingIntent pActivateAndReboot = PendingIntent.getBroadcast(sContext, PENDING_INTENT_ACTIVATE_MODULE_AND_REBOOT,
|
||||
PendingIntent pActivateAndReboot = PendingIntent.getBroadcast(context, PENDING_INTENT_ACTIVATE_MODULE_AND_REBOOT,
|
||||
iActivateAndReboot, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
Intent iActivate = new Intent(sContext, RebootReceiver.class);
|
||||
Intent iActivate = new Intent(context, RebootReceiver.class);
|
||||
iActivate.putExtra(RebootReceiver.EXTRA_ACTIVATE_MODULE, packageName);
|
||||
iActivate.putExtra(RebootReceiver.EXTRA_ACTIVATE_MODULE_AND_RETURN, true);
|
||||
PendingIntent pActivate = PendingIntent.getBroadcast(sContext, PENDING_INTENT_ACTIVATE_MODULE,
|
||||
PendingIntent pActivate = PendingIntent.getBroadcast(context, PENDING_INTENT_ACTIVATE_MODULE,
|
||||
iActivate, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
NotificationCompat.BigTextStyle notiStyle = new NotificationCompat.BigTextStyle();
|
||||
notiStyle.setBigContentTitle(title);
|
||||
notiStyle.bigText(sContext.getString(R.string.module_is_not_activated_yet_detailed, appName));
|
||||
builder.setStyle(notiStyle).setChannelId(NOTIFICATION_MODULES_CHANNEL);
|
||||
NotificationCompat.BigTextStyle style = new NotificationCompat.BigTextStyle();
|
||||
style.setBigContentTitle(title);
|
||||
style.bigText(context.getString(R.string.module_is_not_activated_yet_detailed, appName));
|
||||
builder.setStyle(style);
|
||||
|
||||
// Only show the quick activation button if any module has been
|
||||
// enabled before,
|
||||
// to ensure that the user know the way to disable the module later.
|
||||
if (!ModuleUtil.getInstance().getEnabledModules().isEmpty()) {
|
||||
builder.addAction(new NotificationCompat.Action.Builder(R.drawable.ic_apps, sContext.getString(R.string.activate_and_reboot), pActivateAndReboot).build());
|
||||
builder.addAction(new NotificationCompat.Action.Builder(R.drawable.ic_apps, sContext.getString(R.string.activate_only), pActivate).build());
|
||||
builder.addAction(new NotificationCompat.Action.Builder(R.drawable.ic_apps, context.getString(R.string.activate_and_reboot), pActivateAndReboot).build());
|
||||
builder.addAction(new NotificationCompat.Action.Builder(R.drawable.ic_apps, context.getString(R.string.activate_only), pActivate).build());
|
||||
}
|
||||
|
||||
sNotificationManager.notify(packageName, NOTIFICATION_MODULE_NOT_ACTIVATED_YET, builder.build());
|
||||
notificationManager.notify(packageName, NOTIFICATION_MODULE_NOT_ACTIVATED_YET, builder.build());
|
||||
}
|
||||
|
||||
public static void showModulesUpdatedNotification() {
|
||||
Intent intent = new Intent(sContext, MainActivity.class);
|
||||
Intent intent = new Intent(context, MainActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.putExtra(FRAGMENT_ID, 0);
|
||||
|
||||
PendingIntent pInstallTab = PendingIntent.getActivity(sContext, PENDING_INTENT_OPEN_INSTALL,
|
||||
PendingIntent pInstallTab = PendingIntent.getActivity(context, PENDING_INTENT_OPEN_INSTALL,
|
||||
intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
String title = sContext
|
||||
String title = context
|
||||
.getString(R.string.xposed_module_updated_notification_title);
|
||||
String message = sContext
|
||||
String message = context
|
||||
.getString(R.string.xposed_module_updated_notification);
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(sContext).setContentTitle(title).setContentText(message)
|
||||
.setTicker(title).setContentIntent(pInstallTab)
|
||||
.setVibrate(new long[]{0}).setAutoCancel(true)
|
||||
.setSmallIcon(R.drawable.ic_notification);
|
||||
|
||||
if (prefs.getBoolean(HEADS_UP, true) && Build.VERSION.SDK_INT >= 21)
|
||||
NotificationCompat.Builder builder = getNotificationBuilder(title, message, NOTIFICATION_MODULES_CHANNEL)
|
||||
.setContentIntent(pInstallTab);
|
||||
if (prefs.getBoolean(HEADS_UP, true)) {
|
||||
builder.setPriority(2);
|
||||
builder.setColor(ContextCompat.getColor(sContext, R.color.colorPrimary));
|
||||
Intent iSoftReboot = new Intent(sContext, RebootReceiver.class);
|
||||
}
|
||||
Intent iSoftReboot = new Intent(context, RebootReceiver.class);
|
||||
iSoftReboot.putExtra(RebootReceiver.EXTRA_SOFT_REBOOT, true);
|
||||
PendingIntent pSoftReboot = PendingIntent.getBroadcast(sContext, PENDING_INTENT_SOFT_REBOOT,
|
||||
PendingIntent pSoftReboot = PendingIntent.getBroadcast(context, PENDING_INTENT_SOFT_REBOOT,
|
||||
iSoftReboot, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
Intent iReboot = new Intent(sContext, RebootReceiver.class);
|
||||
PendingIntent pReboot = PendingIntent.getBroadcast(sContext, PENDING_INTENT_REBOOT,
|
||||
Intent iReboot = new Intent(context, RebootReceiver.class);
|
||||
PendingIntent pReboot = PendingIntent.getBroadcast(context, PENDING_INTENT_REBOOT,
|
||||
iReboot, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
builder.addAction(new NotificationCompat.Action.Builder(0, sContext.getString(R.string.reboot), pReboot).build());
|
||||
builder.addAction(new NotificationCompat.Action.Builder(0, sContext.getString(R.string.soft_reboot), pSoftReboot).build());
|
||||
builder.setChannelId(NOTIFICATION_MODULES_CHANNEL);
|
||||
builder.addAction(new NotificationCompat.Action.Builder(0, context.getString(R.string.reboot), pReboot).build());
|
||||
builder.addAction(new NotificationCompat.Action.Builder(0, context.getString(R.string.soft_reboot), pSoftReboot).build());
|
||||
|
||||
sNotificationManager.notify(null, NOTIFICATION_MODULES_UPDATED, builder.build());
|
||||
notificationManager.notify(null, NOTIFICATION_MODULES_UPDATED, builder.build());
|
||||
}
|
||||
|
||||
static void showModuleInstallNotification(@StringRes int title, @StringRes int message, String path, Object... args) {
|
||||
showModuleInstallNotification(sContext.getString(title), sContext.getString(message, args), path, title == R.string.installation_error);
|
||||
showModuleInstallNotification(context.getString(title), context.getString(message, args), path, title == R.string.installation_error);
|
||||
}
|
||||
|
||||
private static void showModuleInstallNotification(String title, String message, String path, boolean error) {
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(
|
||||
sContext).setContentTitle(title).setContentText(message)
|
||||
.setVibrate(new long[]{0}).setAutoCancel(true)
|
||||
.setSmallIcon(R.drawable.ic_notification);
|
||||
NotificationCompat.Builder builder = getNotificationBuilder(title, message, NOTIFICATION_MODULES_CHANNEL);
|
||||
|
||||
if (error) {
|
||||
Intent iInstallApk = new Intent(sContext, ApkReceiver.class);
|
||||
Intent iInstallApk = new Intent(context, ApkReceiver.class);
|
||||
iInstallApk.putExtra(ApkReceiver.EXTRA_APK_PATH, path);
|
||||
PendingIntent pInstallApk = PendingIntent.getBroadcast(sContext, PENDING_INTENT_INSTALL_APK, iInstallApk, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
PendingIntent pInstallApk = PendingIntent.getBroadcast(context, PENDING_INTENT_INSTALL_APK, iInstallApk, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
builder.addAction(new NotificationCompat.Action.Builder(0, sContext.getString(R.string.installation_apk_normal), pInstallApk).build());
|
||||
builder.addAction(new NotificationCompat.Action.Builder(0, context.getString(R.string.installation_apk_normal), pInstallApk).build());
|
||||
}
|
||||
|
||||
if (prefs.getBoolean(HEADS_UP, true) && Build.VERSION.SDK_INT >= 21)
|
||||
if (prefs.getBoolean(HEADS_UP, true)) {
|
||||
builder.setPriority(2);
|
||||
builder.setColor(ContextCompat.getColor(sContext, R.color.colorPrimary));
|
||||
}
|
||||
NotificationCompat.BigTextStyle notiStyle = new NotificationCompat.BigTextStyle();
|
||||
notiStyle.setBigContentTitle(title);
|
||||
notiStyle.bigText(message);
|
||||
builder.setStyle(notiStyle).setChannelId(NOTIFICATION_MODULES_CHANNEL);
|
||||
builder.setStyle(notiStyle);
|
||||
|
||||
sNotificationManager.notify(null, NOTIFICATION_MODULE_INSTALLATION, builder.build());
|
||||
notificationManager.notify(null, NOTIFICATION_MODULE_INSTALLATION, builder.build());
|
||||
|
||||
new android.os.Handler().postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
cancel(NOTIFICATION_MODULE_INSTALLATION);
|
||||
}
|
||||
}, 10 * 1000);
|
||||
new android.os.Handler().postDelayed(() -> cancel(NOTIFICATION_MODULE_INSTALLATION), 10 * 1000);
|
||||
}
|
||||
|
||||
public static void showModuleInstallingNotification(String appName) {
|
||||
String title = sContext.getString(R.string.install_load);
|
||||
String message = sContext.getString(R.string.install_load_apk, appName);
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(sContext).setContentTitle(title).setContentText(message)
|
||||
.setVibrate(new long[]{0}).setProgress(0, 0, true)
|
||||
.setSmallIcon(R.drawable.ic_notification).setOngoing(true);
|
||||
builder.setColor(ContextCompat.getColor(sContext, R.color.colorPrimary));
|
||||
String title = context.getString(R.string.install_load);
|
||||
String message = context.getString(R.string.install_load_apk, appName);
|
||||
NotificationCompat.Builder builder = getNotificationBuilder(title, message, NOTIFICATION_MODULES_CHANNEL)
|
||||
.setProgress(0, 0, true)
|
||||
.setOngoing(true);
|
||||
NotificationCompat.BigTextStyle notiStyle = new NotificationCompat.BigTextStyle();
|
||||
notiStyle.setBigContentTitle(title);
|
||||
notiStyle.bigText(message);
|
||||
builder.setStyle(notiStyle).setChannelId(NOTIFICATION_MODULES_CHANNEL);
|
||||
builder.setStyle(notiStyle);
|
||||
|
||||
sNotificationManager.notify(null, NOTIFICATION_MODULE_INSTALLING, builder.build());
|
||||
notificationManager.notify(null, NOTIFICATION_MODULE_INSTALLING, builder.build());
|
||||
}
|
||||
|
||||
public static void showInstallerUpdateNotification() {
|
||||
Intent intent = new Intent(sContext, MainActivity.class);
|
||||
Intent intent = new Intent(context, MainActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.putExtra(FRAGMENT_ID, 0);
|
||||
|
||||
PendingIntent pInstallTab = PendingIntent.getActivity(sContext, PENDING_INTENT_OPEN_INSTALL,
|
||||
PendingIntent pInstallTab = PendingIntent.getActivity(context, PENDING_INTENT_OPEN_INSTALL,
|
||||
intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
String title = sContext.getString(R.string.app_name);
|
||||
String message = sContext.getString(R.string.newVersion);
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(sContext).setContentTitle(title).setContentText(message)
|
||||
.setTicker(title).setContentIntent(pInstallTab)
|
||||
.setVibrate(new long[]{0}).setAutoCancel(true)
|
||||
.setSmallIcon(R.drawable.ic_notification);
|
||||
String title = context.getString(R.string.app_name);
|
||||
String message = context.getString(R.string.newVersion);
|
||||
NotificationCompat.Builder builder = getNotificationBuilder(title, message, NOTIFICATION_UPDATE_CHANNEL)
|
||||
.setContentIntent(pInstallTab);
|
||||
|
||||
if (prefs.getBoolean(HEADS_UP, true) && Build.VERSION.SDK_INT >= 21)
|
||||
if (prefs.getBoolean(HEADS_UP, true)) {
|
||||
builder.setPriority(2);
|
||||
builder.setColor(ContextCompat.getColor(sContext, R.color.colorPrimary));
|
||||
}
|
||||
NotificationCompat.BigTextStyle notiStyle = new NotificationCompat.BigTextStyle();
|
||||
notiStyle.setBigContentTitle(title);
|
||||
notiStyle.bigText(message);
|
||||
builder.setStyle(notiStyle).setChannelId(NOTIFICATION_UPDATE_CHANNEL);
|
||||
builder.setStyle(notiStyle);
|
||||
|
||||
sNotificationManager.notify(null, NOTIFICATION_INSTALLER_UPDATE, builder.build());
|
||||
notificationManager.notify(null, NOTIFICATION_INSTALLER_UPDATE, builder.build());
|
||||
}
|
||||
|
||||
private static NotificationCompat.Builder getNotificationBuilder(String title, String message, String channel) {
|
||||
return new NotificationCompat.Builder(context, channel)
|
||||
.setContentTitle(title)
|
||||
.setContentText(message)
|
||||
.setVibrate(new long[]{0})
|
||||
.setAutoCancel(true)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setColor(ContextCompat.getColor(context, R.color.colorPrimary));
|
||||
}
|
||||
|
||||
public static class RebootReceiver extends BroadcastReceiver {
|
||||
|
|
@ -244,7 +235,7 @@ public final class NotificationUtil {
|
|||
* expanded notification panel and is therefore not visible to the
|
||||
* user.
|
||||
*/
|
||||
sContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
|
||||
context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
|
||||
cancelAll();
|
||||
|
||||
if (intent.hasExtra(EXTRA_ACTIVATE_MODULE)) {
|
||||
|
|
@ -252,7 +243,7 @@ public final class NotificationUtil {
|
|||
ModuleUtil moduleUtil = ModuleUtil.getInstance();
|
||||
moduleUtil.setModuleEnabled(packageName, true);
|
||||
moduleUtil.updateModulesList(false);
|
||||
Toast.makeText(sContext, R.string.module_activated, Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(context, R.string.module_activated, Toast.LENGTH_SHORT).show();
|
||||
|
||||
if (intent.hasExtra(EXTRA_ACTIVATE_MODULE_AND_RETURN)) return;
|
||||
}
|
||||
|
|
@ -262,7 +253,6 @@ public final class NotificationUtil {
|
|||
return;
|
||||
}
|
||||
|
||||
List<String> messages = new LinkedList<>();
|
||||
boolean isSoftReboot = intent.getBooleanExtra(EXTRA_SOFT_REBOOT,
|
||||
false);
|
||||
int returnCode = isSoftReboot
|
||||
|
|
@ -287,7 +277,7 @@ public final class NotificationUtil {
|
|||
* expanded notification panel and is therefore not visible to the
|
||||
* user.
|
||||
*/
|
||||
sContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
|
||||
context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
|
||||
|
||||
if (intent.hasExtra(EXTRA_APK_PATH)) {
|
||||
String path = intent.getStringExtra(EXTRA_APK_PATH);
|
||||
|
|
|
|||
|
|
@ -46,48 +46,48 @@ import java.util.zip.GZIPInputStream;
|
|||
public class RepoLoader {
|
||||
private static final int UPDATE_FREQUENCY = 24 * 60 * 60 * 1000;
|
||||
private static String DEFAULT_REPOSITORIES;
|
||||
private static RepoLoader mInstance = null;
|
||||
private final List<RepoListener> mListeners = new CopyOnWriteArrayList<>();
|
||||
private final Map<String, ReleaseType> mLocalReleaseTypesCache = new HashMap<>();
|
||||
private XposedApp mApp;
|
||||
private SharedPreferences mPref;
|
||||
private SharedPreferences mModulePref;
|
||||
private ConnectivityManager mConMgr;
|
||||
private boolean mIsLoading = false;
|
||||
private boolean mReloadTriggeredOnce = false;
|
||||
private Map<Long, Repository> mRepositories = null;
|
||||
private ReleaseType mGlobalReleaseType;
|
||||
private SwipeRefreshLayout mSwipeRefreshLayout;
|
||||
private static RepoLoader instance = null;
|
||||
private final List<RepoListener> listeners = new CopyOnWriteArrayList<>();
|
||||
private final Map<String, ReleaseType> localReleaseTypesCache = new HashMap<>();
|
||||
private XposedApp app;
|
||||
private SharedPreferences pref;
|
||||
private SharedPreferences modulePref;
|
||||
private ConnectivityManager conMgr;
|
||||
private boolean isLoading = false;
|
||||
private boolean reloadTriggeredOnce = false;
|
||||
private Map<Long, Repository> repositories = null;
|
||||
private ReleaseType globalReleaseType;
|
||||
private SwipeRefreshLayout swipeRefreshLayout;
|
||||
|
||||
private RepoLoader() {
|
||||
mInstance = this;
|
||||
mApp = XposedApp.getInstance();
|
||||
mPref = mApp.getSharedPreferences("repo", Context.MODE_PRIVATE);
|
||||
instance = this;
|
||||
app = XposedApp.getInstance();
|
||||
pref = app.getSharedPreferences("repo", Context.MODE_PRIVATE);
|
||||
DEFAULT_REPOSITORIES = XposedApp.getPreferences().getBoolean("custom_list", false) ? "https://cdn.jsdelivr.net/gh/ElderDrivers/Repository-Website@gh-pages/assets/full.xml.gz" : "https://dl-xda.xposed.info/repo/full.xml.gz";
|
||||
mModulePref = mApp.getSharedPreferences("module_settings", Context.MODE_PRIVATE);
|
||||
mConMgr = (ConnectivityManager) mApp.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
mGlobalReleaseType = ReleaseType.fromString(XposedApp.getPreferences().getString("release_type_global", "stable"));
|
||||
modulePref = app.getSharedPreferences("module_settings", Context.MODE_PRIVATE);
|
||||
conMgr = (ConnectivityManager) app.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
globalReleaseType = ReleaseType.fromString(XposedApp.getPreferences().getString("release_type_global", "stable"));
|
||||
refreshRepositories();
|
||||
}
|
||||
|
||||
public static synchronized RepoLoader getInstance() {
|
||||
if (mInstance == null)
|
||||
if (instance == null)
|
||||
new RepoLoader();
|
||||
return mInstance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
private boolean refreshRepositories() {
|
||||
mRepositories = RepoDb.getRepositories();
|
||||
repositories = RepoDb.getRepositories();
|
||||
|
||||
// Unlikely case (usually only during initial load): DB state doesn't
|
||||
// fit to configuration
|
||||
boolean needReload = false;
|
||||
String[] config = (mPref.getString("repositories", DEFAULT_REPOSITORIES) + "").split("\\|");
|
||||
if (mRepositories.size() != config.length) {
|
||||
String[] config = (pref.getString("repositories", DEFAULT_REPOSITORIES) + "").split("\\|");
|
||||
if (repositories.size() != config.length) {
|
||||
needReload = true;
|
||||
} else {
|
||||
int i = 0;
|
||||
for (Repository repo : mRepositories.values()) {
|
||||
for (Repository repo : repositories.values()) {
|
||||
if (!repo.url.equals(config[i++])) {
|
||||
needReload = true;
|
||||
break;
|
||||
|
|
@ -102,16 +102,16 @@ public class RepoLoader {
|
|||
for (String url : config) {
|
||||
RepoDb.insertRepository(url);
|
||||
}
|
||||
mRepositories = RepoDb.getRepositories();
|
||||
repositories = RepoDb.getRepositories();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setReleaseTypeGlobal(String relTypeString) {
|
||||
ReleaseType relType = ReleaseType.fromString(relTypeString);
|
||||
if (mGlobalReleaseType == relType)
|
||||
if (globalReleaseType == relType)
|
||||
return;
|
||||
|
||||
mGlobalReleaseType = relType;
|
||||
globalReleaseType = relType;
|
||||
|
||||
// Updating the latest version for all modules takes a moment
|
||||
new Thread("DBUpdate") {
|
||||
|
|
@ -129,8 +129,10 @@ public class RepoLoader {
|
|||
if (getReleaseTypeLocal(packageName) == relType)
|
||||
return;
|
||||
|
||||
synchronized (mLocalReleaseTypesCache) {
|
||||
mLocalReleaseTypesCache.put(packageName, relType);
|
||||
synchronized (localReleaseTypesCache) {
|
||||
if (relType != null) {
|
||||
localReleaseTypesCache.put(packageName, relType);
|
||||
}
|
||||
}
|
||||
|
||||
RepoDb.updateModuleLatestVersion(packageName);
|
||||
|
|
@ -138,20 +140,22 @@ public class RepoLoader {
|
|||
}
|
||||
|
||||
private ReleaseType getReleaseTypeLocal(String packageName) {
|
||||
synchronized (mLocalReleaseTypesCache) {
|
||||
if (mLocalReleaseTypesCache.containsKey(packageName))
|
||||
return mLocalReleaseTypesCache.get(packageName);
|
||||
synchronized (localReleaseTypesCache) {
|
||||
if (localReleaseTypesCache.containsKey(packageName))
|
||||
return localReleaseTypesCache.get(packageName);
|
||||
|
||||
String value = mModulePref.getString(packageName + "_release_type",
|
||||
String value = modulePref.getString(packageName + "_release_type",
|
||||
null);
|
||||
ReleaseType result = (!TextUtils.isEmpty(value)) ? ReleaseType.fromString(value) : null;
|
||||
mLocalReleaseTypesCache.put(packageName, result);
|
||||
if (result != null) {
|
||||
localReleaseTypesCache.put(packageName, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public Repository getRepository(long repoId) {
|
||||
return mRepositories.get(repoId);
|
||||
return repositories.get(repoId);
|
||||
}
|
||||
|
||||
public Module getModule(String packageName) {
|
||||
|
|
@ -179,42 +183,42 @@ public class RepoLoader {
|
|||
if (localSetting != null)
|
||||
return localSetting;
|
||||
else
|
||||
return mGlobalReleaseType;
|
||||
return globalReleaseType;
|
||||
}
|
||||
|
||||
public void triggerReload(final boolean force) {
|
||||
mReloadTriggeredOnce = true;
|
||||
reloadTriggeredOnce = true;
|
||||
|
||||
if (force) {
|
||||
resetLastUpdateCheck();
|
||||
} else {
|
||||
long lastUpdateCheck = mPref.getLong("last_update_check", 0);
|
||||
long lastUpdateCheck = pref.getLong("last_update_check", 0);
|
||||
if (System.currentTimeMillis() < lastUpdateCheck + UPDATE_FREQUENCY)
|
||||
return;
|
||||
}
|
||||
|
||||
NetworkInfo netInfo = mConMgr.getActiveNetworkInfo();
|
||||
NetworkInfo netInfo = conMgr.getActiveNetworkInfo();
|
||||
if (netInfo == null || !netInfo.isConnected())
|
||||
return;
|
||||
|
||||
synchronized (this) {
|
||||
if (mIsLoading)
|
||||
if (isLoading)
|
||||
return;
|
||||
mIsLoading = true;
|
||||
isLoading = true;
|
||||
}
|
||||
mApp.updateProgressIndicator(mSwipeRefreshLayout);
|
||||
app.updateProgressIndicator(swipeRefreshLayout);
|
||||
|
||||
new Thread("RepositoryReload") {
|
||||
public void run() {
|
||||
final List<String> messages = new LinkedList<>();
|
||||
boolean hasChanged = downloadAndParseFiles(messages);
|
||||
|
||||
mPref.edit().putLong("last_update_check", System.currentTimeMillis()).apply();
|
||||
pref.edit().putLong("last_update_check", System.currentTimeMillis()).apply();
|
||||
|
||||
if (!messages.isEmpty()) {
|
||||
XposedApp.runOnUiThread(() -> {
|
||||
for (String message : messages) {
|
||||
Toast.makeText(mApp, message, Toast.LENGTH_LONG).show();
|
||||
Toast.makeText(app, message, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -223,38 +227,38 @@ public class RepoLoader {
|
|||
notifyListeners();
|
||||
|
||||
synchronized (this) {
|
||||
mIsLoading = false;
|
||||
isLoading = false;
|
||||
}
|
||||
mApp.updateProgressIndicator(mSwipeRefreshLayout);
|
||||
app.updateProgressIndicator(swipeRefreshLayout);
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
public void setSwipeRefreshLayout(SwipeRefreshLayout mSwipeRefreshLayout) {
|
||||
this.mSwipeRefreshLayout = mSwipeRefreshLayout;
|
||||
public void setSwipeRefreshLayout(SwipeRefreshLayout swipeRefreshLayout) {
|
||||
this.swipeRefreshLayout = swipeRefreshLayout;
|
||||
}
|
||||
|
||||
public void triggerFirstLoadIfNecessary() {
|
||||
if (!mReloadTriggeredOnce)
|
||||
if (!reloadTriggeredOnce)
|
||||
triggerReload(false);
|
||||
}
|
||||
|
||||
public void resetLastUpdateCheck() {
|
||||
mPref.edit().remove("last_update_check").apply();
|
||||
pref.edit().remove("last_update_check").apply();
|
||||
}
|
||||
|
||||
public synchronized boolean isLoading() {
|
||||
return mIsLoading;
|
||||
return isLoading;
|
||||
}
|
||||
|
||||
public void clear(boolean notify) {
|
||||
synchronized (this) {
|
||||
// TODO Stop reloading repository when it should be cleared
|
||||
if (mIsLoading)
|
||||
if (isLoading)
|
||||
return;
|
||||
|
||||
RepoDb.deleteRepositories();
|
||||
mRepositories = new LinkedHashMap<>(0);
|
||||
repositories = new LinkedHashMap<>(0);
|
||||
DownloadsUtil.clearCache(null);
|
||||
resetLastUpdateCheck();
|
||||
}
|
||||
|
|
@ -270,7 +274,7 @@ public class RepoLoader {
|
|||
sb.append("|");
|
||||
sb.append(repos[i]);
|
||||
}
|
||||
mPref.edit().putString("repositories", sb.toString()).apply();
|
||||
pref.edit().putString("repositories", sb.toString()).apply();
|
||||
if (refreshRepositories())
|
||||
triggerReload(true);
|
||||
}
|
||||
|
|
@ -287,7 +291,7 @@ public class RepoLoader {
|
|||
String filename = "repo_" + HashUtil.md5(repo) + ".xml";
|
||||
if (repo.endsWith(".gz"))
|
||||
filename += ".gz";
|
||||
return new File(mApp.getCacheDir(), filename);
|
||||
return new File(app.getCacheDir(), filename);
|
||||
}
|
||||
|
||||
private boolean downloadAndParseFiles(List<String> messages) {
|
||||
|
|
@ -296,7 +300,7 @@ public class RepoLoader {
|
|||
final AtomicInteger insertCounter = new AtomicInteger();
|
||||
final AtomicInteger deleteCounter = new AtomicInteger();
|
||||
|
||||
for (Entry<Long, Repository> repoEntry : mRepositories.entrySet()) {
|
||||
for (Entry<Long, Repository> repoEntry : repositories.entrySet()) {
|
||||
final long repoId = repoEntry.getKey();
|
||||
final Repository repo = repoEntry.getValue();
|
||||
|
||||
|
|
@ -367,13 +371,13 @@ public class RepoLoader {
|
|||
|
||||
RepoDb.setTransactionSuccessful();
|
||||
} catch (SQLiteException e) {
|
||||
XposedApp.runOnUiThread(() -> new MaterialAlertDialogBuilder(mApp)
|
||||
XposedApp.runOnUiThread(() -> new MaterialAlertDialogBuilder(app)
|
||||
.setTitle(R.string.restart_needed)
|
||||
.setMessage(R.string.cache_cleaned)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
||||
Intent i = new Intent(mApp, DownloadActivity.class);
|
||||
PendingIntent pi = PendingIntent.getActivity(mApp, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);
|
||||
AlarmManager mgr = (AlarmManager) mApp.getSystemService(Context.ALARM_SERVICE);
|
||||
Intent i = new Intent(app, DownloadActivity.class);
|
||||
PendingIntent pi = PendingIntent.getActivity(app, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);
|
||||
AlarmManager mgr = (AlarmManager) app.getSystemService(Context.ALARM_SERVICE);
|
||||
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, pi);
|
||||
System.exit(0);
|
||||
})
|
||||
|
|
@ -383,7 +387,7 @@ public class RepoLoader {
|
|||
DownloadsUtil.clearCache(url);
|
||||
} catch (Throwable t) {
|
||||
Log.e(XposedApp.TAG, "RepoLoader -> Cannot load repository from " + url, t);
|
||||
messages.add(mApp.getString(R.string.repo_load_failed, url, t.getMessage()));
|
||||
messages.add(app.getString(R.string.repo_load_failed, url, t.getMessage()));
|
||||
DownloadsUtil.clearCache(url);
|
||||
} finally {
|
||||
if (in != null)
|
||||
|
|
@ -391,6 +395,7 @@ public class RepoLoader {
|
|||
in.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
cacheFile.delete();
|
||||
RepoDb.endTransation();
|
||||
}
|
||||
|
|
@ -402,20 +407,20 @@ public class RepoLoader {
|
|||
}
|
||||
|
||||
public void addListener(RepoListener listener, boolean triggerImmediately) {
|
||||
if (!mListeners.contains(listener))
|
||||
mListeners.add(listener);
|
||||
if (!listeners.contains(listener))
|
||||
listeners.add(listener);
|
||||
|
||||
if (triggerImmediately)
|
||||
listener.onRepoReloaded(this);
|
||||
}
|
||||
|
||||
public void removeListener(RepoListener listener) {
|
||||
mListeners.remove(listener);
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
private void notifyListeners() {
|
||||
for (RepoListener listener : mListeners) {
|
||||
listener.onRepoReloaded(mInstance);
|
||||
for (RepoListener listener : listeners) {
|
||||
listener.onRepoReloaded(instance);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,308 +1,327 @@
|
|||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/snackbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:animateLayoutChanges="true"
|
||||
android:orientation="vertical"
|
||||
tools:context=".MainActivity">
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false">
|
||||
|
||||
<RelativeLayout
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/nestedScrollView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="72dp"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:layout_height="match_parent"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/app_icon"
|
||||
android:layout_width="42dp"
|
||||
android:layout_height="64dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:adjustViewBounds="true"
|
||||
android:contentDescription="@string/app_name"
|
||||
android:scaleType="centerCrop"
|
||||
app:srcCompat="@drawable/ic_launcher_foreground" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="25dp"
|
||||
android:layout_toEndOf="@id/app_icon"
|
||||
android:contentDescription="@string/app_name"
|
||||
android:text="@string/app_name"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Title"
|
||||
android:textSize="20sp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/menu_more"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:contentDescription="@string/abc_action_menu_overflow_description"
|
||||
android:focusable="true"
|
||||
android:padding="5dp"
|
||||
app:srcCompat="@drawable/ic_more"
|
||||
tools:ignore="PrivateResource" />
|
||||
</RelativeLayout>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
app:cardBackgroundColor="#4CAF50"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:cardElevation="8dp">
|
||||
|
||||
<RelativeLayout
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="18dp"
|
||||
android:paddingTop="20dp"
|
||||
android:paddingEnd="18dp"
|
||||
android:paddingBottom="20dp">
|
||||
android:layout_height="match_parent"
|
||||
android:animateLayoutChanges="true"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/status_icon"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:contentDescription="@string/Activated"
|
||||
android:tint="@android:color/white"
|
||||
app:srcCompat="@drawable/ic_check_circle" />
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="72dp"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status_title"
|
||||
android:layout_width="wrap_content"
|
||||
<ImageView
|
||||
android:id="@+id/app_icon"
|
||||
android:layout_width="42dp"
|
||||
android:layout_height="64dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:adjustViewBounds="true"
|
||||
android:contentDescription="@string/app_name"
|
||||
android:scaleType="centerCrop"
|
||||
app:srcCompat="@drawable/ic_launcher_foreground" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="25dp"
|
||||
android:layout_toEndOf="@id/app_icon"
|
||||
android:contentDescription="@string/app_name"
|
||||
android:text="@string/app_name"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Title"
|
||||
android:textSize="20sp"
|
||||
tools:ignore="RelativeOverlap" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/menu_more"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:contentDescription="@string/abc_action_menu_overflow_description"
|
||||
android:focusable="true"
|
||||
android:padding="2dp"
|
||||
app:srcCompat="@drawable/ic_more"
|
||||
tools:ignore="PrivateResource" />
|
||||
</RelativeLayout>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="25dp"
|
||||
android:layout_toEndOf="@id/status_icon"
|
||||
android:text="@string/Activated"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
||||
android:textColor="@android:color/white" />
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
app:cardBackgroundColor="#4CAF50"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:cardElevation="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status_summary"
|
||||
android:layout_width="wrap_content"
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="18dp"
|
||||
android:paddingTop="20dp"
|
||||
android:paddingEnd="18dp"
|
||||
android:paddingBottom="20dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/status_icon"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:contentDescription="@string/Activated"
|
||||
android:tint="@android:color/white"
|
||||
app:srcCompat="@drawable/ic_check_circle" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="25dp"
|
||||
android:layout_toEndOf="@id/status_icon"
|
||||
android:text="@string/Activated"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
||||
android:textColor="@android:color/white" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status_summary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/status_title"
|
||||
android:layout_alignStart="@id/status_title"
|
||||
android:layout_marginTop="5dp"
|
||||
android:text="@string/ActivatedDetail"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:textColor="@android:color/white" />
|
||||
</RelativeLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/modules"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/status_title"
|
||||
android:layout_alignStart="@id/status_title"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
app:cardCornerRadius="8dp">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="18dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingEnd="18dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/modules_icon"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:contentDescription="@string/Modules"
|
||||
app:srcCompat="@drawable/ic_apps" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/modules_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="25dp"
|
||||
android:layout_toEndOf="@id/modules_icon"
|
||||
android:text="@string/Modules"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/modules_summary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/modules_title"
|
||||
android:layout_alignStart="@id/modules_title"
|
||||
android:layout_marginTop="2dp"
|
||||
android:text="@string/ModulesDetail"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:textColor="@android:color/darker_gray" />
|
||||
</RelativeLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/downloads"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
app:cardCornerRadius="8dp">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="18dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingEnd="18dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/downloads_icon"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:contentDescription="@string/Downloads"
|
||||
app:srcCompat="@drawable/ic_get_app" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/downloads_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="25dp"
|
||||
android:layout_toEndOf="@id/downloads_icon"
|
||||
android:text="@string/Downloads"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/download_summary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/downloads_title"
|
||||
android:layout_alignStart="@id/downloads_title"
|
||||
android:layout_marginTop="2dp"
|
||||
android:text="@string/ModuleUpgradable"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:textColor="@android:color/darker_gray" />
|
||||
</RelativeLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/apps"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:background="@drawable/main_item_background"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:contentDescription="@string/Apps"
|
||||
app:srcCompat="@drawable/outline_list_24" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="25dp"
|
||||
android:text="@string/Apps"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/logs"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:text="@string/ActivatedDetail"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:textColor="@android:color/white" />
|
||||
</RelativeLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
android:background="@drawable/main_item_background"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/modules"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
app:cardCornerRadius="8dp">
|
||||
<ImageView
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:contentDescription="@string/Logs"
|
||||
app:srcCompat="@drawable/ic_assignment" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="18dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingEnd="18dp"
|
||||
android:paddingBottom="16dp">
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="25dp"
|
||||
android:text="@string/Logs"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/modules_icon"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:contentDescription="@string/Modules"
|
||||
app:srcCompat="@drawable/ic_apps" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/modules_title"
|
||||
android:layout_width="wrap_content"
|
||||
<LinearLayout
|
||||
android:id="@+id/settings"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="25dp"
|
||||
android:layout_toEndOf="@id/modules_icon"
|
||||
android:text="@string/Modules"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:background="@drawable/main_item_background"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/modules_summary"
|
||||
android:layout_width="wrap_content"
|
||||
<ImageView
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:contentDescription="@string/Settings"
|
||||
app:srcCompat="@drawable/ic_settings" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="25dp"
|
||||
android:text="@string/Settings"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/about"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/modules_title"
|
||||
android:layout_alignStart="@id/modules_title"
|
||||
android:layout_marginTop="2dp"
|
||||
android:text="@string/ModulesDetail"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:textColor="@android:color/darker_gray" />
|
||||
</RelativeLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:background="@drawable/main_item_background"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/downloads"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
app:cardCornerRadius="8dp">
|
||||
<ImageView
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:contentDescription="@string/About"
|
||||
app:srcCompat="@drawable/ic_info" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="18dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingEnd="18dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/downloads_icon"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:contentDescription="@string/Downloads"
|
||||
app:srcCompat="@drawable/ic_get_app" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/downloads_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="25dp"
|
||||
android:layout_toEndOf="@id/downloads_icon"
|
||||
android:text="@string/Downloads"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/download_summary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/downloads_title"
|
||||
android:layout_alignStart="@id/downloads_title"
|
||||
android:layout_marginTop="2dp"
|
||||
android:text="@string/ModuleUpgradable"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:textColor="@android:color/darker_gray" />
|
||||
</RelativeLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/apps"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:background="@drawable/main_item_background"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:contentDescription="@string/Apps"
|
||||
app:srcCompat="@drawable/outline_list_24" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="25dp"
|
||||
android:text="@string/Apps"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/logs"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:background="@drawable/main_item_background"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:contentDescription="@string/Logs"
|
||||
app:srcCompat="@drawable/ic_assignment" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="25dp"
|
||||
android:text="@string/Logs"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/settings"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:background="@drawable/main_item_background"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:contentDescription="@string/Settings"
|
||||
app:srcCompat="@drawable/ic_settings" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="25dp"
|
||||
android:text="@string/Settings"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/about"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:background="@drawable/main_item_background"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:contentDescription="@string/About"
|
||||
app:srcCompat="@drawable/ic_info" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="25dp"
|
||||
android:text="@string/About"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="25dp"
|
||||
android:text="@string/About"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
@ -1,114 +1,113 @@
|
|||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:background="?selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true">
|
||||
android:focusable="true"
|
||||
android:minHeight="?attr/listPreferredItemHeight"
|
||||
android:padding="8dp">
|
||||
|
||||
<RelativeLayout
|
||||
<ImageView
|
||||
android:id="@+id/app_icon"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:ignore="ContentDescription"
|
||||
tools:srcCompat="@tools:sample/backgrounds/scenic" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/app_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?attr/listPreferredItemHeight"
|
||||
android:orientation="horizontal"
|
||||
android:padding="8dp"
|
||||
android:paddingEnd="12dp">
|
||||
android:layout_marginStart="8dp"
|
||||
android:singleLine="false"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toEndOf="@id/app_icon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@tools:sample/first_names" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/app_icon"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_alignParentTop="true"
|
||||
tools:ignore="ContentDescription" />
|
||||
<TextView
|
||||
android:id="@+id/version_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:marqueeRepeatLimit="marquee_forever"
|
||||
android:maxWidth="100dp"
|
||||
android:singleLine="true"
|
||||
android:textAlignment="viewEnd"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="1.0"
|
||||
app:layout_constraintStart_toEndOf="@+id/app_name"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:ignore="RtlHardcoded"
|
||||
tools:text="@tools:sample/last_names" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linear"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_toEndOf="@id/app_icon">
|
||||
<TextView
|
||||
android:id="@+id/package_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintEnd_toStartOf="@+id/checkbox"
|
||||
app:layout_constraintHorizontal_bias="0"
|
||||
app:layout_constraintStart_toStartOf="@+id/app_name"
|
||||
app:layout_constraintTop_toBottomOf="@+id/app_name"
|
||||
tools:text="@tools:sample/cities" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/app_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_weight="1"
|
||||
android:singleLine="false"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textIsSelectable="false" />
|
||||
<TextView
|
||||
android:id="@+id/timestamps"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
app:layout_constraintStart_toStartOf="@+id/package_name"
|
||||
app:layout_constraintTop_toBottomOf="@+id/package_name"
|
||||
tools:text="@tools:sample/cities" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/version_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:ellipsize="marquee"
|
||||
android:gravity="end"
|
||||
android:marqueeRepeatLimit="marquee_forever"
|
||||
android:maxWidth="100dp"
|
||||
android:scrollHorizontally="true"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textIsSelectable="false"
|
||||
tools:ignore="RtlHardcoded" />
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:visibility="gone"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintEnd_toStartOf="@+id/checkbox"
|
||||
app:layout_constraintHorizontal_bias="0"
|
||||
app:layout_constraintStart_toStartOf="@+id/timestamps"
|
||||
app:layout_constraintTop_toBottomOf="@+id/timestamps"
|
||||
tools:text="@tools:sample/lorem" />
|
||||
|
||||
</LinearLayout>
|
||||
<androidx.appcompat.widget.SwitchCompat
|
||||
android:id="@+id/checkbox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="false"
|
||||
android:focusable="false"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/linear"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_toStartOf="@id/checkbox"
|
||||
android:layout_toEndOf="@id/app_icon"
|
||||
android:orientation="vertical">
|
||||
<TextView
|
||||
android:id="@+id/warning"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textColor="@color/warning"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintStart_toStartOf="@+id/description"
|
||||
app:layout_constraintTop_toBottomOf="@+id/description"
|
||||
tools:text="@tools:sample/lorem" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/package_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textIsSelectable="false" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timestamps"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/warning"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textColor="@color/warning"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.appcompat.widget.SwitchCompat
|
||||
android:id="@+id/checkbox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="4dp"
|
||||
android:checked="false"
|
||||
android:focusable="false" />
|
||||
|
||||
</RelativeLayout>
|
||||
</FrameLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
Loading…
Reference in New Issue