7

I need to connect an android device to wifi programmatically without interacting with the user. Notably, this app is being purpose built and will not be on the play store or deployed publicly (I say this because what I need to do could have serious security concerns).

Here is how I am connecting the device programmatically

TextView textFeedback = findViewById(R.id.text);


ConnectivityManager.NetworkCallback wifiConnectionCallback = new ConnectivityManager.NetworkCallback(){
    @Override
    public void onAvailable(@NonNull Network network) {
        super.onAvailable(network);
        Log.e(logTAG, "wifi connected");
        textFeedback.setText("wifi connected");
    }

    @Override
    public void onLosing(@NonNull Network network, int maxMsToLive) {
        super.onLosing(network, maxMsToLive);
        Log.e(logTAG, "losing wifi connection");
        textFeedback.setText("losing wifi connection");
    }

    @Override
    public void onLost(@NonNull Network network) {
        super.onLost(network);
        Log.e(logTAG, "lost wifi connection");
        textFeedback.setText("lost wifi connection");
    }

    @Override
    public void onUnavailable() {
        super.onUnavailable();
        Log.e(logTAG, "user closed wifi connection");
        textFeedback.setText("user closed wifi connection");
    }
};


// instantiate connectivity manager
ConnectivityManager connectivityManager = (ConnectivityManager) this.getApplicationContext().getSystemService(this.CONNECTIVITY_SERVICE);

// connect to phl via wifi
Thread wifiConnectionThread = new Thread(new Runnable()
{
    @Override
    public void run()
    {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q)
        {
            NetworkSpecifier networkSpecifier  = new WifiNetworkSpecifier.Builder()
                        .setSsid(ssid)
                        .build();
            NetworkRequest networkRequest  = new NetworkRequest.Builder()
                        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                        .setNetworkSpecifier(networkSpecifier)
                        .build();
            connectivityManager.requestNetwork(networkRequest, wifiConnectionCallback);
        }
    }
});
wifiConnectionThread.start();

This works just fine with one exception. It prompts the user to ask them if they would like to connect to the network. This is problematic because I need the device to connect even if there isn't a user (hence the need to do this programmatically, there often will not be a user around). Is there a way to do this (preferably without rooting the device)? For example, is it possible to set this up so that a user is only prompted once and from that point on it is automatic?

2
  • 2
    Unfortunately Android is failing to understand their OS is not just used for google play apps available to the general public, were privacy is warranted. Same kind problem exists for Bluetooth were it requires user interaction for some things. Every OS upgrade comes with more restrictions. You could get whitelisted by the OS and become a system app, but that is probably unfeasible. Commented Jul 24, 2022 at 1:20
  • I added a full answer bellow but, if you could configure it only once and leave it, maybe you could trust the system's Wi-Fi settings interface and mark the "Connect automatically" option. It worked pretty fine for me before finding that library I mentioned in my answer. Commented Jul 24, 2022 at 2:55

2 Answers 2

1

Some years ago I encountered that exact same problem while developing a small gateway to collect data from our BLE sensors and push it to our backend over Wi-Fi.

At that time I used a small library publicly available in GitHub which is called WifiUtils. You can find that library following this link.

It was pretty simple to use and you can get a lot of information from the README.md at GitHub.

Enabling Wi-Fi:

WifiUtils.withContext(getApplicationContext()).enableWifi();

Scanning for Wi-Fi networks:

WifiUtils.withContext(getApplicationContext()).scanWifi(this::getScanResults).start();

private void getScanResults(@NonNull final List<ScanResult> results)
{
    if (results.isEmpty())
    {
        Log.i(TAG, "SCAN RESULTS IT'S EMPTY");
        return;
    }
    Log.i(TAG, "GOT SCAN RESULTS " + results);
}

And finally connecting to them:

WifiUtils.withContext(getApplicationContext())
    .connectWith("JohnDoeWiFi", "JohnDoePassword")
    .setTimeout(40000)
    .onConnectionResult(new ConnectionSuccessListener() {
        @Override
        public void success() {
            Toast.makeText(MainActivity.this, "SUCCESS!", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void failed(@NonNull ConnectionErrorCode errorCode) {
            Toast.makeText(MainActivity.this, "EPIC FAIL!" + errorCode.toString(), Toast.LENGTH_SHORT).show();
        }
    })
    .start();

As the library has all its code in GitHub, you might find much more information there.

Sign up to request clarification or add additional context in comments.

3 Comments

will it work fine for >android10 versions
Apparently not. My specific use case was with Android 8. And there are some issues reported on the library's repository about problems with Android 10. There are ways to solve the problem, but I don't believe that the library is still receiving updates.
Library is full of bugs and outdated. Do not recommend.
0

Sorry you can't do this...

The best solution for actual Android device connection is launch intent to open WiFi settings and observe the current WiFi network.

To enable WiFi YOU MUST need to ask to the user!!!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.