Skip to content

Commit

Permalink
Ready to release V5 (#376)
Browse files Browse the repository at this point in the history
Fixed Hot issue bugs related to Android API.
Add enhanced logging logic.
Add support IPV4/6 endpoint.
Add support multi-endpoint.
Improved performance.
Add Turkish Language.
  • Loading branch information
DanielcoderX authored Aug 10, 2024
1 parent 9fa9319 commit e686c69
Show file tree
Hide file tree
Showing 51 changed files with 2,025 additions and 1,133 deletions.
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ dependencies {
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation 'com.vdurmont:emoji-java:5.1.1'
implementation 'com.github.erfansn:locale-config-x:1.0.1'
implementation 'com.tencent:mmkv:1.3.7'
implementation fileTree(dir: 'libs', include: ['*.aar', '*.jar'])
}

Expand Down
20 changes: 7 additions & 13 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,17 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission
android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED"
android:minSdkVersion="34" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<!-- <uses-permission android:name="android.permission.USE_EXACT_ALARM" />-->
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED"/>
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<queries>
<intent>
<action android:name="android.intent.action.MAIN" />
</intent>
</queries>

<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
Expand All @@ -38,6 +33,7 @@
android:screenOrientation="portrait"
android:enableOnBackInvokedCallback="true"
android:theme="@style/Theme.OblivionUI"
android:networkSecurityConfig="@xml/network_security_config"
tools:targetApi="tiramisu"
tools:ignore="DiscouragedApi">

Expand All @@ -50,6 +46,7 @@
android:process=":vpn_background">
<intent-filter>
<action android:name="android.net.VpnService" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>

<meta-data
Expand Down Expand Up @@ -79,7 +76,7 @@
android:name="autoStoreLocales"
android:value="true" />
</service>

<activity android:name="org.bepass.oblivion.ui.SplashScreenActivity"
android:exported="true">
<intent-filter>
Expand All @@ -95,17 +92,14 @@
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES" />
<!-- <category android:name="android.intent.category.LAUNCHER" />-->
</intent-filter>
</activity>
<activity
android:name="org.bepass.oblivion.ui.InfoActivity"
android:exported="false" />

<activity
android:name="org.bepass.oblivion.ui.LogActivity"
android:exported="false" />

<activity
android:name="org.bepass.oblivion.ui.SettingsActivity"
android:exported="false"
Expand Down
70 changes: 29 additions & 41 deletions app/src/main/java/org/bepass/oblivion/BypassListAppsAdapter.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.bepass.oblivion;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
Expand Down Expand Up @@ -28,48 +29,42 @@
import java.util.concurrent.Executors;

public class BypassListAppsAdapter extends RecyclerView.Adapter<BypassListAppsAdapter.ViewHolder> {

private final ExecutorService executor = Executors.newSingleThreadExecutor();
private final Handler handler = new Handler(Looper.getMainLooper());
private final FileManager fm;
private final LoadListener loadListener;
private List<AppInfo> appList = new ArrayList<>();
private OnAppSelectListener onAppSelectListener;


public BypassListAppsAdapter(Context context, LoadListener loadListener) {
fm = FileManager.getInstance(context);
this.loadListener = loadListener;
if (loadListener != null)
loadListener.onLoad(true);
loadApps(context, false);
}

private void loadApps(Context context, boolean shouldShowSystemApps) {
if (loadListener != null) loadListener.onLoad(true);
executor.submit(() -> {
//Querying installed apps is pretty expensive. Offload it to a worker thread.
this.appList = getInstalledApps(context, false);
//Post the result to the main looper.
handler.post(this::notifyDataSetChanged);
appList = getInstalledApps(context, shouldShowSystemApps);
handler.post(() -> {
if (loadListener != null)
loadListener.onLoad(false);
notifyDataSetChanged();
if (loadListener != null) loadListener.onLoad(false);
});
});

}


private static List<AppInfo> getInstalledApps(Context context, boolean shouldShowSystemApps) {
FileManager fm = FileManager.getInstance(context);
Set<String> selectedApps = fm.getStringSet("splitTunnelApps", new HashSet<>());

final PackageManager pm = context.getPackageManager();
List<ApplicationInfo> packages = pm.getInstalledApplications(PackageManager.GET_META_DATA);
private List<AppInfo> getInstalledApps(Context context, boolean shouldShowSystemApps) {
Set<String> selectedApps = FileManager.getStringSet("splitTunnelApps", new HashSet<>());
PackageManager packageManager = context.getPackageManager();
@SuppressLint("QueryPermissionsNeeded") List<ApplicationInfo> packages = packageManager.getInstalledApplications(PackageManager.GET_META_DATA);
List<AppInfo> appList = new ArrayList<>(packages.size());

for (ApplicationInfo packageInfo : packages) {
if ((packageInfo.flags & ApplicationInfo.FLAG_SYSTEM) == ApplicationInfo.FLAG_SYSTEM && !shouldShowSystemApps)
continue;
if (packageInfo.packageName.equals(context.getPackageName()))
continue;
if (!shouldShowSystemApps && (packageInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) continue;
if (packageInfo.packageName.equals(context.getPackageName())) continue;

appList.add(new AppInfo(
packageInfo.loadLabel(pm).toString(),
() -> packageInfo.loadIcon(pm),
packageInfo.loadLabel(packageManager).toString(),
() -> packageInfo.loadIcon(packageManager),
packageInfo.packageName,
selectedApps.contains(packageInfo.packageName)
));
Expand All @@ -78,15 +73,7 @@ private static List<AppInfo> getInstalledApps(Context context, boolean shouldSho
}

public void setShouldShowSystemApps(Context context, boolean shouldShowSystemApps) {
if (loadListener != null) loadListener.onLoad(true);
executor.submit(() -> {
appList = getInstalledApps(context, shouldShowSystemApps);
handler.post(this::notifyDataSetChanged);
handler.post(() -> {
if (loadListener != null) loadListener.onLoad(false);
});
});

loadApps(context, shouldShowSystemApps);
}

public void setOnAppSelectListener(OnAppSelectListener onAppSelectListener) {
Expand All @@ -110,19 +97,20 @@ public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.itemView.setOnClickListener(v -> {
appInfo.isSelected = !appInfo.isSelected;
notifyItemChanged(position);
Set<String> newSet = new HashSet<>(fm.getStringSet("splitTunnelApps", new HashSet<>()));

Set<String> newSet = new HashSet<>(FileManager.getStringSet("splitTunnelApps", new HashSet<>()));
if (appInfo.isSelected) {
newSet.add(appInfo.packageName);
} else {
newSet.remove(appInfo.packageName);
}
fm.set("splitTunnelApps", newSet);
FileManager.set("splitTunnelApps", newSet);

if (onAppSelectListener != null)
onAppSelectListener.onSelect(appInfo.packageName, appInfo.isSelected);
});
}


@Override
public int getItemCount() {
return appList.size();
Expand Down Expand Up @@ -155,15 +143,15 @@ public static class AppInfo {
IconLoader iconLoader;
boolean isSelected;

AppInfo(String name, IconLoader iconLoader, String packageName, boolean isSelected) {
this.appName = name;
AppInfo(String appName, IconLoader iconLoader, String packageName, boolean isSelected) {
this.appName = appName;
this.packageName = packageName;
this.iconLoader = iconLoader;
this.isSelected = isSelected;
}

private interface IconLoader {
interface IconLoader {
Drawable load();
}
}
}
}
5 changes: 2 additions & 3 deletions app/src/main/java/org/bepass/oblivion/EditSheet.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ public class EditSheet {

public EditSheet(Context context, String title, String sharedPrefKey, SheetsCallBack sheetsCallBack) {
this.context = context;
fileManager = FileManager.getInstance(context);

this.title = context.getString(R.string.editSheetEndpoint).replace("Endpoint",title);
this.sharedPrefKey = sharedPrefKey;
Expand Down Expand Up @@ -61,11 +60,11 @@ public void start() {
}

titleView.setText(title);
value.setText(fileManager.getString("USERSETTING_" + sharedPrefKey));
value.setText(FileManager.getString("USERSETTING_" + sharedPrefKey));

cancel.setOnClickListener(v -> sheet.cancel());
apply.setOnClickListener(v -> {
fileManager.set("USERSETTING_" + sharedPrefKey, value.getText().toString());
FileManager.set("USERSETTING_" + sharedPrefKey, value.getText().toString());
sheet.cancel();
});

Expand Down
128 changes: 128 additions & 0 deletions app/src/main/java/org/bepass/oblivion/EndpointsBottomSheet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package org.bepass.oblivion;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.google.android.material.bottomsheet.BottomSheetDialogFragment;

import org.bepass.oblivion.utils.FileManager;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class EndpointsBottomSheet extends BottomSheetDialogFragment {
private List<Endpoint> endpointsList;
public EndpointSelectionListener selectionListener;

@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.bottom_sheet_endpoints, container, false);

RecyclerView recyclerView = view.findViewById(R.id.recyclerView);
endpointsList = new ArrayList<>();
loadEndpoints();

recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
EndpointsAdapter adapter = new EndpointsAdapter(endpointsList, this::onEndpointSelected);
recyclerView.setAdapter(adapter);

return view;
}

private void loadEndpoints() {
Set<String> savedEndpoints = FileManager.getStringSet("saved_endpoints", new HashSet<>());
for (String endpoint : savedEndpoints) {
String[] parts = endpoint.split("::");
if (parts.length == 2) {
endpointsList.add(new Endpoint(parts[0], parts[1]));
}
}
}

private void onEndpointSelected(String content) {
if (selectionListener != null) {
selectionListener.onEndpointSelected(content);
}
dismiss(); // Close the bottom sheet after selection
}

public void setEndpointSelectionListener(EndpointSelectionListener listener) {
this.selectionListener = listener;
}

private static class Endpoint {
private final String title;
private final String content;

Endpoint(String title, String content) {
this.title = title;
this.content = content;
}

public String getTitle() {
return title;
}

public String getContent() {
return content;
}
}

private static class EndpointsAdapter extends RecyclerView.Adapter<EndpointsAdapter.EndpointViewHolder> {
private final List<Endpoint> endpointsList;
public final EndpointSelectionListener selectionListener;

EndpointsAdapter(List<Endpoint> endpointsList, EndpointSelectionListener selectionListener) {
this.endpointsList = endpointsList;
this.selectionListener = selectionListener;
}

@NonNull
@Override
public EndpointViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_endpoint, parent, false);
return new EndpointViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull EndpointViewHolder holder, int position) {
Endpoint endpoint = endpointsList.get(position);
holder.titleTextView.setText(endpoint.getTitle());
holder.contentTextView.setText(endpoint.getContent());

holder.itemView.setOnClickListener(v -> {
if (selectionListener != null) {
selectionListener.onEndpointSelected(endpoint.getContent());
}
});
}

@Override
public int getItemCount() {
return endpointsList.size();
}

static class EndpointViewHolder extends RecyclerView.ViewHolder {
TextView titleTextView, contentTextView;

EndpointViewHolder(@NonNull View itemView) {
super(itemView);
titleTextView = itemView.findViewById(R.id.titleTextView);
contentTextView = itemView.findViewById(R.id.contentTextView);
}
}
}

public interface EndpointSelectionListener {
void onEndpointSelected(String content);
}
}
Loading

0 comments on commit e686c69

Please sign in to comment.