calling function of activity from fragment class gives NPE - java

I have an activity whose parent class is fragment let we call it fragment A, I have another fragment B from where I want to call the function of the activity related to fragment A, How to call this function? I have tried this:
Respond and SResponses are the activities whose function am calling.and these function are only called when these activites are in active state.
if (Respond.getActivityStatus() == true)
{
if (Respond.getrthreadid().compareTo(threadid) == 0)
{
//Respond res = new Respond();
//res.notiffy(message);
((Respond)getActivity()).notiffy(message);
}
}
if (SResponses.getActivityStatus() == true)
{
if (SResponses.getsrthreadid().compareTo(threadid) == 0)
{
//SResponses sres = new SResponses();
// sres.notiffy(message);
((SResponses)getActivity()).notiffy(message);
}
}
}
} catch (RuntimeException e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
} catch (RuntimeException e) {
// TODO: handle exception
e.printStackTrace();
}
But its giving me Null pointer exception. Please help.

Your fragment is not always attached to an activity, so at times, getActivity() may return null.
Read about this Coordinating With The Activity Lifecycle.

If you want fragment A to communicate with fragment B, you should define an interface inside fragment A (which the parent activity has to implement) to send data from fragment A to parent activity and from the parent activity send that data to fragment B.
Check this link.

Related

Is there an alternative way for nested try and catch?

In the below posted code, I am tring to code a utility method and I want to check if an object is null or not and a string is null and not empty.
so, I coded the way shown below with throwing some exception, but I think the code could have been coded in a better way because the way I coded it has nested
try and catch blocks.and i do not think it is a good style
please guide me to better code the belwo method
code:
public static boolean isFragmentShowing(Activity activity, String tag) throws Exception {
try {
if (activity != null) {
FragmentManager fragmentManager = FragmentUtils.getFragmentManagerInstance(activity);
try {
if (tag != null && !tag.equals("")) {
Fragment fragment = fragmentManager.findFragmentByTag(tag);
return (fragment != null && fragment.isVisible())? true : false;
} else {
throw new NullPointerException("isFragmentShowing: fragment tag passed is null or empty");
}
} catch (NullPointerException e) {
Log.e(TAG, "Error: " + e.getMessage().toString());
System.exit(1);
return false;
}
} else {
throw new NullPointerException("isFragmentShowing: context reference is null");
}
} catch (NullPointerException e) {
Log.e(TAG, "Error: " + e.getMessage().toString());
System.exit(1);
return false;
}
}
There are two part of your application. One is request validation and another one is application logic. Separate request validation and application logic. It will be easier to read and maintains. Here is my try in bellow
public static boolean isFragmentShowing(Activity activity, String tag) throws Exception {
//validate request
if(activity == null) {
// throw exception or return value
}
if (tag == null && tag.equals("")){
// throw exception or return value
}
// rest of the part
FragmentManager fragmentManager = FragmentUtils.getFragmentManagerInstance(activity);
Fragment fragment = fragmentManager.findFragmentByTag(tag);
return (fragment != null && fragment.isVisible())? true : false;
}
If all you're going to do with the exception is
Log.e(TAG, "Error: " + e.getMessage().toString());
then you don't need the exception, you just need a string. As I said on your previous question, catching NullPointerException is rarely the correct thing to do; more generally, using exceptions for control flow is a pretty dubious practice. And using System.exit is rarely what you really want to do.
You can create a method something like:
boolean logMessageAndExit(String message) {
Log.e(TAG, "Error: " + message);
System.exit(1);
return false;
}
and then call in your code like this:
if (activity == null) {
return logMessageAndExit("isFragmentShowing: context reference is null");
}
if (tag != null && !tag.equals("")) {
return logMessageAndExit("isFragmentShowing: fragment tag passed is null or empty");
}
Fragment fragment = fragmentManager.findFragmentByTag(tag);
return fragment != null && fragment.isVisible();
Returning a boolean here is a mere convenience to allow you to return it: this convinces the compiler that execution never goes past that line, even though the return is never really executed.
(You could make it return something Throwable instead, so you can throw logMessageAndExit, to make it more clear that it is abnormal).
Alright, here's how your isFragmentShowing method should be like.
You see I've removed ALL of the try/catches. This is because your method already throws a checked Exception and the code calling your static method would need to wrap the call to isFragmentShowing inside the try/catch none the less. You can catch the NPE there quite easily and even print out its stack trace which would let you know which instance was essentially null. Either fragment or activity. The only time we need to actually throw an NPE is when tag.equals("") returns true (since that won't throw an exception). I've also replaced the last ternary operator return by just fragment != null && fragment.isVisible() since it means the same thing (true is returned if the expression evaluates to true and false on the right is returned otherwise, why not the return the result of the expression itself?)
And here's the code:
public static boolean isFragmentShowing(Activity activity, String tag) throws Exception {
FragmentManager fragmentManager = FragmentUtils.getFragmentManagerInstance(activity);
if (tag.equals("")) {
throw new NullPointerException("isFragmentShowing: fragment tag passed is empty");
}
Fragment fragment = fragmentManager.findFragmentByTag(tag);
return fragment != null && fragment.isVisible();
}

Dial multiple numbers one by one programmatically | Android

I am trying to develop a feature for an app where you have a list of "codes" that you enter and that are dialed one by one. I have looked over TelephonyManager and followed a tutorial on developing a broadcast receiver with a listener for responses but it does not always work as it should.
One idea was to store all the numbers necessary in SharedPref. If the Activity (only created for the intent towards dialer) went into onStop() (meaning that above, the dialer screen was on) and then into onResume() (call ended and activity resumed), I would remove the number last dialed from the SharedPref and then, if any remained, open the dialer again. The broadcast made sure than once the state flow of the TelephonyManager was "OFFHOOK => IDLE", it would return the user to the Activity . Short story, it did not always perform as it should have.
How should I tackle the problem ?
EDIT
My curent solution was to
Create a doPhoneCall() function that would handle the intent creation and deployment itself.
#Override
protected void doPhoneCall(){
super.onResume();
wentIntoCall = false;
/** More code here for dialing */
}
Place this function into the onResume(). Even if the onResume will be called multiple times, the wentIntoCall boolean will make sure that the function won't be called multiple times.
#Override
protected void onResume() {
super.onResume();
if(wentIntoCall)
doPhoneCall();
}
Having in mind that after a call, the phone should return to its previous state, so it would return to the Activity in which we are doing are call, we will add to the activity a CallListener, and in the case of IDLE, based on the tutorial linked above, we make the wentIntoCall be true. ( The activity will go into onResume() and, upon seeing that the boolean is true, it will initialize the next call ).
case TelephonyManager.CALL_STATE_IDLE:
Log.e(TAG, "CALL_STATE_IDLE==>"+incoming_number);
if((prev_state == TelephonyManager.CALL_STATE_OFFHOOK)){
prev_state=state;
wentIntoCall = true;
//Answered Call which is ended
}
if((prev_state == TelephonyManager.CALL_STATE_RINGING)){
prev_state=state;
wentIntoCall = true;
//Rejected or Missed call
}
My final question : is this the right way to handle this functionality, or should I try to come up with another implementation of it ?
EDIT 2
Looks like my "codes", being USSD codes, are not behaving like normal phone calls.. So for normal phone calls the code above seems to work, but for dialing codes, not that much. I have "downgraded" my solution to a simple for-loop. Seems to be working fine now.
I dont know for android O , but for android 6.0 > You cant detect answer in direct way . Call no exist number and see PhoneStateListener what will trigger in one case and track successed call also.
Make public static array , add all your numbers intro array .
I made services . Insert permissions in manifest make your own action also ( NEXT_CALL for example ) .
Than easy make intent for startServices :
SharedPreferences settings;
SharedPreferences.Editor SAVES;
Intent serviceIntent = new Intent(MainActivity.this, ServiceForCalls.class);
serviceIntent.setAction("xxx.xxx.NEXT_CALL");
startService(serviceIntent);
isCalling = true;
SAVES.putBoolean( "isCalling" , isCalling );
SAVES.commit();
SAVES.apply();
You must use timeout interval about 10 sec for next call.
Heres little help func - end call and phoneState handler :
void END_CALL () throws InvocationTargetException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException {
tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
Class c = null;
try {
c = Class.forName(tm.getClass().getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Method m = null;
try {
m = c.getDeclaredMethod("getITelephony");
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
m.setAccessible(true);
Object telephonyService = m.invoke(tm); // Get the internal ITelephony object
c = Class.forName(telephonyService.getClass().getName()); // Get its class
m = c.getDeclaredMethod("endCall"); // Get the "endCall()" method
m.setAccessible(true); // Make it accessible
m.invoke(telephonyService); // invoke endCall()
if ( SIGNAL_STOP == false ) {
timerHandlerServicesStartNewNumber.postDelayed(timerRunnableServicesStartNewNumber, 1000);
}
}
private class PhoneStateChangeListener extends PhoneStateListener {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch(state){
case TelephonyManager.CALL_STATE_RINGING:
Log.println( Log.INFO , "RINGING" , "SERVICES%%%%%%%%%%%%%%%%RINGING%%%%%%%%%%%%%%%%%%");
wasRinging = true;
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.println( Log.INFO , "OFFHOOK BROADCAST" , "SERVICES%%%%%%%%%%%%%%%%%%%%%%%%");
if (!wasRinging) {
// Start your new activity
Log.println( Log.INFO , "OFFHOOK BROADCAST" , "SERVICES%%%%%%%%%%%%%%%%%%%%%%%");
if (SIGNAL_STOP == false) {
timerHandlerServices.postDelayed(timerRunnableServices, 10000);
}
} else {
// Cancel your old activity
Log.println( Log.INFO , "OFFHOOK BROADCAST" , "SERVICES%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
}
// this should be the last piece of code before the break
wasRinging = true;
break;
case TelephonyManager.CALL_STATE_IDLE:
Log.println( Log.INFO , "IDLE BROADCAST" , "SERVICES%%%%%%%%%%%%%%%%%IDLE%%%%%%%%%%%%%%%%%%%");
// this should be the last piece of code before the break
wasRinging = false;
break;
}
}
}
Thanks for : "meaning that above, the dialer screen was on" nice catch.
As a side note, in the Android O developer preview there is a new API which allows you to send a USSD request and register a callback to receive its results. For newer versions of Android this might meet your needs better.

Android Beacon Library, Null Object Reference when calling startRangingBeaconsInRegion

I'm developing an android app using beacon library, part of this app is about to search for a specific beacon via its minor ID (which is inserted by user via dialog).
if I write everything in the same activity things works fine but I'd like to keep dialogs separate in an external pure java class, so in the activity implementing BeaconConsumer I added a "method" creating and binding the beacon manager.
public class Activity03 extends AppCompatActivity
implements BeaconConsumer, RangeNotifier {
...
public void scanForBeacon(Context context, String selectedMinorId){
beaconManager = BeaconManager.getInstanceForApplication(context);
beaconManager.getBeaconParsers().add(new BeaconParser()
.setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
Identifier minorIdFilter = Identifier.parse(selectedMinorId);
myRegion = new Region(
"my_region",
null,
null,
minorIdFilter);
beaconManager.bind((BeaconConsumer) context);
}
...
}
The point is that when calling startRangingBeaconsInRegion, i got:
Attempt to invoke virtual method 'void org.altbeacon.beacon.BeaconManager.startRangingBeaconsInRegion(org.altbeacon.beacon.Region)' on a null object reference
The sequence is:
1. the user is asked (via GoogleApiClient) to switch on BLE and localization
2. inside onActivityResult the dialog for inserting minor ID is picked from the java class DialogUtilities
DialogUtilities.showSelectionDialog(Activity03.this);
3. pressing the button dialog is dismissed, an instance of the BeaconConsumer activity is created and the method called:
Activity03 a03 = new Activity03();
a03.scanForBeacon(context, minorId);
4. when the onBeaconServiceConnect() is called I got null object reference on the line of startRangingBeaconsInRegion
#Override
public void onBeaconServiceConnect() {
try {
beaconManager.startRangingBeaconsInRegion(myRegion);
} catch (RemoteException e) {
e.printStackTrace();
}
}
I'm new of java and android but it doesn't seems to me that problem is about the Region because I've the same response even if I set to null all the Identifiers so I cannot understand why null reference.
Is it possible that I create two different BeaconMangers because of the activity's istance I return by Dialog ? If so how I can solve it?
If not, how to avoid this null object reference?
Thanks in advance
EDIT
BeaconManager declaration
public class Activity03 extends AppCompatActivity implements BeaconConsumer, RangeNotifier {
static final int REQUEST_CHECK_SETTINGS = 1000;
private BeaconManager beaconManager;
private Region myRegion;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(R.style.AppTheme);
setContentView(R.layout.activity_03);
}
#Override
protected void onResume() {
#Override
super.onResume();
PermissionsUtilities.switchLocationAndBluetooth(Activity03.this);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
final LocationSettingsStates states = LocationSettingsStates.fromIntent(data);
switch (requestCode) {
case REQUEST_CHECK_SETTINGS:
switch (resultCode) {
case Activity.RESULT_OK:
DialogUtilities.showSensorSelectionDialog(Activity03.this);
break;
case Activity.RESULT_CANCELED:
...
break;
default:
break;
}
break;
}
}
You can try the code below to avoid null pointer exception:
beaconManager.setRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection beacons, Region region) {
if (beacons.size() > 0) {
Log.i(TAG, "The first beacon I see is about "+beacons.iterator().next().getDistance()+" meters away.");
}
}
});
try {
beaconManager.startRangingBeaconsInRegion(new Region("myRangingUniqueId", null, null, null));
} catch (RemoteException e) {
e.printStackTrace();
}
The question does not show the declaration of beaconManager and how it is scoped, so it is hard to say the exact cause.
Two tips:
The BeaconManager is a singleton, meaning there is one instance per Java process. So you can always get this instance from within an Activity like this: BeaconManager.getInstanceForApplication(this).startRangingBeaconsInRegion(myRegion);
Manually constructing a new Activity instance as shown below generally will not work in Android programming. You must create new Activity instance using an Intent. In your case I suspect you may not want to create a new Activity instance at all but to get a reference to the existing one. This may be unrelated to what you are asking, but it will certainly need to be changed: Activity03 a03 = new Activity03();
a03.scanForBeacon(context, minorId);

java.lang.IllegalStateException Fragment not attached to Activity

After I receive a response with Volley, I have to get back to the main fragment.
I have two different volley requests , depending on some condition, I'll call it 'a' in this example.
The weird thing is the when a==1, popBackStack gets me successfully to the main fragment .
When a==0 it crashes and I receive java.lang.IllegalStateException Fragment not attached to Activity
I tried creating a new main fragment (transaction.commit....) but it didn't help.
if( a == 0 )
{
VolleyManager.add(jsnObj,
new RequestListener() {
#Override
public <T> void onSuccess(T object) {
mFragmentManager.popBackStack(DataManager.BACK_STACK_KEY_MAIN_FRAGMENT, 0);
}
});
}
else if( a==1 )
{
VolleyManager.update(jsnObj,
new RequestListener() {
#Override
public <T> void onSuccess(T object) {
mFragmentManager.popBackStack(DataManager.BACK_STACK_KEY_MAIN_FRAGMENT, 0);
}
});
}
Error -
java.lang.IllegalStateException: Fragment MainFragment{6aaaf7f} not attached to Activity
at android.app.Fragment.getResources(Fragment.java
The problem seems to be with the getResources(), but I do the same thing when a==1 and I've got no problems at all.
It seems like that by the time AsyncTask finishes and calls onPostExecute, the MainFragment has been detached from its activity. So either the activity has already been destroyed or fragment was never attached.
So if fragment is not attached to the activity, it can't access resources because that requires context and fragment doesn't have but activity does.
So you should check if activity is null or not before calling getResources.
Update the code like this:
if(getActivity()!=null){
String streetFormat = getActivity().getResources().getString( R.string.address_name_string );
....
}
You have to cancel your requests on
onDestroyView()
method of the fragment or check if the fragment is already alive and added to host activity or not
I'd go with something like this:
onDestroyView(){ Volley.cancelAllRequests() }
or
onResponse(){ if(getActivity() != null && isAdded(){ // here handle the response and update views, otherwise just cache the response!}}
getResources() must be called from something that has Context, like the activity. The fragment itself does not have the Context since it does not implement it. If you're using getResources() in a fragment, you can try this:
String streetFormat = getActivity().getResources().getString( R.string.address_name_string );

Exception while writing to MifareUltralight

I get an exception while trying to write a MifareUltralight NFC tag on Android. The error shown in logcat is:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.setVisibility(int)' on a null object reference at
.MainActivity.getTagInfo(MainActivity.java:124)
com.mynfctest.MainActivity.resolveIntent(MainActivity.java:106)
com.mynfctest.MainActivity.onNewIntent(MainActivity.java:98)
How I can solve this error?
Write method:
public static boolean writeOnMifareUltralight(Context _context, Tag tag, String pageData, int i) {
MifareUltralight mifare = null;
int size=pageData.length();
try {
mifare = MifareUltralight.get(tag);
mifare.connect();
mifare.writePage(i, pageData.getBytes(Charset.forName("US-ASCII")));
} catch (Exception ex) {
ex.printStackTrace();
Log.d("skm", ex.getMessage());
// return false;
} finally {
try {
mifare.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
return true;
}
Write method called from my activity:
switch (mifareUlTag.getType()) {
case MifareUltralight.TYPE_ULTRALIGHT:
boolean result=NFCHammer.writeOnMifareUltralight(this,tag,tvName.getText().toString(),4);
if(result){
findViewById(R.id.incProgressBar).setVisibility(View.GONE);
Intent Callintent = new Intent(this, HomeActivity.class);
Callintent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(Callintent);
finish();
overridePendingTransition(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
}
else{
findViewById(R.id.incProgressBar).setVisibility(View.GONE);
CommonTask.createToast("Tap The card again!!!", this, Color.RED);
}
break;
}
As the exception explains, you are calling the method setVisibility on a null ob ject reference:
java.lang.NullPointerException: Attempt to invoke virtual method '... setVisibility(int)' on a null object reference
In other words, somewhere in your code, you have a like this:
object.setVisibility(...);
and on this like the variable object is null and does not reference a real object.
The stacktrace of the exception further tells you that the exception occured on line 124 of the file MainActivity.java, more specifically inside a method named getTagInfo:
at .MainActivity.getTagInfo(MainActivity.java:124)
As you did not reveal enough code to verify if the problem comes from those code snippets that you posted, we can only speculate that the problem comes from the two lines that set the visibility of a view R.id.incProgressBar to GONE:
findViewById(R.id.incProgressBar).setVisibility(View.GONE);
If that's the case, then findViewById(R.id.incProgressBar) returned null, indicating that the view R.id.incProgressBar was not found in the current view hiearchy of the activity.

Categories

Resources