Android Helper class -> null pointer exception - java

i would like to ask:
I have in my AppHelper class following method which check availability of internet connection.
public boolean checkInternetConnection(Context ctx) {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
// test for connection
if (cm.getActiveNetworkInfo() != null
&& cm.getActiveNetworkInfo().isAvailable()
&& cm.getActiveNetworkInfo().isConnected()) {
return true;
} else {
Log.i(GlobalApplication.APP_LOG_NAMESPACE, "Internet Connection Not Present");
return false;
}
}
Im trying to get Boolean value by using:
// check internet connection and availability
Boolean isConnectionAvailable = appHelper.checkInternetConnection(getBaseContext());
But unfortunately i get always null pointer exception. Is it matter of passed application context? And how should i solve that issue?
Thanks for any advice.

I'm going to take a stab in the dark and say that AppHelper class is a seperate Activity that is never properly started with an intent.
If this is so, I would instead implement AppHelper as a Service instead of an Activity, as the method "checkInternetConnection" is better suited for this type of task.
Weather or not the service runs in its own process or not I suppose would depend on the particular problem at hand.

Related

Difference between DJI onProductChange and onProductConnect

Context
I'm building a Flutter Plugin above the DJK SDK. For that, I have to implement the communication with the aircraft on the native side, and I'm doing it with Java. I'm also doing it only for Android.
One of the methods of the API is boolean connectToAircraft(), which must return if the connection with the aircraft succeeded.
Expected/current behavior
After I call connectToAircraft() - which invokes the DJISDKManager.getInstance().startConnectionToProduct() method, I expected to be able to use anything related to aircraft immediately, but this doesn't happen. I have to wait a few seconds before I can retrieve data from the aircraft.
Some code
public class UavApi implements IUavApi, DJISDKManager.SDKManagerCallback {
...
private final CountDownLatch onConnectToUavFinishedSignal = new CountDownLatch(1);
...
public boolean connectToUav() throws InterruptedException {
Logger.v("connectToUav()");
DJISDKManager.getInstance().startConnectionToProduct();
synchronized (onConnectToUavFinishedSignal) {
onConnectToUavFinishedSignal.await();
}
return DJISDKManager.getInstance().getProduct() instanceof Aircraft;
}
...
#Override
public void onProductConnect(#Nullable final BaseProduct baseProduct) {
Logger.v(MessageFormat.format("onProductConnect(product: {0})", baseProduct));
if (baseProduct != null) {
handleProductConnected(baseProduct);
}
}
#Override
public void onProductChanged(#Nullable final BaseProduct baseProduct) {
Logger.v(MessageFormat.format("onProductChanged(product: {0})", baseProduct));
if (baseProduct != null) {
handleProductConnected(baseProduct);
}
}
...
private void handleProductConnected(#NonNull final BaseProduct baseProduct) {
Logger.d(MessageFormat.format("Is null? {0}", baseProduct == null ? "Yes" : "No"));
Logger.d(MessageFormat.format("Type: {0}", baseProduct.getClass().getSimpleName()));
onConnectToUavFinishedSignal.countDown();
}
...
}
Problem
The code above is what I tried to do, but it's not working and guess it's because I'm misunderstanding the use of the onProductChange() and onProductConnect() methods.
The DJISDKManager.getInstance().getProduct() is always returning null.
OBS: It's always returning null immediately after the onConnectToUavFinishedSignal.await() call finishes. After a few seconds, I get a valid instance of the aircraft.
Something I've also noticed is that sometimes the onProductChange() is called with some value that the log outputs as Unknwoun and None. What are those and how can I test for them? Like if (baseProduct == ???) doSomething()
Environment
Android 9
MSDK 4.13.1
Phantom 4 Pro
Difference
According to the SDK Docs onProductChanged is primarily used to detect when the connection status changes from only remote controller connected to a full connection between the aircraft and the SDK running on your device.
Keep in mind that when the aircraft is disconnected, this method will be called with an instance of an aircraft, but this instance will come with property isConnected as false. If you print the aircraft object to the console you will notice that if isConnected is true, it will print the aircraft name, otherwise, it will print "None".
As long for the onProductConnect, it will be called always after DJISDKManager.getInstance().registerApp() succeeded or after you manually connect to the aircraft with success using DJISDKManager.getInstance().startConnectionToProduct(). In my tests, even though the app registration succeeds, the method will return false, so you might need to check if the SDKManagerCallback::onRegister results in DJISDKError.REGISTRATION_SUCCESS.
Solution
You need to listen to component change events. Unfortunately just because the product is connected it does not mean that the individual components, such as the flight controller, camera etc are connected. You will need to implement onComponentChange and add a listener to detect when a component is connected. These don't always connect in the same order and may start to connect before or after the product is connected.
#Override
public void onComponentChange(
BaseProduct.ComponentKey componentKey,
BaseComponent oldBaseComponent,
BaseComponent newBaseComponent
) {
newBaseComponent.setComponentListener(isConnected -> {
// check if component connected and access data
if (isConnected) {
if(componentKey == ComponentKey.FLIGHT_CONTROLLER) {
// DJISDKManager.getInstance().getProduct() should no longer be null
DJISDKManager.getInstance().getProduct().getModel();
}
}
})
}

Difference between NetworkInfo.isConnected() and NetworkInfo.getDetailedState() == NetworkInfo.DetailedState.CONNECTED. What to use?

I want to know which method will be precise to check the network state for successfully getting connected.
So if we look at the source code of NetworkInfo.java class you will see that the network detailed states are declared as Enum,
public enum DetailedState {
/** Ready to start data connection setup. */
IDLE,
/** Searching for an available access point. */
SCANNING,
/** Currently setting up data connection. */
CONNECTING,
/** Network link established, performing authentication. */
AUTHENTICATING,
/** Awaiting response from DHCP server in order to assign IP address information. */
OBTAINING_IPADDR,
/** IP traffic should be available. */
CONNECTED,
/** IP traffic is suspended */
SUSPENDED,
/** Currently tearing down data connection. */
DISCONNECTING,
/** IP traffic not available. */
DISCONNECTED,
/** Attempt to connect failed. */
FAILED,
/** Access to this network is blocked. */
BLOCKED,
/** Link has poor connectivity. */
VERIFYING_POOR_LINK,
/** Checking if network is a captive portal */
CAPTIVE_PORTAL_CHECK
}
But if you read the comments for these DetailedState it says below about these
The fine-grained state of a network connection. This level of detail
is probably of interest to few applications. Most should use
android.net.NetworkInfo.State State instead.
The isConnected() method inside the NetworkInfo.java class is checking against the State.CONNECTED State only,
public boolean isConnected() {
synchronized (this) {
return mState == State.CONNECTED;
}
}
Essentially if you use
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null &&
activeNetwork.isConnectedOrConnecting();
that should suffice as above code will query the active network and determine if it has Internet connectivity. Once you know it, you can proceed with accessing internet resource.
Java:
ConnectivityManager manager =
(ConnectivityManager)getApplication.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info=manager.getActiveNetworkInfo()
if(info!=null && info.isConnected()){
// you are online for sure.
}
Kotlin:
val manager = application.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val info = manager.getActiveNetworkInfo()
if (info != null && info.isConnected()) {
// you are online for sure.
}
I use Above code in my development to be sure that my device is connected to internet.
Read this thread to know the difference and how state can be changed
from source code
public boolean isConnected() {
synchronized (this) {
return mState == State.CONNECTED;
}
}
so it's the same
From here https://developer.android.com/training/monitoring-device-state/connectivity-monitoring#java
ConnectivityManager cm =
(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null &&
activeNetwork.isConnected();
you will need to add this to your manifest
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

How to handle com.android.volley.NoConnectionError: java.net.UnknownHostException

I am using Volley for webcalls in my application and everything is working fine and smooth except one state in which somehow my device is not getting Network Connection but checking connection via code is returning true using below code.
public static boolean isNetworkAvailable() {
ConnectivityManager connectivityManager = SessionApplication.getConnectivityManager();
if(connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState() == NetworkInfo.State.CONNECTED ||
connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState() == NetworkInfo.State.CONNECTED) {
//we are connected to a network
return true;
}
else
return false;
}
Instead of returning network state false using above code My volley web calls returning me this exception "handle com.android.volley.NoConnectionError: java.net.UnknownHostException".
I checked my internet connection by opening browser in my device and found it is also not working. So i am okay with application behavior but still i need to handle such condition because this is not user friendly user should be prompted a dialog that "Check Your Internet Connection!".
This should be a common issues in Android could any body please help me to give me best approach to handle such cases. Thanks in advance.
Network state is :
This exception indicates the problem in connectivity. In fact you can show some dialog about the connectivity. Overriding the onErrorResponse(VolleyError error) you can do like this -
public void onErrorResponse(VolleyError error) {
Log.d(TAG, error.toString());
if (error instanceof NoConnectionError)
new AlertDialog.Builder(this).setMessage(
"Unable to connect to the server! Please ensure your internet is working!").show();
}
Try this method might help
public boolean isConnectedToInternet(){
connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivityManager != null){
NetworkInfo[] info = connectivityManager.getAllNetworkInfo();
if (info != null){
for (int i = 0; i < info.length; i++){
if (info[i].getState() == NetworkInfo.State.CONNECTED){
return true;
}
}
}
}
return false;
}

Google Analyrics track user if connected to the Internet

I just started learning Google Analytics for Android (v4). I am trying to measure how many users use my application with WiFi turned on when an activity is created. I am not sure if I am doing this correctly but I added a custom dimension for "Users are Connected" and used this code:
builder.setCustomDimension(1, isNetworkConnected() ? "True" : "False");
tracker.send(builder.setNewSession().build());
I look at the Google Analytics webpage and cannot see any information about this custom dimension on the "Realtime" navigation. I can see that the user count increased but no information about whether users are connected or not.
Thanks in advance.
Android has to check with isNetworkConnected. If the condition provided, you can run your request in this. This will assume internet is available and connected.
Implement this way:
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
if(isNetworkConnected(this)){
// start a service related to internet or
// put your tracker to send data
tracker.send(builder.setNewSession().build()); // or any other methot you use to track app
}
}
public static boolean isNetworkConnected(Context context) {
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
return (cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isAvailable() && cm.getActiveNetworkInfo().isConnected());
}
}

Recall a function

I'm performing a check of internet access in a program. I'd like to do a function to that cause this checking need to often happens... But my original function have to return while it because the screen need to refresh. This is what I have:
public void isOnline(Runnable Rcallback, Ccallback) {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
boolean checkState = cm.getActiveNetworkInfo().isConnectedOrConnecting();
if(checkState) {
isOnline = true;
if(Rcallback != null) Rcallback.run();
if(Ccallback != null) set;}
else {
isOnline = false;
Toast.makeText(gMain.this, R.string.nointernet, Toast.LENGTH_LONG).show();
Handler reTry = new Handler();
reTry.postDelayed(new Runnable() {
#Override
public void run() {
isOnline(callback) ;
}
},3000);
}
}
My really problem is in Ccallback that it's a function to call back when the program turns online. I don't know how to declare a function as a "variable". Any ideas?
You should setup a listener using the Observer Pattern. This will allow you to tell anyone marked as a listener (likely your UI) that you have done something. In this case, something is connected.
One thing to keep in mind while doing this is to ensure that while doing things on the UI, you are on the Event Thread.

Categories

Resources