Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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">
<activity
android:name=".MainActivity"
android:launchMode="singleInstance"
android:exported="true">
</activity>

<activity-alias
android:name=".Home"
android:targetActivity=".MainActivity"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</activity-alias>
<activity-alias
android:name=".XposedSettings"
android:targetActivity=".MainActivity"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="de.robv.android.xposed.category.MODULE_SETTINGS" />
</intent-filter>
</activity-alias>

<receiver
android:name=".BootCompletedReceiver"
android:exported="true">
Expand Down
181 changes: 106 additions & 75 deletions app/src/main/java/com/kooritea/fcmfix/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,42 +14,39 @@
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;
import androidx.core.app.ActivityCompat;
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<String> allowList = new HashSet<>();
JSONObject config = new JSONObject();
Expand All @@ -74,9 +71,6 @@ public void onServiceBind(@NonNull XposedService service) {
xposedService = service;
runOnUiThread(() -> {
loadConfigFromRemotePreferences();
if (appListAdapter != null) {
appListAdapter.notifyDataSetChanged();
}
});
}

Expand Down Expand Up @@ -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<>()));
Expand All @@ -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<AppInfo> buildAppList() {
Set<String> allowListSet = new HashSet<>(allowList);
List<AppInfo> _allowList = new ArrayList<>();
List<AppInfo> _notAllowList = new ArrayList<>();
List<AppInfo> _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<AppInfo> {
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 {
Expand All @@ -145,7 +205,7 @@ public AppInfo(PackageInfo packageInfo) {

private class AppListAdapter extends RecyclerView.Adapter<AppListAdapter.ViewHolder> {

private final List<AppInfo> mAppList;
private final List<AppInfo> mAppList = new ArrayList<>();
class ViewHolder extends RecyclerView.ViewHolder {
View appView;
ImageView icon;
Expand All @@ -166,57 +226,8 @@ public ViewHolder(View view) {
}

public AppListAdapter(){
Set<String> allowListSet = new HashSet<>(allowList);
allowListSet.containsAll(allowList);
List<AppInfo> _allowList = new ArrayList<>();
List<AppInfo> _notAllowList = new ArrayList<>();
List<AppInfo> _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<AppInfo> {
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(需重启生效)")
Expand All @@ -225,6 +236,12 @@ public int compare(AppInfo a1, AppInfo a2) {
}
}

public void submitList(List<AppInfo> appList) {
mAppList.clear();
mAppList.addAll(appList);
notifyDataSetChanged();
}


@SuppressLint("NotifyDataSetChanged")
@NonNull
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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);

Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<resources>
<string name="app_name">fcmfix</string>
<string name="description">让FCM/GCM唤醒未启动的应用进行发送通知</string>
</resources>