2

I't trying to implement a local VpnService to have my app do some tasks, but I'm a little confused as to how to stop it one it started. The VpnService class and client activity are based on this repo: https://github.com/hexene/LocalVPN

The caller activity is basically this:

public class MainActivity extends AppCompatActivity {

private static final int VPN_REQUEST_CODE = 0x0F;
private boolean waitingForVPNStart;
private BroadcastReceiver vpnStateReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (LocalVPNService.BROADCAST_VPN_STATE.equals(intent.getAction()))
            if (intent.getBooleanExtra("running", false))
                waitingForVPNStart = false;
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    final Button vpnButton = (Button)findViewById(R.id.vpn);
    vpnButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            startVPN();
        }
    });

    final Button vpnStopButton = (Button)findViewById(R.id.stopVpnButton);
    vpnStopButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            stopVPN();
        }
    });

    waitingForVPNStart = false;
    LocalBroadcastManager.getInstance(this).registerReceiver(vpnStateReceiver,
            new IntentFilter(LocalVPNService.BROADCAST_VPN_STATE));
}

private void startVPN() {
    Intent vpnIntent = VpnService.prepare(this);
    if (vpnIntent != null)
        startActivityForResult(vpnIntent, VPN_REQUEST_CODE); //Prepare to establish a VPN connection. This method returns null if the VPN application is already prepared or if the user has previously consented to the VPN application. Otherwise, it returns an Intent to a system activity.
    else
        onActivityResult(VPN_REQUEST_CODE, RESULT_OK, null);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == VPN_REQUEST_CODE && resultCode == RESULT_OK) {
        waitingForVPNStart = true;
        startService(new Intent(this, LocalVPNService.class));
        enableButton(false);
    }
}

What confuses me is: how would I call the service's onDestroy() method or something similar if I don't keep an instance if it in my main activity?

I looked at this answer and this and seen implementations of stopService, but I'm not sure how to handle the Intent, because it's not only used to call startService() but also involved in calling VpnService.prepare().

Edit: I tried stopService(new Intent(this, LocalVPNService.class)); but it doesn't stop it. I tried stopService(vpnIntent); and IT WORKS, but makes my app crash/close.

DmitryB
  • 119
  • 1
  • 2
  • 13
  • Check this answer https://stackoverflow.com/questions/5555765/stop-service-in-android – KMI Mar 18 '18 at 14:58
  • Thank you! But stopping it with stopService() doesn't stop my service. The little vpn key icon stays there and it keeps working. That is why I suspect that it has something to do with the fact that it's a vpn service and thus is called also with prepare(). – DmitryB Mar 18 '18 at 15:04
  • How you stop service? – KMI Mar 18 '18 at 15:13
  • Yeah, that is exactly my question. I want to stop it from the activity. I tried stopService(new Intent(this, LocalVPNService.class)); but it doesn't stop it. I tried stopService(vpnIntent); and IT WORKS, but makes my app crash/close. – DmitryB Mar 18 '18 at 15:14
  • You can use localbroadcast – KMI Mar 18 '18 at 15:15
  • Can you specify what you mean? – DmitryB Mar 18 '18 at 15:16
  • check my answer – KMI Mar 18 '18 at 15:29

1 Answers1

6

In your LocalVPNService class create a new broadcast:

private BroadcastReceiver stopBr = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
    if ("stop_kill".equals(intent.getAction())) {
         stopself();
    }
}
};

and in the onCreate method add this:

    LocalBroadcastManager lbm = 
    LocalBroadcastManager.getInstance(this);
    lbm.registerReceiver(stopBr, new IntentFilter("stop_kill"));

in your activity:

Intent intent = new Intent("stop_kill");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
Christian Garbin
  • 2,512
  • 1
  • 23
  • 31
KMI
  • 258
  • 1
  • 10
  • Ok, this works to stop the service. But then if I want to start it again (by pressing the first button again) it doesn't start. Testing, it seems like the LocalVPNService's onCreate() method is not even called anymore (no log in LogCat). – DmitryB Mar 18 '18 at 15:33
  • Apparently it wouldn't start back up because I killed it calling it's own onDestroy() instead of it's stopSelf() method. Changed it and now everything works fine. Anyway, my question was "how to stop" and your answer actually worked for stopping it, so thank you for your help! – DmitryB Mar 18 '18 at 16:25