Recently i discovered that the implementation to connect to a Wifi in Android is deprecated for Android 10 or above and I'm trying to fix my application using WifiNetworkSpecifier. But I notice the WifiNetworkSpecifier do not save the network connection and just stay connected while the application is running and when it's closed, the wifi is disconnected and do not save the password.
I'm using this code:
private void connectByWifiNetworkSpecifier(String wifiSsid, String pass) {
Log.d(TAG, "connectByWifiNetworkSpecifier: wifi=" + wifiSsid + ", pass=" + pass);
connectivityManager = (ConnectivityManager) context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
WifiNetworkSpecifier.Builder specifierBuilder = new WifiNetworkSpecifier.Builder()
.setSsid(wifiSsid)
.setWpa2Passphrase(pass);
NetworkRequest request = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.setNetworkSpecifier(specifierBuilder.build())
.build();
networkCallback = new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(Network network) {
super.onAvailable(network);
Log.d(TAG, "onAvailable: network=" + network);
// do success processing here..
connectivityManager.bindProcessToNetwork(network);
}
#Override
public void onUnavailable() {
super.onUnavailable();
Log.d(TAG, "onUnavailable: ");
// do failure processing here..
}
};
connectivityManager.requestNetwork(request, networkCallback);
}
Have it any way to save the connection "permanently" (without me having to connect all the time and always put the password) using WifiNetworkSpecifier or another API?
.
Related
Let me quickly describe my setup and goal. I have a android tablet display running Android version 7.1.2
I have a motor controller that is hooked up to the Android tablet via ethernet. In my Android app that controls the motor controller, I use Wifi to communicate with some servers that provide/store data. Currently, I can use an Android simulator (in Android Studio) that allows me to communicate with the motor controller while also using the wifi for calls to the server. When I run the app on the Android tablet itself, I can only have Wifi OR Ethernet active at one time.
According to this post this is a hard limitation in Android itself. It also details some possible fixes, but its quite old and to be honest I do not have any experience in the required steps described by their vague instructions.
Can anyone provide a more up-to-date solution to this problem, preferably one that is a little more detailed for newbies like me? Even just a pointer to learning how to do the necessary steps for fixing this would be great, I've been stuck on this for awhile! Thanks for any help!
EDIT: Here's some relevant info in regards to AlwaysLearning's answer...
The class I use to manage reading from Modbus
public class ModbusRead {
private static final String TAG = "MODBUS READ";
ModbusClient mClientReadAll;
public ModbusRead()
{
// IP = "192.168.124.2";
// port = 502;
mClientReadAll = new ModbusClient(Modbus.IP, Integer.valueOf(Modbus.port));
mClientReadAll.setUnitIdentifier((byte)255);
}
public Runnable readAll()
{
return () -> {
ReadAllFromModbus mReadAll = new ReadAllFromModbus();
mReadAll.execute();
};
}
public class ReadAllFromModbus extends AsyncTask<String, Void, String> {
private final String TAG = "READ ALL FROM MODBUS";
#Override
protected String doInBackground(String... params) {
try
{
mClientReadAll.Connect();
// get all registers
int[] registerBlock = mClientReadAll.ReadHoldingRegisters(Constants.RegisterRead.HR_MODE.getRegister()- 1, 16);
int[] wideRegisters = new int[] {
Modbus.convertWideRegister(mClientReadAll.ReadHoldingRegisters(Constants.RegisterRead.HR_ACTUAL_POSITION.getRegister() - 1, 2)),
Modbus.convertWideRegister(mClientReadAll.ReadHoldingRegisters(Constants.RegisterRead.HR_TARGET_POSITION.getRegister() - 1, 2)),
Modbus.convertWideRegister(mClientReadAll.ReadHoldingRegisters(Constants.RegisterRead.HR_ROM_DELTA.getRegister() - 1, 2)),
Modbus.convertWideRegister(mClientReadAll.ReadHoldingRegisters(Constants.RegisterRead.HR_REWIND_ZERO.getRegister() - 1, 2))
};
int[] tensionRegister = mClientReadAll.ReadHoldingRegisters(Constants.RegisterRead.HR_ACTUAL_TENSION.getRegister() - 1, 1);
Modbus.updateAllRegisters(registerBlock, wideRegisters, tensionRegister);
}
catch (Exception e)
{
Log.i(TAG, "ERROR IN GETTING ALL REGISTERS LOOP: " + e.getMessage());
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
try
{
mClientReadAll.Disconnect();
}
catch(Exception e)
{
Log.i(TAG, "ERROR IN DISCONNECTING");
}
}
}
}
The relevant part of my Dashboard class that would handle starting the thread that does all the modbus reading
How would I go about forcing the ModbusRead class to use the Ethernet here?
ModbusRead modbusRead = new ModbusRead();
final ConnectivityManager connectivityManager = (ConnectivityManager) this.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkRequest requestEthernet = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
.build();
final ConnectivityManager.NetworkCallback cbEthernet = new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(Network network) {
// connectivityManager.bindProcessToNetwork(network);
try
{
// Modbus.IP = "192.168.124.2"
// Modbus.port = 502
Log.i(TAG, "TRYING TO BIND SOCKET...");
InetAddress address = InetAddress.getByName(Modbus.IP);
Log.i(TAG, "ADDRESS: " + address.toString());
Socket socket = new Socket(address, Modbus.port);
Log.i(TAG, "SOCKET CREATED..." + socket.getInetAddress());
network.bindSocket(socket);
Log.i(TAG, "BOUND ETHERNET");
}
catch (Exception e)
{
e.printStackTrace();
Log.i(TAG, "EXCEPTION: " + e.getMessage());
}
}
};
connectivityManager.requestNetwork(requestEthernet, cbEthernet);
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
executorService.scheduleAtFixedRate(modbusRead.readAll(), 2000, 250, TimeUnit.MILLISECONDS);
I have been working on an android application.For one of the feature, I need the active network information(i.e. whether it's connected with Wi-Fi or mobile data). I got this piece of code from the internet.
NetworkInfo activeNetworkInfo = context.getSystemService(ConnectivityManager.class).getActiveNetworkInfo();
But this API is deprecated and I don't want to use any deprecated API.
After some more googling, I found that we should use ConnectivityManager.NetworkCallback instead. But I am not able to get an example of it. How can I use this?. Please help me if anyone having an idea about using ConnectivityManager.NetworkCallback
Check out this function in Kotlin
fun networkConnection(): Boolean {
var networkAvailable = false
val connectivityManager: ConnectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val network: Network = connectivityManager.activeNetwork!!
val networkCapabilities: NetworkCapabilities = connectivityManager.getNetworkCapabilities(network)!!
if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
networkAvailable = true
} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
networkAvailable = true
} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
networkAvailable = true
}
return networkAvailable
}
try the following code:
private void registerNetworkCallback(Context context) {
final ConnectivityManager manager =
(ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE);
manager.registerNetworkCallback(
new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
.build(),
new NetworkCallback() {
#Override
public void onAvailable(Network network) {
/** here to get the available info
this ternary operation is not quite true, because non-metered
doesn't yet mean, that it's wifi
nevertheless, for simplicity let's assume that's true
*/
Log.i("vvv", "connected to " + (manager.isActiveNetworkMetered() ? "LTE" : "WIFI"));
}
#Override
public void onCapabilitiesChanged(Network network,
NetworkCapabilities networkCapabilities){
/**here to get the change network info
Value is TRANSPORT_CELLULAR, TRANSPORT_WIFI,
TRANSPORT_BLUETOOTH, TRANSPORT_ETHERNET, TRANSPORT_VPN
*/
if(networkCapabilities.hasTransport("type")){
}
}
});
}
connectivityManager = (ConnectivityManager)
context.getSystemService(ConnectivityManager.class);
#RequiresApi(api = Build.VERSION_CODES.M)
private void getActiveNet() {
Network currentNetwork = connectivityManager.getActiveNetwork();
}
Note that "active network" is synonymous in android with "default network".
ConnectivityManager#getActiveNetworkInfo()
Returns details about the currently active default data network...
ConnectivityManager#registerDefaultNetworkCallback(NetworkCallback)
Registers to receive notifications about changes in the application's
default network...
Therefore using ConnectivityManager#registerDefaultNetworkCallback(NetworkCallback) you can listen for default (aka "active") network changes. Unfortunately, this only returns the Network object which does not have information regarding transport (Wi-Fi vs Cellular) in which case you'll need to make an additional call to ConnectivityManager#getNetworkCapabilities(Network) to get that info.
Here is an example:
final ConnectivityManager connectivityManager = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkCallback networkCallback = new NetworkCallback() {
#Override
void onAvailable(Network network) {
// Triggers when a default network is available.
NetworkCapabilities nc = connectivityManager.getNetworkCapabilities(network);
boolean isWifi = nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
boolean isCellular = nc.hasTransport(NetworkCapabilities. TRANSPORT_CELLULAR);
}
};
connectivityManager.registerDefaultNetworkCallback(networkCallback);
I am running JavaFX jar file on Windows system and my code includes connection to Firebase. I make the connection to the firebase through the following code:
public void start(Stage primaryStage) throws Exception {
System.out.println("Connecting FireBase...");
// Initialize the app with a service account, granting admin privileges
FirebaseOptions options = null;
try {
options = new FirebaseOptions.Builder()
.setCredential(FirebaseCredentials.fromCertificate(getServiceAccount(<path-to-json-file>)))
.setDatabaseUrl("https://<firebase-name>.firebaseio.com")
.build();
} catch (IOException e) {
e.printStackTrace();
}
FirebaseApp.initializeApp(options);
System.out.println("Connecting to FireBase and initializing...");
// check if the connection succedded
DatabaseReference connectedRef =
FirebaseDatabase.getInstance().getReference(".info/connected");
connectedRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
boolean connected = snapshot.getValue(Boolean.class);
if (connected) {
System.out.println("Connected to firebase!");
} else {
System.out.println("Not connected to firebase...");
}
}
#Override
public void onCancelled(DatabaseError error) {
System.err.println("Listener was cancelled");
}
});
System.out.println("Get a reference to the firebase db...");
// Get a reference to our posts
final FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("server/<path>");
// rest of the code ...
}
Eventually, I get the following output:
Connected to firebase!
Now I have to run the same jar file on Raspberry Pi system. When I execute the jar on Raspberry Pi, the console outputs the following:
Not connected to firebase...
and there is no exceptions.
Is there any way to check what is the reason of no connection to firebase from Raspberry Pi system?
How to resolve this problem?
My android app uses google endpoints as a scalable backend solution. However, I am having trouble calling it from the android client.
I call an async task class from an activity and in the async task class call the endpoints method. In this case the default sayHi() method is called and the message should be displayed in a toast using the onPostExecute(String result) method.
However when I run the app module in the emulator, this error appears in the toast:
failed to connect to /10.0.2.2 (port 8080) after 20000ms: isConnected failed: ECONNREFUSED (Connection refused)
Here is the code that calls the async task from the activity:
Profile profile = new Profile(firstName, lastName, birthday);
new EndpointTask(). new SaveProfileTask(profile, this).execute();
Here is the async task class:
public class EndpointTask {
public class SaveProfileTask extends AsyncTask<Void, Void, String> {
private final String LOG_TAG = SaveProfileTask.class.getSimpleName();
private MyApi mApi;
private Profile mProfile;
private Context mContext;
public SaveProfileTask(Profile profile, Context context) {
mProfile = profile;
mContext = context;
}
#Override
protected String doInBackground(Void... params) {
if (mApi == null) {
MyApi.Builder builder = new MyApi.Builder(AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(), null)
// options for running against local devappserver
// - 10.0.2.2 is localhost's IP address in Android emulator
// - turn off compression when running against local devappserver
.setRootUrl("http://10.0.2.2:8080/_ah/api/")
.setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
#Override
public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
abstractGoogleClientRequest.setDisableGZipContent(true);
}
});
mApi = builder.build();
}
try {
return mApi.sayHi(mProfile.getFirstName()).execute().getData();
} catch (IOException e) {
return e.getMessage();
}
}
#Override
protected void onPostExecute(String result) {
Toast.makeText(mContext, result, Toast.LENGTH_LONG).show();
Log.d(LOG_TAG, "ERROR: " + result);
}
}
}
Most of this is taken from the github repo here. Which is part of the official android documentation for hooking up the client with the backend for google app engine.
Why is this error occurring and how can it be fixed?
Thanks guys, happy coding.
I am having an issue when try to connect to wireless network.
My code works ok I sucessfully connect to the network whit the problems described below.
I have a listview whit the wifi scan results.
When I click the first time my receiver is not getting the "completed" state.
After clicking the second time , and , without chosing any network it get connected and my code inside the "complete" is executed.
The code below is called from another class that thre reason why it is static
Coonect Code:
public static boolean connect(String ssid,String password)
{
String networkSSID = ssid;
String networkPass = password;
WifiConfiguration conf = new WifiConfiguration();
conf.SSID = "\"" + networkSSID + "\"";
conf.preSharedKey = "\""+ networkPass +"\"";
//WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
int netid=mainWifi.addNetwork(conf);
mainWifi.disconnect();
mainWifi.enableNetwork(netid, true);
//mainWifi.reconnect(); <-- exact the same issue discommenting this line
return true;
}
On the class were the connect is been called I have registered BradcastReceiver as follow:
public void onClick(View v)
{
mainWifi = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifiinfo = mainWifi.getConnectionInfo();
AuthWifi authWifi = new AuthWifi();
IntentFilter mIntentFilter = new IntentFilter();
mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
getApplicationContext().registerReceiver(authWifi, mIntentFilter);
ClientManager.scan(CameraActivity.this, mainWifi);
}
my broadcast receiver
public class AuthWifi extends BroadcastReceiver {
#Override
public void onReceive(Context c, Intent intent) {
String action = intent.getAction();
if (action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)) {
SupplicantState supl_state = ((SupplicantState) intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE));
switch (supl_state) {
case COMPLETED:
/////////////IF I AM CONNECTED THE WIFI SSID I CHOSE FROM A LISTVIEW THEN ---->
if(wifiinfo != null & wifiinfo.getSSID()!=null & ClientManager.getSSID() !=null& !conectado ) {
if (wifiinfo.getSSID().contains(ClientManager.getSSID().trim())) ///I know here is better .equals() /// I have contain for my own reasons
conectado = true;
/*HERE I DO SOME THINGS WHEN CONNECTED (I CALL A RUNNABLE TO MAKE A SERVER SOCKET)*/
}
}
break;
case DISCONNECTED:
Log.i("SupplicantState", "Disconnected");
conectado = false;
if (ClientStartReceive.isStopped)
{
ClientStartReceive.stop();
}
break;
default:
Log.i("SupplicantState", "Unknown");
break;
}
int supl_error = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -1);
if (supl_error == WifiManager.ERROR_AUTHENTICATING) {
/////HERE I MANAGE AUTHENTICATION ERROR
}
}
}
}
Hope someone is able to help :( if you need more code to troubleshoot please let me know.
If you have some reference to help me even if i need to rebuild the code is accepted also.. My goal is be able to connect to a network ,show for authentication errors and execute some code on connection susscess.
Sorry for my english I think you have gessed I am not native.
Regards
As doc indicate that “COMPLETED“ use as follow:
This state indicates that the supplicant has completed its processing for the association phase and that data connection is fully configured. Note, however, that there may not be any IP address associated with the connection yet.
You should not rely this state to ensure your connection is completed. Instead, you can register an BroadcastReceiver listener for network status change.