Hi All I want to open the "Text-To-Speech output" fragment of Settings from my application. I think first I need to open the settings activity and then its fragment. I tried setting the ComponentName but it was unable to locate the activity.
Should I use FragmentManager; I couldn't find anything specific to my needs. Can somebody give me some link which might explain it well.
You are right, First You need to start the Activity than set the current Fragment in FragmentPager / Manager... Their is no such way to start some foreign fragment from your Activity that would be dangerous see that will lead to zombie fragments floating around the App (or May be I am not aware of that..)
You call the Activity Intent with some parameter for the Fragment name, you want to start i.e. interger, boolean etc...
Intent intent = new Intent(this,SecondActivity.class);
intent.putExtra("fragmentNumber",1); //for example
startActivity(intent);
You check the passed value inside OnCreate of the Second Acitivty and set the desired fragment on top.. inside OnCreate
if(getIntent().getIntExtra("fragmentNumber",0)==1){
//set the desired fragment as current fragment to fragment pager
}
However, I am not getting the problem "It was unable to locate the activity." Have you entered the Activity in manifest file than what was the problem you were facing? Please post the full stack trace.
You can use the following:
Intent ttsSettings = new Intent("com.android.settings.TTS_SETTINGS");
ttsSettings.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(ttsSettings);
Related
In my MainActivity, I have a viewPager
containing two containers "A and B".
Both containers are possessed with their own Fragments.
In container B; I again have a viewPager containing multiple fragments.(For example one,two,three,four)
On launch of my app MainActivity gets load with container A's homeFragment.
What I need to do is,For a given condition I have to launch fragment two of container B from onResume of my MainActivity.
What I've able to achieve is , I have successfully redirect to container B's fragment one but couldn't able to redirect towards fragment two from onResume of MainActivity, any help will be appreciate.
If you are using Intent to redirect to Fragment B, then pass the int position of sub fragment, and on the fragment B side check for intent extras and set the current page, which you received via intent.getIntExtra().
If I understood it clear, you want to show the second page of the viewpager when you open it, if so you can use mViewPager.setCurrentItem(1, true);
I think you want to set the specific page .. so to do that you can set viewpager as :
viewpager.setCurrentItem(item, true);
Certainly,I found a way of achieving this by using static concept.
I have declared a static variable inside container B's fragment two,and set its value in onResume of MainActivity.
When onResume calls with given condition it sets static variables value to the required fragment, and in my container B,I have used this value to set setCurrentItem() of B'viewPager.
ps: I know it quite confusing as it seems but not too complex in practice,work fine.
I've found a lot of questions about that, but none of these can help me.
I have a "MainActivity" which have 4 fragments.
I need to access to one of these fragments, called "my_fragment", in an other simple activity, let's call "SecondActivity".
So, I try to put a property android:tag="my_fragment" in the LinearLayout markup XML of "my_fragment".
And after that, I do that in "SecondActivity":
Fragment frg = getFragmentManager().findFragmentByTag("my_fragment");
... in order to get my fragment. But frg is always null.
I try a lot of others ways, but in vain. This one seems better and easier to do, but perhaps I'm wrong.
Any help would be appreciate. Thank you in advance.
Fabien
EDIT
Since your answers that indicate that's isn't possible, I want to specify what I need.
I just want to get this fragment for reload it. I found something like that on an other subject on Stackoverflow:
frg= getFragmentManager().findFragmentByTag(my_fragment);
final FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.detach(frg);
ft.attach(frg);
ft.commit();
By the way, I just try to get the fragment in the fragment himself and it's still return null. With the method :
findFragmentById(R.layout.my_fragment)
it's the same result.
And after, I did :
findFragmentById(this.getId())
But it's make an infinite looper, I don't understand the reason...
EDIT2
Alright, let’s give some details :
I have MainActivity with ViewPager with 4 fragments. It’s not fragments at the xml sense. Sorry if I’m confused, I was training to Android very recently and somethings are not clear for me again. So, before yesterday and the read of #Bruce edit, I was thinking that fragments were the components of a ViewPager. So, #Bruce, this is why I can’t use your solution. I was trying to use findFragmentByTag with the tag applicate on my principal LinearLayout markup of my fragment - that is not, I repeat, an xml markup fragment.
This is my approach :
In my MainActivity, I click on the third fragment. I make a research for find some points around me. After an action of the user, still from the third fragment, I open the SecondActivity for authentification and on the user connection, I close this SecondActivity. Now, I need to reload the fourth fragment that will adapt his components in terms of the user situation, while keeping the same state on the third fragment, with points loaded. It’s why can’t use your solution #menion.asamm : I can’t reinstantiate the MainActivity, even if I simulate a click on the third fragment because it will come back in his initial state, without points loaded.
Thank you both of you #Bruce and #menion.asamm for your time in helping me !
Fragments are always owned by one activity, so you cannot directly access a different activity's fragments. The call you are making is looking for fragments within your SecondActivity.
Why do you want to do this? Once some UI is off screen (MainActivity), you usually don't want to do anything with those UI objects, because Android may have removed them from memory. If there is data in "my_fragment" that is needed by SecondActivity, one approach might be to save the data in SharedPreferences or a database in my_fragment, and then load it in SecondActivity.
EDIT
I'm not sure you're getting that it is important which activity you are running in. Here are two options for how to proceed:
If you just want to run the SAME instance of your fragment that was already running inside MainActivity, then maybe what you want to do is finish your SecondActivity to return to MainActivity.
If you want a NEW copy of the same fragment inside SecondActivity, then you can include the fragment inside SecondActivity's layout (or add it to some container later).
Also, notice that for your call to findFragmentById, the ID needs to be the ID that was specified in the layout file as the value of android:id (not the R.layout.my_fragment). It might be better to use a fragment tag, which you can either specify in your layout file or when you add the fragment.
Mainly I think you need to read Google's guide on fragments.
EDIT2:
Ah, I see, I have a similar fragment-refresh situation in my app. You basically need to get data from SecondActivity back to the fragment inside MainActivity. The approach I use is this:
Save the data from SecondActivity in storage (DB or SharedPreferences).
Finish SecondActivity so that MainActivity and your fragment are shown again.
Override onResume in your fragment to fetch the data you saved in SecondActivity.
Another option is to launch SecondActivity using startActivityForResult, and then process the results in MainActivity, passing them to its fragment.
Regarding how to find the fragment by tag, you first need to set the fragment's tag. If you are declaring your fragment in a layout XML, then you can do it there (and you can also declare
<fragment class="com.xyz.MyFragment"
android:tag="MyFragment"
android:id="#+id/my_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
Now from inside MainActivity you can either do findFragmentById(R.id.my_fragment) or findFragmentByTag("MyFragment").
If you are NOT declaring the fragment in XML, but adding it directly, you can set the fragment's tag as part of the add call:
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.frag_parent, new MyFragment(), tag);
EDIT3: Ah, you're using ViewPager to hold fragments. Now I understand better. They're still fragments, but getting access to them is indeed tricky, because Android constructs a fragment tag in some internal code. Here is another SO question on this issue:
Retrieve a Fragment from a ViewPager
Hmm if you really need just refresh of fragment attached to different activity, I suggest:
first activity start second activity with
startActivityForResult(intent, MY_CODE);
second activity when wants to refresh fragment in first activity, finish it's state with
Intent data = new Intent();
data.putExtra("REFRESH_FRAGMENT", true);
setResult(RESULT_OK, data);
finish();
back in first activity, you may catch this result by
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// check request code
if (requestCode == MY_CODE) {
// check result
if (resultCode == RESULT_OK) {
// check data
if (data != null && data.getBooleanExtra("REFRESH_FRAGMENT", false)) {
refreshFragment();
}
}
}
}
Possible?
I have 2 list views :
- The first one is instantiated in a fragment
- The second one in a activity.
They display the same information
On click on a list item, I open another activity to display item detail.
Depending on the calling activity/fragment, I want to render a different layout, so I need to know in the activity that render the detail of a item, which activity created the intent ?
getCallingActivity and getParentActivityIntent seems to be declarative and fixe, isn"t it ? in my case there are both null.
How can I do that ?
You can pass an argument with your intent as:
intent.putExtra("ParentActivity", "ActivityA");
or
intent.putExtra("ParentActivity", "ActivityB");
In your next activity, use this:
String parentActivity = getIntent().getStringExtra("ParentActivity");
And render the layout according to result.
Hope it helps.
To implement the up navigation, I would like to go back to a specific activity on the history stack. If the activities on the stack are implemented by different classes, it works like this (assuming I have activities A, B and C on the stack and want to go back to activity A:
protected void onUpPressed() {
Intent intent = new Intent(this, A.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
finish();
}
Android will pop activities off the stack until the activity specified by the intent is the top most (activity implemented by class A in this case).
However, my app has several activities on the stack implemented by the same class. That's because they display the same kind of data but for different objects. They were launched with an intent that specified both the class implementing the activity and the object to display (either in the extras bundle or in the data property).
Now I'm looking for code to again pop several activities off the history stack until the matching activity the top most. If I extend the above code and additionally set the extras bundle or the data property, it doesn't work. Android always matches the first activity implemented by the specified class and doesn't go back far enough. The extras bundle and the data property are ignored.
protected void onUpPressed() {
Intent intent = new Intent(this, A.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.setData(Uri.parse("myapp:" + rootId));
startActivity(intent);
finish();
}
So how can I achieve to go back to a specific activity? What intent fields does Android compare to determine if it has found the desired activity?
As you described, you have one Activity that show different content based on the starting Intent. Well, why not Fragments?
I don't know the details of your applications architecture, but is should be easy to refactor that Activity to a Fragment. There could be a FragmentActivity that wraps all the Fragments which responsible for showing the content. This way you would have much more freedome to handle the activity's stack of fragments.
Steps summarized:
Convert your existing Activity (that show the content) to a Fragment.
Make a FragmentActivity (that will manage the Fragments).
Make the FragmentActivity "singleInstance", so it will cache all the
"startActivity" requests, where you have the opportunity to add a
new Fragment representing the new content to show.
You could add fragments this way:
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
// ContentFragment is the Fragment that you made from your Activity.
// Here you can pass the intent that stores the object to show also,
// so the parsing of the intent would be the same.
ContentFragment fragment = ContentFragment.newInstance(intent);
getFragmentManager()
.beginTransaction()
.add(fragment, null)
.addToBackStack("id here that will be used at pop")
.commit();
}
And you can pop to a specific id this way:
getFragmentManager().popBackStack("id here", 0);
This solution has a side-effect. The fragments will stick together, so you cannot insert any other Activity between them. This is trivial, but worth mentioning since differs from your current implementation.
I also assumed that you are familiar with how "singleInstance" and Fragments work. Fell free to ask if something is not clear.
To implement FLAG_ACTIVITY_CLEAR_TOP, Android searches through your task's activity stack (from top to bottom) using the following test:
if (r.realActivity.equals(newR.realActivity)) {
Your problem is that realActivity is a ComponentName (so the above comparison locates the topmost activity in the stack that matches on package and class name): no further test is performed against the intent, so it is impossible to be any more specific about which of that component's activities you wish to target.
Therefore:
So how can I achieve to go back to a specific activity?
There is no native means of accomplishing this. Your best bet is probably to manually implement a form of bubbling as suggested by #VM4.
What intent fields does Android compare to determine if it has found the desired activity?
Only the component name.
I recommend storing your data model outside of the extras, using a singleton to access, and refreshing an activity using that data model on the onResume()
Lets say you are in /home/usr/vm4/development and in this activity you have somekind of Views (lets say TextViews) that let you go to all parent directories. (Clicking on for example "usr" will go to /home/usr. In windows it looks like this:
I don't think Android lets you back into a specific Activity based on extra data. However you can do a trick here. The View (that when clicked takes you somewhere) can have a String tag attached to it:
TextView link = new TextView();
link.setTag("/home/usr");
Now when you click this View in the onClick() method:
onClick(View v) {
String extra = v.getTag();
// start your activity with extras here.
}
Now you just need to make sure you add the right tags to your links when inflating the activity.
There are 4 Tabs in a TabHost, let them be A, B, C, and D. Now each one is just an index page and clicking on any of them shows a different activity.
The problem is that I need to start another activity when the user selects something from the content displayed in the tab. The other activity should also be displayed in the parent tab itself. Is it possible? Or will I have to try something else?
Try this, found this solution in android cookbook,
http://androidcookbook.com/Recipe.seam;jsessionid=5424397F3130CE7769FF47DD67742911?recipeId=1693&recipeFrom=ViewTOC
Can't you change the contentView of your tab instead of starting a new Activity ?
Maybe I'm wrong but I think also that starting an activity in a tab isn't possible because the TabView is hosted in a activity and not the opposite (Tabview don't host an activity per Tab).
I think the common consensus is that it is best not to use individual Activities as tab content due to these limitations. See these questions and answers for pointers to alternatives:
Android: Why shouldn't I use activities inside tabs?
Android - Tabs, MapView, activities within tabs
To summarize the link that Rukmal Dias provided. Here's what you do:
Change your current Activity (that's in a tab) to derive from ActivityGroup
Create a new intent for the Activity you want to switch to
Copy/Paste and call this function in your current activity where "id" is the "android:id" for the layout of the new activity you want to switch to
public void replaceContentView(String id, Intent newIntent){
View view = getLocalActivityManager().startActivity(id,newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)) .getDecorView();
this.setContentView(view);}
Here's an example of how I make the call to switch views from my current Tabbed Activity:
public void switchToNextActivity(View view)
{
Intent myIntent = new Intent(getApplicationContext(), MyNextActivity.class);
replaceContentView("next_activity", myIntent);
}
It looses the view hierarchy. When you press the back button, in my case, the app closes.