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