I am having some trouble with my simple app. The app starts in the MainActivity where you can press a camera icon. This opens an implicit intent for taking a photo. When the photo is taken, another activity DisplayImageActivity is opened. This activity consists of two fragments: one that holds an ImageView for displaying the photo and another one that holds some TextViews that displays some information about the photo (filename, size, location etc.). I use a ViewPager for having horizontal swipe capabilities.
Now to the problem. I should note that this is not a consistent problem. Sometimes the app crashes, sometimes it works just fine. The problem lies in getting the image path from the onActivityResult in MainActivity to the two fragments so I can get the image and info. Here is my onActivityResult method:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 42 && resultCode == RESULT_OK) {
Log.d(TAG, "MainActivity onActivityResult method called.");
Intent intentShowPicture = new Intent(this, DisplayImageActivity.class);
intentShowPicture.putExtra(PICTURE_KEY, imgPath);
startActivity(intentShowPicture);
}
}
So I just put the image path I get from taking the picture in the bundle and start the DisplayImageActivity. Then in my DisplayImageActivity, I do this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_image);
Log.d(MainActivity.TAG, "DisplayImageActivity onCreate called.");
imgPath = getIntent().getExtras().getString(MainActivity.PICTURE_KEY);
mAdapter = new FragmentAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mAdapter);
Then I have a method that just return the straing imgPath:
public String getImgPath() {
return imgPath;
}
Then inside the fragment (PictureFragment) I try to retrieve the imgPath like this:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
DisplayImageActivity activity = (DisplayImageActivity) getActivity();
imgPath = activity.getImgPath();
But as I mentioned earlier, sometimes the getImgPath method just returns null and the app crashes when I try to retrieve the photo. But sometimes it works fine. I am kinda lost as to why this is. Is it because the fragment is sometimes constructed before the imgPath variable is assigned in the DisplayImageActivity, so the variable is just null?
I am kinda new to android, so this might not be the best approach. I just did it from the top of my head. Any ideas why this is happening?
If you want to pass data from an Activity to a Fragment, you could use this approach:
In the Activity:
Bundle bundle = new Bundle();
String imgPath = "path/to/my/image";
bundle.putString("imgPath", imgPath );
PictureFragment frag = new PictureFragment();
frag.setArguments(bundle);
transaction.replace(R.id.fragment_single, frag);
transaction.commit();
Fragment:
Reading the value in fragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
String myValue = this.getArguments().getString("imgPath");
...
...
...
}
For more information, take a look at this question How to pass a variable from Activity to Fragment, and pass it back?
Related
The problem that Teno I want to use an intro slide in my app through fragments and the third fragment I want to put a button that leads to another activity and in Android studio the code does not make any error but when I run the app and click the app button It stops what is it?
public ThirdFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_third, container, false);
viewPager = getActivity().findViewById(R.id.viewPager);
back1 = view.findViewById(R.id.slideThereback);
back1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
viewPager.setCurrentItem(1);
}
});
//The TextView "Done " is the one I want to click on the Take me to another activity and that up to now gives me an error to run in the emulator
done = view.findViewById(R.id.Done);
done.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent myIntent = new Intent(getActivity(), MenuP.class);
startActivity(myIntent);
}
});
return view;
}
I hope I can provide the code or say my error to open a new activity in a fragment and not close the app to Ejecutarce on a mobile device
Use the below code in your onClick() method.
Intent myIntent = new Intent(getActivity(), MenuP.class);
getActivity().startActivity(myIntent);
Check that R.id.Done does exists in R.layout.fragment_third. if it doesn't exist then done View might be null.
I need to pass a String from an Activity to a fragment but nothing seems to work for me.
I found this answer on stackoverflow
From Activity you send data with intent as:
Bundle bundle = new Bundle(); bundle.putString("edttext", "From
Activity"); // set Fragmentclass Arguments Fragmentclass fragobj = new
Fragmentclass(); fragobj.setArguments(bundle);
and in Fragment onCreateView method:
#Override public View onCreateView(LayoutInflater inflater, ViewGroup
container,
Bundle savedInstanceState) {
String strtext = getArguments().getString("edttext");
return inflater.inflate(R.layout.fragment, container, false); }
But this doesn't work for me. When I click the button nothing happens.
Is it maybe because the fragment is already created? In my app: ToDoFragment> Activity(pass data to:>ToDoFragment
Here is my code but I don't thing it will provide more info:
Activity.java (inside OnClickListener of a button)
String datePassed = mDate.getText().toString();
String toDoPassed = mEditText.getText().toString();
Bundle bundle=new Bundle();
bundle.putString("key1", datePassed);
//set Fragmentclass Arguments
ToDoFragment myToDoFragment=new ToDoFragment();
myToDoFragment.setArguments(bundle);
ToDoFragment.java (inside oncreateview)
Bundle bundle = this.getArguments();
if (bundle != null) {
mToDoInfo = getActivity().getIntent().getStringExtra(key1);
If I understood correct, then you are not doing it wrong, but you are doing this in wrong scenario. This is on assumption that your fragment is already inflated & you are starting new Activity from it & want the data back as result from it. so what you need is something like this,
inside your ToDoFragment where I believe you are starting activity, do this instead:
startActivityForResult(new Intent(getActivity(), MyActivity.class), 1001);
& override onActivityResult method like:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 1001 && resultCode == Activity.RESULT_OK) {
String myData = data.getStringExtra("my_key");
}
}
& now inside onClick of your MyActivity,
Intent intent = new Intent();
intent.putExtra("my_key", "my_data");
setResult(RESULT_OK, intent);
finish();
this should invoke onActivityResult of fragment where we wrote code to get data.
Yes this is because the fragment is already created. Create a method in your fragment class and call it from inside the onClick method of your activity.
Let me make it Easy for you!
ToDoFragment myToDoFragment=new ToDoFragment(datePassed); //easy right?
and in your ToDoFragment class make a constructor with String as input!
You can simply follow this pattern to pass the values from activity to fragment
ToDoFragment.java
public class ToDoFragment extends Fragment {
String date;
public static Fragment newInstance(String date) {
ToDoFragment fragment = new ToDoFragment();
fragment.date = date;
return ToDoFragment;
}
}
In your activity's onclick
String toDoPassed = mEditText.getText().toString();
ToDoFragment myToDoFragment = ToDoFragment.newInstance(toDoPassed);
In one of my activities I have a button, when pressed it stores a string value inside a bundle that I want to send to another activity and display in a TextView.
Code for when the bundle is created:
public void enemy_seen(View view){
Intent send_enemy = new Intent(rear_gunner.this, pilot.class);
String sight = "ENEMY SPOTTED";
Bundle spotted = new Bundle();
spotted.putString("TAG",sight);
send_enemy.putExtras(spotted);
}
This code hapens on the button clicked and so far, from what I can tell this works....I believe.
When the bundle is called in second activity:
public class pilot extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pilot);
//sets screen orientation on created
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
Bundle bundle = getIntent().getExtras();
String something = bundle.getString("TAG");
TextView enemy = (TextView) findViewById(R.id.enemy_spotted);
enemy.setText(something);
}
}
The activity loads and crashes. So it must be something to do with when using the bundle I believe?
I don't see you starting the activity from the intent you set the bundle.
The activity will only receive the bundle you put in an intent if you fire that activity with that intent.
You should do a startActivity(send_enemy) after setting the bundle to the intent.
I am making an app, that will have FragmentsActivity and after clicking on Floating Action Button making a simple button on the screen. How I should implement something like that. Now I have got this:
at main.java
#Override
public View onCreateView(final LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.monday_act, container, false);
RelativeLayout rl = (RelativeLayout) rootView.findViewById(R.id.rel);
rl.addView(new DayView(this.getContext(), getArguments().getInt(ARG_SECTION_NUMBER)));
FloatingActionButton fab = (FloatingActionButton) getActivity().findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent addClass = new Intent(getActivity(), AddClass.class);
startActivityForResult(addClass, 1);
}
});
return rootView;
}
and the onActivityResult:
#SuppressLint("SetTextI18n")
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1)if (resultCode == RESULT_OK) {
final Button lesson = new Button(this.getActivity());
lesson.setText("Button");
lesson.setBackgroundColor(getResources().getColor(R.color.green));
lesson.setTextColor(getResources().getColor(R.color.red));
lesson.setX(100);
lesson.setY(100);
lesson.setWidth(100);
lesson.setHeight(150);
lesson.setTextSize(100);
RelativeLayout(this.getActivity());
rl.addView(lesson);
}
}
Both functions are in public static class PlaceholderFragment extends Fragment {
You don't use onActivityResult() between Activity and Fragment
you use it between two Activities
A activity will command another activity to do some work on some data passed to it or a request is made to the other activity to fetch something or do something and return the result.
after the work is done the worker Activity finishes it self and returns the result to the activity which started it.
And the activity who issues the work will have onActivityResult() it updated the UI depending on the result it gets
Hers is my code
public static class DetailFragment extends Fragment {
private String forecastData;
private static final String LOG_TAG = DetailFragment.class.getSimpleName();
private static final String FORECAST_SHARE_HASHTAG ="#SunshineApp";
public DetailFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_detail, container, false);
//receive forecast data from the ForeCast Fragment
Intent intent=getActivity().getIntent();
forecastData=intent.getStringExtra(Intent.EXTRA_TEXT);
Log.v(LOG_TAG,"data is "+forecastData);
TextView textView=(TextView)rootView.findViewById(R.id.detail_text);
textView.setText(forecastData);
return rootView;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_detailfragment,menu);
MenuItem menuItem=menu.findItem(R.id.action_share);
// Get the provider and hold onto it to set/change the share intent.
ShareActionProvider mShareActionProvider =
(ShareActionProvider) MenuItemCompat.getActionProvider(menuItem);
// Attach an intent to this ShareActionProvider. You can update this at any time,
// like when the user selects a new piece of data they might like to share.
if (mShareActionProvider!= null ) {
mShareActionProvider.setShareIntent(createShareIntent());
}
else
{
Log.v(LOG_TAG,"Share Action Provider is null");
}
}
public Intent createShareIntent()
{
Log.v(LOG_TAG,"data is "+forecastData);
Intent intent=new Intent(Intent.ACTION_SEND);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT,forecastData+DetailFragment.FORECAST_SHARE_HASHTAG);
Log.v(LOG_TAG,"data is "+forecastData);
return intent;
}
I am absolutely sure the intent is fired correctly because i can share with other apps and it works ,It's clear if you see the logs below
01-04 18:36:02.370 6121-6121/com.example.droid.sunshine V/DetailFragment﹕ in optionMenu method data is null
01-04 18:36:02.380 6121-6121/com.example.droid.sunshine V/DetailFragment﹕ in create intent data is null
01-04 18:36:02.380 6121-6121/com.example.droid.sunshine V/DetailFragment﹕ in create intent data is null
01-04 18:36:02.650 6121-6121/com.example.droid.sunshine V/DetailFragment﹕ in view method data is Wed, Jan 7 - Clear - 27/24
Why is this , i thought OnCreate() view method was called before OnCreateOptionsMenu()
?what do i do to rectify this?
Here's an idea:
According to your logs, the outputs are FIRST displayed from the onCreateOptionsMenu() method and only the last one is from the onCreateView(). That would mean that onCreateOptionsMenu() is called before onCreateView which would explain why everything is null.
Try moving setHasOptionsMenu(true) somewhere else, maybe in the constructor That should make sure that onCreateOptionsMenu() is called after onCreate and onCreateView. Try it.
imho you should move your code from onCreateView() to onActvivityCreated().
onCreateView is meant to return the view.
onActivityCreated means that the associated activity has completed its method onCreate() and is set up.