How to use Activities within fragments in Navigation Drawer - android

I am having an issue with using activities in fragments.
I have two activities , activity one will send data to two using intents.
Activity one is basically nfc scan part and tag information is sent using intents, Activity two will receive and display the info.
I am trying to put activities in fragments and use with navigation drawer UI.
How do i achieve this?
Activity 1 Code :
public class Activity2 extends Activity {
private NfcAdapter mAdapter;
private PendingIntent mPendingIntent;
private IntentFilter[] mFilters;
private String[][] mTechLists;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mAdapter = NfcAdapter.getDefaultAdapter(this);
mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
mFilters = null;
mTechLists = null;
Intent intent = getIntent();
String action = intent.getAction();
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action))
{
onNewIntent(intent);
}
}
#Override
protected void onResume() {
super.onResume();
mAdapter.enableForegroundDispatch(this, mPendingIntent, mFilters, mTechLists);
}
#Override
public void onPause() {
super.onPause();
mAdapter.disableForegroundDispatch(this);
}
#Override
public void onNewIntent(Intent intent) {
Log.i("Foreground dispatch", "Discovered tag with intent: " + intent);
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
startnfcread(tag);
}
private void startnfcread(Tag tag){
try {
NfcV nfcv = NfcV.get(tag);
if(nfcv != null){
nfcv.connect();
Intent newActivity = new Intent(this, Activity2.class);
newActivity.putExtra("TagID", tag.getId());
startActivity(newActivity);
nfcv.close();
}
} catch (Exception e) {
Log.e("NFC error", e.toString());
Toast.makeText(this, "NFC failed", Toast.LENGTH_SHORT).show();
}
}
Activity 2:
public class Activity2 extends Activity {
private String displayID = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.results);
TextView resultIdView = (TextView) findViewById(R.id.Tag_id);
Bundle extras = getIntent().getExtras();
if(extras !=null)
{
byte[] TagID = extras.getByteArray("TagID");
displayID = toHex(TagID);
resultIdView.setText(displayID);
}
}
}
I have taken the navigation drawer example from http://www.androidhive.info/2013/11/android-sliding-menu-using-navigation-drawer/.
There is a main drawer activity and different fragments, how can i use the activity with these fragments. When i scan nfc tag from activity 1 it will send tag id to activity 2 and display tag id.
Same concept how do use with fragments, like from fragment1 scan tag happens and displays the tag id in fragment 2.
kumar

You should read some basic docs and guides about how to deal with Fragments.
Fragments ahve pretty similar lifecycle callback to Activities, so you should be able to convert your code quickly - according to its complexity.
Briefly. Create an Activity which will server as a container for you fragments (just basic Activity with some simple layout). Then in this Activity use FragmentManager to add your Fragments to it. You can be adding or removing Fragments from you Activities on the fly, or just showing/hiding them, that is completely up to you. Google has some nice examples and guides which should server you well to start.
Communication among Fragments could be once again done with Intents (see getArguments()), custom interfaces, you can use an event Bus (see Otto),...I would start with Intents..

You can pass a Bundle to a fragment.
Bundle b = new Bundle();
b.putExtra("TagID", tag.getId());
FragmentVedioView fv = new FragmentVedioView();
fv.setArguments(b);
SFM.beginTransaction().replace(id, fv, "FragmentVedioView").commit();

Related

Hello! I need some help in updating LIstView in Fragments

How can I update ListView in the other Fragment?
public class ChooseCS extends FragmentActivity {
final private Context context = this;
private HashMap<String, List<String>> mCitiesStreets = null;
private View rootViewStreetChangeFragment = null;
private SimpleAdapter adapter;
...
private static final int NUM_PAGES = 3;
private ViewPager mPager;
private PagerAdapter mPagerAdapter;
...
and two Fragments
public class CityChangeFragment extends Fragment {
and
public class StreetChangeFragment extends Fragment {
...
mMapDataAdapter.put("streets", fillcities);
adapter = new SimpleAdapter(
rootViewStreetChangeFragment.getContext(),
mMapDataAdapter.get("streets"), R.layout.grid_streets_4_7,
from, to);
mDataListViewStreets.setAdapter(adapter);
...
I need make update ListView in StreetChangeFragment from CityChangeFragment where I doing changing data
You can use LocalBroadcastManager to achieve this.
In your StreetChangeFragment write below code
#Override
public void onCreate(Bundle savedInstanceState) {
...
// Register to receive messages.
// We are registering an observer (mMessageReceiver) to receive Intents
// with actions named "custom-event-name".
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("custom-event-name"));
}
// Our handler for received Intents. This will be called whenever an Intent
// with an action named "custom-event-name" is broadcasted.
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Get extra data included in the Intent
String message = intent.getStringExtra("message");
Log.d("receiver", "Got message: " + message);
}
};
#Override
protected void onDestroy() {
// Unregister since the activity is about to be closed.
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
super.onDestroy();
}
And use below method to send broadcast message from CityChangeFragment to StreetChangeFragment
private void sendMessage() {
Log.d("sender", "Broadcasting message");
Intent intent = new Intent("custom-event-name");
// You can also include some extra data.
intent.putExtra("message", "This is my message!");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
Note: You can pass data using intent (here you can position also on which you want to update data in listview)
You can check below link to learn more about LocalBroadcastManager
https://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html
Interface is good idea,The idea is basically to define an interface and let the activity implement that interface.
Once it has implemented that interface, you could do anything you want in the method it overrides.
There is a good tutorial on Simple Developer Blog how to do exactly this kind of thing.
And you need t declare a method in fragment and it can be executed from the activity by getting the fragment instance from adapter like
Fragment fragment= mPagerAdapter.getItem(int positon);
((StreetChangeFragment )).updateList();
in StreetChangeFragment declare method and do what else you want, Thank you

Call a method from an activity to a fragment of another activity. What is the proper way?

This might have already answered but I am still troubling with a function like this. Let's say I have activity A and activity B. B holds a viewpager with several fragments in it. I would like to call a function in the fragment held by activity B from activity A.
I used callbacks many times to communicate between activites and fragments but every single time it was only the fragment and its holder activity. I do not want to make a static method (the callback listener cannot be static anyway) so it causes a headache for me. The simple static solution to make a static method in the fragment and have it called from the other actually works very well, but I am not sure if it was a good idea as I need to change several things static.
So communicating between Activity B and its fragments is ok, but I cannot call this method in Activity A.
Activity B:
public class ActivityB extends FragmentActivity implements Fragment1.OnWhateverListener
{
...
#Override
public void onWhateverSelected(int position) {
//stuff, here I can call any function in Fragment 1
}
}
The following code snippet is a wrong solution (doesnt even work) but makes a better picture what I would like to do.
Activity A:
ActivityB ab = new ActivityB ();
ab.onWhateverSelected(number);
So how can I do this?
Thank you!
EDIT
Activity A: the method I call
Bundle args = new Bundle();
args.putString("ID", id); // the data to send
Intent frag_args = new Intent(Intent.ACTION_VIEW);
frag_args.setClass(this, MainActivity.class);
frag_args.putExtra("args", args);
startActivity(frag_args);
Activity B:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
...
processIntent(getIntent()); //last line of onCreate, always gets called here
}
#Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
processIntent(intent); // this never gets called here only in OnCreate
}
private void processIntent(Intent intent) {
Bundle args = intent.getBundleExtra("args");
if (args != null) { // check if ActivityB is started to pass data to fragments
String id = args.getString("ID");
Log.i("ID_FROM", "id: " + id); //works well
if (id != null) {
List<Fragment> fragments = new ArrayList<Fragment>();
fragments = getSupportFragmentManager().getFragments();
//NULLPOINTER for the following line
FragmentMainDiscover fr = (FragmentMainDiscover) fragments.get(0);
fr.RefreshHoverView(id);
}
}
}
You are right to stay away from statics. Way too risky, for visual objects that may or may not be on screen.
I would recommend going through activity B, since it is the parent of your target fragment. Create an Intent that starts activity B, and include an intent extra that tells activity B what it should do to the target fragment. Then activity B can make sure that the fragment is showing, and pass the information on to it.
One other idea to pass the info to the fragment is to use setArguments, rather than direct calls. This is a nice approach because Android will restore the arguments automatically if the activity and its fragments are removed from memory.
Does this make sense? Do you want the code?
EDIT
To use arguments, you still need to have activity A go through activity B. This is because activity A doesn't know if activity B, and all its fragments, is running unless it sends it an Intent. But you can include data targeted for the fragments, by putting them inside the intent. Like this:
public class ActivityA extends Activity {
public static final String KEY_FRAG = "frag"; // tells activity which fragment gets the args
public static final String KEY_ARGS = "args";
public static final String KEY_MY_PROPERTY = "myProperty";
public void foo() {
Bundle args = new Bundle();
args.putString(KEY_FRAG, "frag1Tag"); // which fragment gets the data
args.putCharSequence(KEY_MY_PROPERTY, "someValue"); // the data to send
// Send data via an Intent, to make sure ActivityB is running
Intent frag_args = new Intent(Intent.ACTION_VIEW);
frag_args.setClass(this, ActivityB.class);
frag_args.putExtra(KEY_ARGS, args);
startActivity(frag_args);
}
}
public class ActivityB extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//TODO configure activity including fragments
processIntent(getIntent()); // this call is in case ActivityB was not yet running
}
#Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
processIntent(intent); // this call is in case ActivityB was already running
}
private void processIntent(Intent intent) {
Bundle args = intent.getBundleExtra(ActivityA.KEY_ARGS);
if (args != null) { // check if ActivityB is started to pass data to fragments
String fragTag = args.getString(ActivityA.KEY_FRAG);
if (fragTag != null) {
Fragment frag = getSupportFragmentManager().findFragmentByTag(fragTag);
frag.setArguments(args);
//TODO either show the fragment, or call a method on it to let it know it has new arguments
}
}
}
}
public class Fragment1 extends Fragment {
public static final String TAG = "frag1Tag";
#Override
public void onResume() {
super.onResume();
Bundle args = getArguments();
String value = args.getString(ActivityA.KEY_MY_PROPERTY);
...
}
}

Call fragment from another fragment after some delay

I searched all over the web, couldn't find a good reference on how to call fragment from another fragment.
Fragment A -> Fragment B (fragment A calls fragment B after 3 seconds)
Well, first of all you need to consider that it's a very bad idea to keep somehow a direct reference from FragmentA to FragmentB. Why:
FragmentB may be recreated and you may keep a reference to an older reference of FragmentB. So you have a memory leak.
FragmentB may be not created, added or visible. So you would have a null/unusable reference.
For this reason you need to consider methods that base on sending messages from FragmentA to FragmentB. I see several options:
Send a broadcast message using a custom action from FragmentA. FragmentB registers itself as a receiver for this kind of message (in onCreate/onResume/onAttach and de-register in onDestroy/onPause/onDetach) and when the message arrives it can handle it. This is very suitable if you have no data to send from FragmentA to FragmentB or if you do these are primitive types or easy-to-implement Parcelables. Here's an example:
Have this in FragmentA:
private void sendMessageToFragmentB(String someData) {
Intent messageIntent = new Intent("com.your_package.A_TO_B_ACTION");
messageIntent.putExtra("DATA_VALUE", someData);
LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(messageIntent);
}
While in FragmentB you could have this:
public class FragmentB extends Fragment {
private BroadcastReceiver messagesFromAReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if ("com.your_package.A_TO_B_ACTION".equals(intent.getAction())) {
String dataFromA = intent.getStringExtra("DATA_VALUE");
dataFromAReceived(dataFromA);
}
}
};
protected void dataFromAReceived(String data) {
// here you have the data
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
IntentFilter messageFromAIntentFilter = new IntentFilter("com.your_package.A_TO_B_ACTION");
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(messagesFromAReceiver,
messageFromAIntentFilter);
}
#Override
public void onDestroy() {
super.onDestroy();
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(messagesFromAReceiver);
}
}
Use the hosting activity as a proxy: The host activity implements some kind of interface defined in FragmentA and when requested it can search if it can find FragmentB and if so call some method in there. The advantage is that you can send any data, no matter its weight. The base idea is descrived in Android dev articles. To exemplify, you could have FragmentA as:
public class FragmentA extends Fragment {
public static interface CallerProxy {
public void sendCustomMessage(Object... dataParams);
}
private CallerProxy proxyActivity;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof CallerProxy) {
this.proxyActivity = (CallerProxy) activity;
}
}
#Override
public void onDetach() {
super.onDetach();
this.proxyActivity = null;
}
private void sendMessageToFragmentB(String someData) {
if (proxyActivity != null) {
// send whatever data
proxyActivity.sendCustomMessage(new Integer(1), new Object());
// or don't send anything ...
proxyActivity.sendCustomMessage();
}
}
}
The proxy activity would have at least these methods and signature:
public class MyProxyActivity extends FragmentActivity implements CallerProxy {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// call setContentView and then make sure you've added FragmentA and
// FragmentB.
}
#Override
public void sendCustomMessage(Object... dataParams) {
// FragmentB must be identified somehow, either by tag,
// either by id. Suppose you'll identify by tag. This means you've added
// it previously with this tag
Fragment fragment = getSupportFragmentManager().findFragmentByTag("FragmentB-TAG");
if (fragment != null) {
FragmentB fragB = (FragmentB) fragment;
fragB.dataFromAReceived(dataParams);
}
}
}
While in FragmentB all you need is a method that can be called with above sent parameters:
public void dataFromAReceived(Object ... data) {
// here you have the data
}
Use or implement some sort of event bus. Some general details here. For Android I remember that Otto event bus was very handy and easy to use. Here's a link with this. This is very similar to first option as you need anyway to register and un-register.
In the end it depends on what you need to send as a message, when should it be received and how flexible does it need to be. ... your choice!
Enjoy programming!
Fragments are not supposed to connect to each other directly, that may be your problem in finding a decent guide to do this.
Your approach makes the assumption that a fragment B will always be reachable (and ready) for a fragment A to interact, and that is actually not true, will kill the flexibility of your Fragment and will cause you problems in the future.
A better approach to interaction of Fragments is to talk only through interfaces that talk directly to a activity that can handle who is alive when where and should receive what.
-> http://developer.android.com/training/basics/fragments/index.html
This Android guide above, specifically on the last topic, shows you how to do this.
i hope this code help you..
in your first fragment add this code
onCreateView
LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(getActivity());
IntentFilter intentFilter = new IntentFilter("update");
// Here you can add additional actions which then would be received by the BroadcastReceiver
broadcastManager.registerReceiver(receiver, intentFilter);
#Override
public void onDestroyView() {
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(receiver);
super.onDestroyView();
}
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action != null && action.equals("update")) {
// perform your update
getOngoingOrderData();
}
}
};
in your second fragment add this code where you send broadcast..
Intent intent = new Intent("update");
LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(getActivity());
broadcastManager.sendBroadcast(intent);

Change tabhost tab title in a different activity

I have a main activity that hold the tabs and each tab start a new activity. May I know how can I change the tab title from the new activity? Thanks.
Although CommonsWare has pointed out that having Activities as Tab content is deprecated, if you still want to do it then one possibility is to use a nested BroadcastReceiver and have the content Activity send a broadcast Intent. I'm not sure if it will work but I would try something like the following...
public class MainActivity extends Activity {
bool tabMonitorIsRegistered = false;
TabMonitor tabMonitor = null;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Other code
tabMonitor = new TabMonitor();
}
#Override
protected void onResume() {
super.onResume();
if (!tabMonitorIsRegistered) {
registerReceiver(tabMonitor, new IntentFilter(Intent.com.mydomain.myapp.ACTION_TAB_CHANGE));
tabMonitorIsRegistered = true;
}
}
#Override
protected void onPause() {
super.onPause();
if (tabMonitorIsRegistered) {
unregisterReceiver(tabMonitor);
tabMonitorIsRegistered = false;
}
}
// Nested BroadcastReceiver
private class TabMonitor extends BroadcastReceiver {
#Override
public void onReceive(Context arg0, Intent arg1) {
// Process the Intent here to change the tab title
}
}
}
At this point it occurs to me that each 'content' Activity will need to tell the MainActivity (via the Intent it sends) 'who' it is. To do this, I would use an Intent extra when adding the tab content Activities identifying each as 'tab1', tab2' etc. When the 'content' Activities start, e.g., in onCreate(), they can store this string and use it in the Intent they send as the broadcast to the MainActivity.

How to reference child activity from TabHost to call a public function?

I have a TabHost with two child activities in it (in two tabs). I also implemented a public function in one of these activities that i would like to call from my parent (TabHost), to trigger some action within the tab.
Is it possible to reference the activity itself from the TabHost to call a public function?
Thanks
here is my tabhost setup:
res = getResources();
tabHost = getTabHost();
TabHost.TabSpec spec;
Intent intent;
intent = new Intent().setClass(this, home.class);
spec = tabHost.newTabSpec("home").setIndicator("Groups", res.getDrawable(R.drawable.groups)).setContent(intent);
tabHost.addTab(spec);
intent = new Intent().setClass(this, messages.class);
spec = tabHost.newTabSpec("messages").setIndicator("Messages", res.getDrawable(R.drawable.messages)).setContent(intent);
tabHost.addTab(spec);
My approach would be to define a nested 'listener' class in the child activity which extends BroadcastReceiver.
I would then simply broadcast an Intent from my TabActivity which would then trigger the BroadcastReceiver to perform the action.
EDIT: To give example code...
The steps are...
Define the intent filter in the manifest
Add the nested 'listener' to the child activity
Set onResume()/onPause() in child activity to register/unregister the listener
Create intent in TabActivity and broadcast it when you want child to do something
In AndroidManifest.xml
<activity
android:name=".MyActivity"
android:label="#string/app_name"
<intent-filter>
<action android:name="com.mycompany.myApp.DO_SOMETHING" />
</intent-filter>
</activity>
In MyActivity.java
public class MyActivity extends Activity {
private MyListener listener = null;
private Boolean MyListenerIsRegistered = false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreated(savedInstanceState);
listener = new MyListener();
}
#Override
protected void onResume() {
super.onResume();
if (!MyListenerIsRegistered) {
registerReceiver(listener, new IntentFilter("com.mycompany.myApp.DO_SOMETHING"));
MyListenerIsRegisterd = true;
}
}
#Override
protected void onPause() {
super.onPause();
if (MyListenerIsRegistered) {
unregisterReceiver(listener);
MyListenerIsRegistered = false;
}
}
// Nested 'listener'
protected class MyListener extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// No need to check for the action unless the listener will
// will handle more than one - let's do it anyway
if (intent.getAction().equals("com.mycompany.myApp.DO_SOMETHING")) {
// Do something
}
}
}
}
In the main TabActivity
private void MakeChildDoSomething() {
Intent i = new Intent();
i.setAction("com.mycompany.myApp.DO_SOMETHING");
sendBroadcast(i);
}
I've found another, probably simpler solution. I'm sure OP doesn't need this any more, but maybe someone from the future will be glad to find it.
So, basically, to run a public method in your child activity, you just need this little piece of code in your parent (tabHost, home and message are taken from OP's TabHost configuration):
tabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
#Override
public void onTabChanged(String tabId) {
Activity currentActivity = getCurrentActivity();
if (currentActivity instanceof home) {
((home) currentActivity).aPublicMethodFromClassHome();
}
if (currentActivity instanceof messages) {
((messages) currentActivity).aPublicMethodFromClassMessages();
}
}
});
I use it in my application. Works as a charm;)
I'm currently debugging an Android application and came across the same need. I found a much straightforward answer to this with this code snippet :
String currentActivityId = getLocalActivityManager().getCurrentId();
Activity currentActivity = getLocalActivityManager().getActivity(currentActivityId);
The identifier here is the identifier given when creating the TabSpec :
tabHost.newTabSpec("id").setIndicator(indicator).setContent(intent);
Thank you, this helped me to solve a simular problem!
Activity currentActivity = getLocalActivityManager().getActivity(_TabHost.getCurrentTabTag());
if(currentActivity != null && currentActivity instanceof iMyActivity)
{
// pass to children
((iMyActivity)currentActivity).onLaunchDelegate();
}
From this link, I found this simple solution (http://androidactivity.wordpress.com/2012/08/17/two-way-communication-between-tabactivity-and-its-child-tabs/):
Well, the trick is to store the TAG associated with each tab, and use it to call the respective activity.
When you create the tab, you associate it with a tag like following:
yourTabHost.newTabSpec("Tab1");
Lets say we want to invoke a method “refreshContent()” that is inside the Tab1 Activity.
It’s simple as calling these lines from the MainActivity:
ActivityTab1 activity = (ActivityTab1) getLocalActivityManager().getActivity("Tab1");
activity.refreshContent();
And that’s it!
Now for the opposite direction, we want to call some method “updateMain()” inside MainActivity, from the child tab TabActivity1.
At the TabActivity1 you will only need to call
((MainActivity)getParent()).updateMain();
find it simple, use it in app ActivityTab class:
if(getCurrentActivity() instanceof YourSearchActivity){
log("onClick: instance found");
((YourSearchActivity)getCurrentActivity()).activityPublicFuntion();
}

Categories

Resources