Skip to content

Commit

Permalink
Implement quick settings toggle button
Browse files Browse the repository at this point in the history
  • Loading branch information
Amillinium committed Feb 12, 2024
1 parent 640ea18 commit a9eed77
Show file tree
Hide file tree
Showing 12 changed files with 464 additions and 146 deletions.
17 changes: 16 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
<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" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
Expand Down Expand Up @@ -41,6 +42,20 @@
android:value="true" />
</service>

<service
android:name=".QuickStartService"
android:exported="true"
android:label="Oblivion"
android:icon="@drawable/vpn_off"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<meta-data android:name="android.service.quicksettings.TOGGLEABLE_TILE"
android:value="true" />
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>

</service>

<activity
android:name="org.bepass.oblivion.MainActivity"
android:exported="true"
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/java/org/bepass/oblivion/ConnectionState.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.bepass.oblivion;

public enum ConnectionState {
CONNECTING,
CONNECTED,
DISCONNECTED
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.bepass.oblivion;

public interface ConnectionStateChangeListener {
void onChange(ConnectionState state);
}
7 changes: 7 additions & 0 deletions app/src/main/java/org/bepass/oblivion/FileManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,16 @@ public String getString(String name) {
return sharedPreferences.getString(name, "");
}

public String getString(String name, String defaultValue) {
return sharedPreferences.getString(name, defaultValue);
}

public boolean getBoolean(String name) {
return sharedPreferences.getBoolean(name, false);
}
public boolean getBoolean(String name, boolean defaultValue) {
return sharedPreferences.getBoolean(name, defaultValue);
}

public int getInt(String name) {
return sharedPreferences.getInt(name, 0);
Expand Down
153 changes: 46 additions & 107 deletions app/src/main/java/org/bepass/oblivion/MainActivity.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
package org.bepass.oblivion;

import android.Manifest;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
Expand All @@ -24,37 +20,33 @@

import com.suke.widget.SwitchButton;

import java.io.IOException;
import java.net.ServerSocket;

import tun2socks.StartOptions;

public class MainActivity extends AppCompatActivity {

private static final String ConnectionStateObserverKey = "mainActivity";
private ActivityResultLauncher<String> pushNotificationPermissionLauncher;
private ActivityResultLauncher<Intent> vpnPermissionLauncher;

private Messenger serviceMessenger;
private boolean isBound;

// 1 Wait For Connect
// 2 Connecting
// 3 Connected
int connectionState = 1;

// Views
ImageView infoIcon, bugIcon, settingsIcon;
SwitchButton switchButton;
TouchAwareSwitch switchButton;
TextView stateText;

FileManager fileManager;

Boolean canShowNotification = false;

private ConnectionState lastKnownConnectionState = ConnectionState.DISCONNECTED;

private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
serviceMessenger = new Messenger(service);
isBound = true;
observeConnectionStatus();
}

@Override
Expand All @@ -64,25 +56,23 @@ public void onServiceDisconnected(ComponentName arg0) {
}
};


private SwitchButton.OnCheckedChangeListener createSwitchCheckedChangeListener() {
return (view, isChecked) -> {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && !canShowNotification) {
pushNotificationPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS);
return;
}
if (connectionState == 1 && isChecked) {
// From NoAction to Connecting
stateText.setText("درحال اتصال ...");
connectionState = 2;

if (lastKnownConnectionState == ConnectionState.DISCONNECTED && isChecked) {
// From NoAction to Connecting
Intent vpnIntent = OblivionVpnService.prepare(this);
if (vpnIntent != null) {
vpnPermissionLauncher.launch(vpnIntent);
} else {
startVpnService();
}
} else if(connectionState < 4 && connectionState > 1) {
disconnected();
} else if(lastKnownConnectionState == ConnectionState.CONNECTED || lastKnownConnectionState == ConnectionState.CONNECTING) {
stopVpnService();
}
};
Expand All @@ -92,39 +82,39 @@ private SwitchButton.OnCheckedChangeListener createSwitchCheckedChangeListener()
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

init();
firstValueInit();
if(isMyServiceRunning()) {
connected();
}
switchButton.setOnCheckedChangeListener(createSwitchCheckedChangeListener());
}

private void sendMessageToService() {


private void observeConnectionStatus() {
if (!isBound) return;
try {
// Create a message for the service
Message msg = Message.obtain(null, OblivionVpnService.MSG_PERFORM_TASK);

// Create a Messenger for the reply from the service
Messenger replyMessenger = new Messenger(new Handler(message -> {
if (message.what == OblivionVpnService.MSG_TASK_COMPLETED) {
// Handle task completion
Toast.makeText(getApplicationContext(), "متصل شدید!", Toast.LENGTH_LONG).show();
connected();
} else {
disconnected();
stopVpnService();
}
return true;
}));
msg.replyTo = replyMessenger;

// Send the message
serviceMessenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
OblivionVpnService.registerConnectionStateObserver(ConnectionStateObserverKey, serviceMessenger, new ConnectionStateChangeListener() {
@Override
public void onChange(ConnectionState state) {
lastKnownConnectionState = state;
updateUi();
}
});
}

private void unsubscribeConnectionStatus() {
if (!isBound) return;
OblivionVpnService.unregisterConnectionStateObserver(ConnectionStateObserverKey, serviceMessenger);
}
private void updateUi() {
switch(lastKnownConnectionState) {
case DISCONNECTED:
disconnected();
break;
case CONNECTING:
connecting();
break;
case CONNECTED:
connected();
break;
}
}

Expand All @@ -140,26 +130,25 @@ protected void onStop() {
super.onStop();
// Unbind from the service
if (isBound) {
unsubscribeConnectionStatus();
unbindService(connection);
isBound = false;
}
}

private void connected() {
switchButton.setOnCheckedChangeListener(null);
stateText.setText("اتصال برقرار شد");
connectionState = 3;
switchButton.setChecked(true);
switchButton.setOnCheckedChangeListener(createSwitchCheckedChangeListener());
switchButton.setChecked(true, false);
}

private void connecting() {
stateText.setText("در حال اتصال...");
switchButton.setChecked(true, false);
}

private void disconnected() {
switchButton.setOnCheckedChangeListener(null);
// From Connecting to Disconnecting
stateText.setText("متصل نیستید");
connectionState = 1;
switchButton.setChecked(false);
switchButton.setOnCheckedChangeListener(createSwitchCheckedChangeListener());
switchButton.setChecked(false, false);
}

private void firstValueInit() {
Expand Down Expand Up @@ -192,69 +181,19 @@ private void initPermissionLauncher() {
if (result.getResultCode() == RESULT_OK) {
startVpnService();
} else {
stopVpnService();
Toast.makeText(this, "Really!?", Toast.LENGTH_LONG).show();
}
}
);
}

private boolean isMyServiceRunning() {
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
if (manager != null) {
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (OblivionVpnService.class.getName().equals(service.service.getClassName())) {
return true;
}
}
}
return false;
}

private static int findFreePort() {
ServerSocket socket = null;
try {
socket = new ServerSocket(0);
socket.setReuseAddress(true);
int port = socket.getLocalPort();
try {
socket.close();
} catch (IOException e) {
// Ignore IOException on close()
}
return port;
} catch (IOException e) {
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
}
}
}
throw new IllegalStateException("Could not find a free TCP/IP port to start embedded Jetty HTTP Server on");
}

private String getBindAddress() {
String port = fileManager.getString("USERSETTING_port");
boolean enableLan = fileManager.getBoolean("USERSETTING_lan");
if(OblivionVpnService.isLocalPortInUse("127.0.0.1:" + port).equals("true")) {
port = findFreePort()+"";
}
String Bind = "";
Bind += "127.0.0.1:" + port;
if(enableLan) {
Bind = "0.0.0.0:" + port;
}
return Bind;
}

private void startVpnService() {
//Toast.makeText(getApplicationContext(), calculateArgs(), Toast.LENGTH_LONG).show();
Intent intent = new Intent(this, OblivionVpnService.class);
intent.putExtra("bindAddress", getBindAddress());
intent.setAction(OblivionVpnService.FLAG_VPN_START);
ContextCompat.startForegroundService(this, intent);
sendMessageToService();
}

private void stopVpnService() {
Expand Down
Loading

0 comments on commit a9eed77

Please sign in to comment.