Skip to content

Commit

Permalink
Fixed battery issue, improved VpnService performance
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielcoderX authored and markpash committed Jun 7, 2024
1 parent d2bd505 commit 9fd7a40
Show file tree
Hide file tree
Showing 11 changed files with 246 additions and 72 deletions.
7 changes: 0 additions & 7 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,6 @@ android {
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion '1.4.3'
}
packagingOptions {
resources.excludes.add("META-INF/*")
}
Expand All @@ -54,7 +48,6 @@ configurations {
}

dependencies {
implementation 'androidx.activity:activity-compose:1.9.0'
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'com.google.android.material:material:1.12.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
Expand Down
66 changes: 66 additions & 0 deletions app/src/main/java/org/bepass/oblivion/BatteryOptimization.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.bepass.oblivion

import android.annotation.SuppressLint
import android.app.AlertDialog
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.PowerManager
import android.provider.Settings
import android.view.LayoutInflater
import android.widget.Button
import android.widget.TextView

/**
* Checks if the app is running in restricted background mode.
* Returns true if running in restricted mode, false otherwise.
*/
fun isBatteryOptimizationEnabled(context: Context): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val powerManager = context.getSystemService(Context.POWER_SERVICE) as? PowerManager
powerManager?.isIgnoringBatteryOptimizations(context.packageName) == false
} else {
false
}
}

/**
* Directly requests to ignore battery optimizations for the app.
*/
@SuppressLint("BatteryLife")
fun requestIgnoreBatteryOptimizations(context: Context) {
val intent = Intent().apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
data = Uri.parse("package:${context.packageName}")
}
}
context.startActivity(intent)
}


/**
* Shows a dialog explaining the need for disabling battery optimization and navigates to the app's settings.
*/
fun showBatteryOptimizationDialog(context: Context) {
val dialogView = LayoutInflater.from(context).inflate(R.layout.dialog_battery_optimization, null)

val dialog = AlertDialog.Builder(context).apply {
setView(dialogView)
}.create()

dialogView.findViewById<TextView>(R.id.dialog_title).text = context.getString(R.string.batteryOpL)
dialogView.findViewById<TextView>(R.id.dialog_message).text = context.getString(R.string.dialBtText)

dialogView.findViewById<Button>(R.id.dialog_button_positive).setOnClickListener {
requestIgnoreBatteryOptimizations(context)
dialog.dismiss()
}

dialogView.findViewById<Button>(R.id.dialog_button_negative).setOnClickListener {
dialog.dismiss()
}

dialog.show()
}
42 changes: 2 additions & 40 deletions app/src/main/java/org/bepass/oblivion/MainActivity.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
package org.bepass.oblivion;

import static org.bepass.oblivion.OblivionVpnService.startVpnService;
import static org.bepass.oblivion.OblivionVpnService.stopVpnService;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
import android.provider.Settings;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
Expand All @@ -28,7 +25,6 @@
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;

import com.google.android.material.floatingactionbutton.FloatingActionButton;

Expand All @@ -43,12 +39,6 @@ public class MainActivity extends StateAwareBaseActivity {
private long backPressedTime;
private Toast backToast;
private LocaleHandler localeHandler;
private final ActivityResultLauncher<Intent> batteryOptimizationLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
// Do nothing, as no return value is expected
});

private final Handler handler = new Handler();

@Override
Expand All @@ -70,11 +60,6 @@ protected void onCreate(Bundle savedInstanceState) {
FloatingActionButton floatingActionButton = findViewById(R.id.floatingActionButton);
floatingActionButton.setOnClickListener(v -> localeHandler.showLanguageSelectionDialog(()->
localeHandler.restartActivity(this)));
if (!isIgnoringBatteryOptimizations()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestIgnoreBatteryOptimizations();
}
}
// Views
ImageView infoIcon = findViewById(R.id.info_icon);
ImageView logIcon = findViewById(R.id.bug_icon);
Expand Down Expand Up @@ -119,7 +104,7 @@ protected void onCreate(Bundle savedInstanceState) {
}
// Start the VPN service if it's disconnected
if (lastKnownConnectionState.isDisconnected()) {
OblivionVpnService.startVpnService(this);
startVpnService(this);
}
// To check is Internet Connection is available
handler.postDelayed(new Runnable() {
Expand Down Expand Up @@ -190,29 +175,6 @@ private void checkInternetConnectionAndDisconnectVPN() {
stopVpnService(this);
}
}
private boolean isIgnoringBatteryOptimizations() {
String packageName = getPackageName();
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
if (pm != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return pm.isIgnoringBatteryOptimizations(packageName);
}
}
return false;
}
@SuppressLint("BatteryLife")
@RequiresApi(api = Build.VERSION_CODES.M)
private void requestIgnoreBatteryOptimizations() {
try {
Intent intent = new Intent();
String packageName = getPackageName();
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
batteryOptimizationLauncher.launch(intent);
} catch (Exception e) {
Toast.makeText(this, "Unable to request ignore battery optimizations", Toast.LENGTH_SHORT).show();
}
}
protected void cleanOrMigrateSettings() {
// Get the global FileManager instance
FileManager fileManager = FileManager.getInstance(getApplicationContext());
Expand Down
62 changes: 38 additions & 24 deletions app/src/main/java/org/bepass/oblivion/OblivionVpnService.java
Original file line number Diff line number Diff line change
Expand Up @@ -373,53 +373,67 @@ public void onDestroy() {
public void onRevoke() {
setLastKnownState(ConnectionState.DISCONNECTED);
Log.i(TAG, "Stopping VPN");

// Stop foreground service and notification
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager notificationManager = getSystemService(NotificationManager.class);
if (notificationManager != null) {
notificationManager.deleteNotificationChannel("oblivion");
}
}
try {
stopForeground(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager notificationManager = getSystemService(NotificationManager.class);
if (notificationManager != null) {
notificationManager.deleteNotificationChannel("oblivion");
}
}
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "Error stopping foreground service and notification", e);
}

// Release the wake lock if held
if (wLock != null && wLock.isHeld()) {
wLock.release();
wLock = null;
try {
if (wLock != null && wLock.isHeld()) {
wLock.release();
wLock = null;
}
} catch (Exception e) {
Log.e(TAG, "Error releasing wake lock", e);
}

// Close the VPN interface
if (mInterface != null) {
try {
try {
if (mInterface != null) {
mInterface.close();
} catch (IOException e) {
Log.e(TAG, "Error closing the VPN interface", e);
}
} catch (IOException e) {
Log.e(TAG, "Error closing the VPN interface", e);
}

// Stop Tun2socks
Tun2socks.stop();
try {
Tun2socks.stop();
} catch (Exception e) {
Log.e(TAG, "Error stopping Tun2socks", e);
}

// Shutdown executor service
if (executorService instanceof ExecutorService) {
((ExecutorService) executorService).shutdownNow();
}

// Ensure all tasks are completed or terminated
try {
if (!((ExecutorService) executorService).awaitTermination(1, TimeUnit.SECONDS)) {
Log.e(TAG, "Executor service did not terminate in the specified time.");
ExecutorService service = (ExecutorService) executorService;
service.shutdown(); // Attempt to gracefully shutdown
try {
// Wait a certain amount of time for tasks to complete
if (!service.awaitTermination(500, TimeUnit.MILLISECONDS)) {
service.shutdownNow(); // Forcefully terminate if tasks are not completed
}
} catch (InterruptedException e) {
service.shutdownNow(); // Forcefully terminate if interrupted
Thread.currentThread().interrupt(); // Restore interrupted status
Log.e(TAG, "Executor service termination interrupted", e);
}
} catch (InterruptedException e) {
Log.e(TAG, "Executor service termination interrupted.", e);
}

Log.i(TAG, "VPN stopped successfully");
}



private void publishConnectionState(ConnectionState state) {
if (!connectionStateObservers.isEmpty()) {
for (String observerKey : connectionStateObservers.keySet())
Expand Down
14 changes: 13 additions & 1 deletion app/src/main/java/org/bepass/oblivion/SettingsActivity.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package org.bepass.oblivion;

import static org.bepass.oblivion.BatteryOptimizationKt.isBatteryOptimizationEnabled;
import static org.bepass.oblivion.BatteryOptimizationKt.showBatteryOptimizationDialog;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.util.Pair;
import android.view.View;
import android.widget.AdapterView;
Expand Down Expand Up @@ -38,6 +40,16 @@ protected void onCreate(Bundle savedInstanceState) {
context = this;
fileManager = FileManager.getInstance(this);

LinearLayout batteryOptLayout = findViewById(R.id.battery_optimization_layout);
LinearLayout batteryOptLine = findViewById(R.id.battery_opt_line);
if(isBatteryOptimizationEnabled(this)){
batteryOptLayout.setOnClickListener(view -> {
showBatteryOptimizationDialog(this);
});
}else{
batteryOptLayout.setVisibility(View.GONE);
batteryOptLine.setVisibility(View.GONE);
}
LinearLayout endpointLayout = findViewById(R.id.endpoint_layout);
LinearLayout portLayout = findViewById(R.id.port_layout);
LinearLayout splitTunnelLayout = findViewById(R.id.split_tunnel_layout);
Expand Down
47 changes: 47 additions & 0 deletions app/src/main/res/layout/activity_settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,53 @@
android:layout_height="wrap_content"
android:orientation="vertical">

<LinearLayout
android:id="@+id/battery_optimization_layout"
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="?android:selectableItemBackground"
android:gravity="center"
android:paddingHorizontal="16dp"
android:orientation="vertical">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/shabnam"
android:minWidth="100dp"
android:text="@string/batteryOpL"
android:textAlignment="viewEnd"
android:textColor="@color/black"
android:textSize="20sp" />
</LinearLayout>

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:fontFamily="@font/shabnam"
android:text="@string/batteryOpLText"
android:textColor="#9A9A9A"
android:textSize="16sp" />

</LinearLayout>
<LinearLayout
android:id="@+id/battery_opt_line"
android:layout_width="match_parent"
android:layout_height="10dp"
android:gravity="center"
android:orientation="vertical"
>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@android:color/darker_gray" />
</LinearLayout>
<LinearLayout
android:id="@+id/endpoint_layout"
android:layout_width="match_parent"
Expand Down
Loading

0 comments on commit 9fd7a40

Please sign in to comment.