Pass the context from a fragment inside an activity to another class - java

I have a fragment which is instantiated by an Activity. The issue that I'm having is that I have another class in the fragment which takes as a parameter an Activity context.
public class LocationQueries {
Activity context;
private static int REQUEST_CODE_RECOVER_PLAY_SERVICES = 200;
public LocationQueries(Activity context) {
this.context = context;
}
public boolean checkGooglePlayServices() {
int checkGooglePlayServices = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(context);
if (checkGooglePlayServices != ConnectionResult.SUCCESS) {
/*
* google play services is missing or update is required
* return code could be
* SUCCESS,
* SERVICE_MISSING, SERVICE_VERSION_UPDATE_REQUIRED,
* SERVICE_DISABLED, SERVICE_INVALID.
*/
GooglePlayServicesUtil.getErrorDialog(checkGooglePlayServices,
context, REQUEST_CODE_RECOVER_PLAY_SERVICES).show();
return false;
}
return true;
}
}
I instantiate that class in my fragment like this
private LocationQueries locationQueries = new LocationQueries(getActivity());
but when I try to use locationQueries.checkGooglePlayServices();
I get Caused by: java.lang.NullPointerException: Attempt to invoke virtual method android.content.pm.PackageManager android.content.Context.getPackageManager() on a null object reference.
It looks like the LocationQueries(getActivity()) doesn't actually pass the activity context. How can I solve this ?
Edit: Everything is working if I do the same from an Activity -> LocationQueries(this);

It seems that you initiate LocationQueries at the wrong place. Indeed, I assume this:
private LocationQueries locationQueries = new LocationQueries(getActivity());
is called as a global variable in your Fragment class.
Instead you should keep your variable as global but set it into onCreate() or onResume(), as follows:
private class Frag extends Fragment {
private LocationQueries locationQueries;
...
#Override
public void onCreate(Bundle inState) {
locationQueries = new LocationQueries(getActivity());
}
}

Your Fragment appears not to be attached to an Activity.
I suspect you have instantiated your LocationQueries object before onAttach(Activity activity) has been called, or after onDetach() has been called on your Fragment.
In such a case, calling getActivity() will return null which is what you then pass to your LocationQueries object resulting in the NPE.

Related

How to change view visibility at parent fragment from child fragment?

I am using nested fragment that have hierarcy looks like this :
MainActivity>parent fragment> child fragment.
mainactivity hold few parent fragment like fragment10,fragment11,fragment12.
and on parent fragment hold few fragment too like fragmentinti,fragmentdasar,fragmentindikator.
At fragment10 i hv relativelayout that blocking listview, the recyclerview is showing information if i dont hv data.
At fragmentinti i hv process that getting from API if hv data relativelayout on the fragment10 must be setvisibility GONE.
I have trying to use some code at stackoverflow but its still give me an error,
first code that i tested
fragmentKelas10 = (fragmentKelas10) getParentFragment();
fragmentKelas10.getView().findViewById(R.id.nodata).setVisibility(View.GONE);
second
fragmentKelas19 parentFrag = ((fragmentKelas10)fragmentKompetensiInti.this.getParentFragment());
parentFrag.setVisibilityNoData(View.GONE);
third
(fragmentkelas10 getparentfragment()).setvisivity(View.GONE);
and on my parentfragment i add public method
public void setVisibilityNoData(int visibility){
nodata.setVisibility(visibility);
}
*nodata is relativelayout
all above code that i tried return error message like this
Attempt to invoke virtual method 'android.view.View edu.stikom.molearn.fragment.fragmentKelas10.getView()' on a null object reference
Make The activity or fragment you want to return to implement OnFragmentInteractoinLister and when on no data gets called it can return to that fragment or activity and you can hide whatever you want.
private OnFragmentInteractionListener mListener;
public void onNoData() {
if (mListener != null) {
mListener.onFragmentInteraction();
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
void onFragmentInteraction();
}

Call mainActivity's method in LifecycleObserver

I'm in trouble.
I would like to call my MainActivity's method from my LifeCycleManager ( which is a LifecycleObserver ) and perform simple XML modifications. But that crash because I'm trying to access to an XML value and main_activity.xml isn't fully created yet
First this is my LifeCycleManager :
class LifeCycleManager(context: Context) : LifecycleObserver {
companion object {
var notif = NotificationManager()
var onForeground = false
var main = MainActivity()
// If we are on MainActivity return true , otherwise return false
fun isOnHomeController(context: Context?): Boolean {
if (context == null || context !is MainActivity)
return false
return true
}
var mContext = context
// WHEN THE APP BECOME ACTIVE
#OnLifecycleEvent(Lifecycle.Event.ON_START)
fun appComeBackFromBackground() {
onForeground = true
notif.cancelAllLocalNotifications(mContext)
if (isOnHomeController(mContext)) {
// Call the refresh dialog and print it
main.appComeBackFromBackground("refresh", null)
}
}
}
Here is my MainActivity method :
fun appComeBackFromBackground(status: String?, elementsadded: Int?)
{
Log.e("enterForeground", "App come back in Foreground")
if (status == null) return
when (status)
{
"refresh" ->{
val text = findViewById<TextView>(R.id.refreshtext)
text.setText("test")
}
else -> {
return
}
}
}
As you can see when my MainActivity Start , my Lifecycle get the event and go directly in my appComeBackFromBackground() method.
In it I'm calling my MainActivity method where I want to modify an element from activity_main.xml
That crash with theses :
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mControllers.MainActivity}: java.lang.RuntimeException: Failed to call observer method
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.Window$Callback android.view.Window.getCallback()' on a null object reference
What can I do please? I really need to do it like this ( LifecycleObserver to MainActivity ). Thank's
EDIT :
I tried to call my MainActivity's method with delay like this :
Handler().postDelayed({
main.appComeBackFromBackground("refresh", null)
}, 5000)
And it crash too , even if MainActivity layout is loaded
I am writing this in Java,
(This is the method if you don't want to save the data in preferences or storage)
Application Class:
public class TestApplication extends Application implements ActivityLifecycleCallbacks {
private static String mStringToSet;
#Override
public void onCreate() {
super.onCreate();
//App is not from background, a new instance of your app is created
mStringToSet="new_instance";
registerActivityLifecycleCallbacks(this);
}
public static String getStringToSet() {
return mStringToSet;
}
#Override
public void onActivityDestroyed(Activity activity) {
if(activity instanceof MainActivity){
//This is only called when the activity is destroyed not the application, so if the context is your desired activity then set the string here
mStringToSet="refresh";
}
}
//Implement other life cycle methods**
In your activity:
public class MainActivity extends AppCompatActivity {
private final String TAG="ACTIVITY";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if("refresh".equals(TestApplication.getStringToSet())){
Toast.makeText(this,"From Background",Toast.LENGTH_SHORT).show();
(TextView)findViewById(R.id.YOUR_TEXT_VIEW).setText("refresh")
}else{
Log.d(TAG,TestApplication.getStringToSet());
Toast.makeText(this,"Not from background",Toast.LENGTH_SHORT).show();
(TextView)findViewById(R.id.YOUR_TEXT_VIEW).setText("new_instance")
}
}
}
//Implement other life cycle methods
}

Which is a better way to code getActivity() , getApplicationContext()?

i'm not asking diffrence, but how to use these referenes?, Class level object to store their reference or use getter everytime which is provided by super class, Which is a better code practice: 1. call getActivity(), getApplicationContext() ..etc everytime in a local method or pass method as parameter when required in an activity or fragment.
Store their reference in a class level object and use it whereever it's required with null check in an activity or fragment.
I would like to know what is more efficient and why?
type1:
Class A extends Activity
{
#Override
public void onCreate()
{
methodA(getApplicationContext());
//or if fragment
methodA(getActivity());
Toast.makeText(getApplicationContext(),...).show();
}
private void methodA(Context mContext)
{
......
......
}
private void methodA()
{
Activity activity = getActivity();
......
......
}
}
type2:
class A extends Activity{
private Activity mContext;
private Activity mActRef; //if fragment
#Override
public void onCreate()
{
mContext = getApplicationContext();
mActRef = getActivity();//if fragment;
methodA(mContext);
//or if fragment
methodA(mActRef);
..........
.........
.........
Toast.makeText(mContext,...).show();
}
private void methodA(Context mContext)
{
......
......
}
private void methodA()
{
Toast.makeText(mContext,....).show();
}
}
}
getActivity() and getApplicationContext() both return the context and available throughout the class extend with Activity.
According to my opinion No need to create a global variable for them because they are available at class level. Both are correct but storing the context is not efficient.

Android call cameraApp from non-activity class issue

Though I found several similar answered questions, I couldn't solve my problem:
I use Fragment oFragment from where I want to call the Camera as a new Activity. Therefore I created a non-activity class Camera. When running I get the error:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.PackageManager android.app.Activity.getPackageManager()' on a null object reference
oFragment is placed in a FrameLayout in MainActivity. I also tried the constructor of Camera with Context context.
Do you see any workarounds or mistakes? Thanks in advance!
Edit: The code works fine if implemented directly into oFragment.
Class Camera:
public class Camera {
static final int REQUEST_IMAGE_CAPTURE = 1;
Activity activity;
public Camera(Activity activity) {
this.activity = activity;
}
public void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(activity.getPackageManager()) != null) {
activity.startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
Snipped from oFragment:
public class OFragment extends Fragment {
Camera cam = new Camera(getActivity());
...
#Override
public void onClick(View v) {
cam.dispatchTakePictureIntent();
}
I just solved it. I had to add the line super(); to my constructer and it works fine!

Run non static method on current activity from another class

I am struggling to figure out how to simply call and run a method from a class (that is not an activity) on my current activity.
my current code:
CustomListViewAdapter.java (other class)
public void onClick(View v) {
int position = Photos.listView.getPositionForView(v);
Log.v("value ", "tada" + position);
Photos photos = new Photos();
photos.deletePhoto(position);
}
});
Photos.java (my current activity class)
public void deletePhoto(int pos){
Toast.makeText(thisActivity, "delete index:"+pos , Toast.LENGTH_SHORT).show();
mylist.remove(pos);
setupListView();
}
Problem is, this way of doing it makes a new instance of mylist which gives me a outofbounds error. How can I do this correctly so I get the current activity and update it accordingly?
If you don't want a static method, you could create in interface.
public interface DeleteInterface {
public void deletePhoto(int position);
}
And then in your adapter's constructor...
private DeleteInterface mInterface;
public CustomListAdapter(/* other paramaters */ DeleteInterface interface) {
// other assignments
mInterface = interface;
}
And then in your Activity...
public class Photos extends Activity implements DeleteInterface {
// your code here
public void deletePhoto(int pos) {
// your method here
}
}
But make sure that when you create your Adapter, you have a pointer to the current Activity and pass it through the Adapter's constructor.
Last but not least...
In your adapter, call mInterface.deletePhoto(position); to call your Activity's method.

Categories