diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 0d460b6..17659c4 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -14,17 +14,37 @@
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
+ android:description="@string/description"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
+
+
+
-
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/com/kooritea/fcmfix/MainActivity.java b/app/src/main/java/com/kooritea/fcmfix/MainActivity.java
index 53b6e8b..79ab313 100644
--- a/app/src/main/java/com/kooritea/fcmfix/MainActivity.java
+++ b/app/src/main/java/com/kooritea/fcmfix/MainActivity.java
@@ -14,15 +14,10 @@
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
+import android.view.*;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
-
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
@@ -30,26 +25,28 @@
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
-
+import com.kooritea.fcmfix.util.IceboxUtils;
import io.github.libxposed.service.XposedService;
import io.github.libxposed.service.XposedServiceHelper;
-
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.text.Collator;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Set;
-
-import com.kooritea.fcmfix.util.IceboxUtils;
+import java.util.*;
public class MainActivity extends AppCompatActivity {
private AppListAdapter appListAdapter;
+ private RecyclerView recyclerView;
+ private final Handler configRetryHandler = new Handler();
+ private final Runnable configRetryRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if (!loadConfigFromRemotePreferencesInternal()) {
+ configRetryHandler.postDelayed(this, 500);
+ }
+ }
+ };
private static XposedService xposedService;
Set allowList = new HashSet<>();
JSONObject config = new JSONObject();
@@ -74,9 +71,6 @@ public void onServiceBind(@NonNull XposedService service) {
xposedService = service;
runOnUiThread(() -> {
loadConfigFromRemotePreferences();
- if (appListAdapter != null) {
- appListAdapter.notifyDataSetChanged();
- }
});
}
@@ -111,11 +105,11 @@ private void ensureDefaultConfigValues() {
}
}
- private void loadConfigFromRemotePreferences() {
+ private boolean loadConfigFromRemotePreferencesInternal() {
ensureDefaultConfigValues();
SharedPreferences pref = getRemotePreferencesOrNull();
if (pref == null) {
- return;
+ return false;
}
this.allowList.clear();
this.allowList.addAll(pref.getStringSet("allowList", new HashSet<>()));
@@ -127,6 +121,72 @@ private void loadConfigFromRemotePreferences() {
} catch (JSONException e) {
Log.e("loadRemoteConfig", e.toString());
}
+ return true;
+ }
+
+ private void loadConfigFromRemotePreferences() {
+ if (loadConfigFromRemotePreferencesInternal()) {
+ refreshAppList();
+ }
+ }
+
+ private void refreshAppList() {
+ if (appListAdapter != null) {
+ appListAdapter.submitList(buildAppList());
+ }
+ }
+
+ private List buildAppList() {
+ Set allowListSet = new HashSet<>(allowList);
+ List _allowList = new ArrayList<>();
+ List _notAllowList = new ArrayList<>();
+ List _notFoundFcm = new ArrayList<>();
+ PackageManager packageManager = getPackageManager();
+ for (PackageInfo packageInfo : packageManager.getInstalledPackages(PackageManager.GET_RECEIVERS | PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_UNINSTALLED_PACKAGES)) {
+ boolean flag = false;
+ AppInfo appInfo = new AppInfo(packageInfo);
+ if (packageInfo.receivers != null) {
+ for (ActivityInfo receiverInfo : packageInfo.receivers) {
+ if (receiverInfo.name.equals("com.google.firebase.iid.FirebaseInstanceIdReceiver") || receiverInfo.name.equals("com.google.android.gms.measurement.AppMeasurementReceiver")) {
+ flag = true;
+ appInfo.includeFcm = true;
+ break;
+ }
+ }
+ } else {
+ continue;
+ }
+ if (allowListSet.contains(appInfo.packageName)) {
+ appInfo.isAllow = true;
+ _allowList.add(appInfo);
+ } else {
+ if (flag) {
+ _notAllowList.add(appInfo);
+ } else {
+ _notFoundFcm.add(appInfo);
+ }
+ }
+ }
+ class SortName implements Comparator {
+ final Collator localCompare = Collator.getInstance(Locale.getDefault());
+
+ @Override
+ public int compare(AppInfo a1, AppInfo a2) {
+ if (localCompare.compare(a1.name, a2.name) > 0) {
+ return 1;
+ } else if (localCompare.compare(a1.name, a2.name) < 0) {
+ return -1;
+ }
+ return 0;
+ }
+ }
+ final SortName sortName = new SortName();
+ _allowList.sort(sortName);
+ _notAllowList.sort(sortName);
+ _notFoundFcm.sort(sortName);
+ _allowList.addAll(_notAllowList);
+ _allowList.addAll(_notFoundFcm);
+ return _allowList;
}
private class AppInfo {
@@ -145,7 +205,7 @@ public AppInfo(PackageInfo packageInfo) {
private class AppListAdapter extends RecyclerView.Adapter {
- private final List mAppList;
+ private final List mAppList = new ArrayList<>();
class ViewHolder extends RecyclerView.ViewHolder {
View appView;
ImageView icon;
@@ -166,57 +226,8 @@ public ViewHolder(View view) {
}
public AppListAdapter(){
- Set allowListSet = new HashSet<>(allowList);
- allowListSet.containsAll(allowList);
- List _allowList = new ArrayList<>();
- List _notAllowList = new ArrayList<>();
- List _notFoundFcm = new ArrayList<>();
- PackageManager packageManager = getPackageManager();
- for(PackageInfo packageInfo : packageManager.getInstalledPackages(PackageManager.GET_RECEIVERS | PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_UNINSTALLED_PACKAGES)) {
- boolean flag = false;
- AppInfo appInfo = new AppInfo(packageInfo);
- if (packageInfo.receivers != null) {
- for (ActivityInfo receiverInfo : packageInfo.receivers ){
- if(receiverInfo.name.equals("com.google.firebase.iid.FirebaseInstanceIdReceiver") || receiverInfo.name.equals("com.google.android.gms.measurement.AppMeasurementReceiver")){
- flag = true;
- appInfo.includeFcm = true;
- break;
- }
- }
- }else{
- continue;
- }
- if(allowListSet.contains(appInfo.packageName)){
- appInfo.isAllow = true;
- _allowList.add(appInfo);
- }else{
- if(flag){
- _notAllowList.add(appInfo);
- }else{
- _notFoundFcm.add(appInfo);
- }
- }
- }
- class SortName implements Comparator {
- final Collator localCompare = Collator.getInstance(Locale.getDefault());
- @Override
- public int compare(AppInfo a1, AppInfo a2) {
- if(localCompare.compare(a1.name,a2.name)>0){
- return 1;
- }else if (localCompare.compare(a1.name, a2.name) < 0) {
- return -1;
- }
- return 0;
- }
- }
- final SortName sortName = new SortName();
- _allowList.sort(sortName);
- _notAllowList.sort(sortName);
- _notFoundFcm.sort(sortName);
- _allowList.addAll(_notAllowList);
- _allowList.addAll(_notFoundFcm);
- this.mAppList = _allowList;
- if(_allowList.size() == 0 || _allowList.isEmpty() ||(_allowList.size() == 1 && "com.kooritea.fcmfix".equals(_allowList.get(0).packageName))){
+ submitList(buildAppList());
+ if(mAppList.size() == 0 || mAppList.isEmpty() ||(mAppList.size() == 1 && "com.kooritea.fcmfix".equals(mAppList.get(0).packageName))){
new AlertDialog.Builder(MainActivity.this)
.setTitle("请在系统设置中授予读取应用列表权限")
.setMessage("或直接编辑" + getApplicationContext().getFilesDir().getAbsolutePath() + "/config.json(需重启生效)")
@@ -225,6 +236,12 @@ public int compare(AppInfo a1, AppInfo a2) {
}
}
+ public void submitList(List appList) {
+ mAppList.clear();
+ mAppList.addAll(appList);
+ notifyDataSetChanged();
+ }
+
@SuppressLint("NotifyDataSetChanged")
@NonNull
@@ -268,10 +285,12 @@ public int getItemCount() {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
- RecyclerView recyclerView = findViewById(R.id.recycler_view);
+ recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
initXposedService();
+ loadConfigFromRemotePreferences();
+ configRetryHandler.postDelayed(configRetryRunnable, 300);
try {
if (ContextCompat.checkSelfPermission(this, IceboxUtils.SDK_PERMISSION) != PackageManager.PERMISSION_GRANTED) {
@@ -288,6 +307,18 @@ protected void onCreate(Bundle savedInstanceState) {
}, 1000);
}
+ @Override
+ protected void onResume() {
+ super.onResume();
+ loadConfigFromRemotePreferences();
+ }
+
+ @Override
+ protected void onDestroy() {
+ configRetryHandler.removeCallbacks(configRetryRunnable);
+ super.onDestroy();
+ }
+
@Nullable
@Override
public View onCreateView(@Nullable View parent, @NonNull String name, @NonNull Context context, @NonNull AttributeSet attrs) {
@@ -329,7 +360,7 @@ private void updateConfig(){
@Override
public boolean onCreateOptionsMenu (Menu menu){
-// menu.add("隐藏启动器图标").setCheckable(true);
+ menu.add("隐藏启动器图标").setCheckable(true);
menu.add("阻止应用停止时自动清除通知").setCheckable(true);
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 67f1b6b..69e608e 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,3 +1,4 @@
fcmfix
+ 让FCM/GCM唤醒未启动的应用进行发送通知
\ No newline at end of file