Why do i always get error when i try to call AlertDialog from my fragment?
At first i try to put it in OnCreate but it also get the same error log...
MainFragment.java
public class MainFragment extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_fragment);
if (savedInstanceState == null) {
FragmentTransaction ft = getFragmentManager().beginTransaction();
LoginFragment fragment = new LoginFragment();
ft.add(R.id.simple_fragment, fragment).commit();
}
}
}
LoginFragment.java
public class LoginFragment extends Fragment implements OnClickListener {
Helper application;
static LoginFragment newInstance() {
LoginFragment f = new LoginFragment();
Bundle args = new Bundle();
f.setArguments(args);
return f;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
AlertDialog.Builder dlgAlert = new AlertDialog.Builder(getActivity().getApplicationContext());
dlgAlert.setMessage("TEST");
dlgAlert.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.dismiss();
}
});
dlgAlert.setCancelable(false);
dlgAlert.create().show();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.activity_login, container, false);
Button inner = (Button) v.findViewById(R.id.btnSignUp);
inner.setOnClickListener(LoginFragment.this);
return v;
}
#Override
public void onClick(View v) {
}
}
and this is the error log
12-19 10:14:25.295: E/AndroidRuntime(1083): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.myfirstapp/com.example.fragment.MainFragment}: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
anyone has ever encountered this before?
Just try
AlertDialog.Builder dlgAlert = new AlertDialog.Builder(getActivity());
If you are dealing with nested fragments. When a fragment has it's own child fragments you need to use getChildFragmentManager().
Related
frag1 calls frag 2 and frag 2 calls a method in frag1 that updates a textview. The code works (doesn't crash) but the frag1 UI (when I return from frag2) is not updated/
Is it a valid approach? Is there a way to update the UI?
here is the frag1 and frag2 code:
public class Frag1 extends android.app.Fragment {
private static TextView txt;
public Frag1() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootview = null;
rootview = inflater.inflate(R.layout.fragment_frag1, container, false);
return rootview;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
txt = (TextView) getActivity().findViewById(R.id.txt);
Button btn = (Button) getActivity().findViewById(R.id.btn1);
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
FragmentTransaction ft = getFragmentManager().beginTransaction();
Frag2 f2 = new Frag2();
ft.replace(R.id.content_frame, f2);
ft.addToBackStack(null);
ft.commit();
}
});
}
void setTxt(String s){
txt.setText(s);
}
}
and frag2 - the setTxt() method updates the textview in frag1:
public class Frag2 extends Fragment {
private Button btn2;
public Frag2() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootview;
rootview = inflater.inflate(R.layout.fragment_frag2, container, false);
Log.i("frag2","createdview");
return rootview;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Frag1 f1 = new Frag1();
f1.setTxt("msg from frag2");
btn2 = (Button) getActivity().findViewById(R.id.btn2);
btn2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
FragmentTransaction ft = getFragmentManager().beginTransaction();
Frag3 f3 = new Frag3();
ft.replace(R.id.content_frame, f3);
ft.addToBackStack(null);
ft.commit();
}
});
}
}
You can Broadcast Intent from the frag2
Intent intent = new Intent("key_to_identify_the_broadcast");
Bundle bundle = new Bundle();
bundle.putString("edttext", json.toString());
intent.putExtra("bundle_key_for_intent", bundle);
context.sendBroadcast(intent);
and then you can receive the bundle in your frag 1 by using the BroadcastReceiver class
private final BroadcastReceiver mHandleMessageReceiver = new
BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle =
intent.getExtras().getBundle("bundle_key_for_intent");
if(bundle!=null){
String edttext = bundle.getString("edttext");
}
//you can call any of your methods for using this bundle for your use case
}
};
in onCreateView() of your fragment you need to register the broadcast receiver first otherwise this broadcast receiver will not be triggered
IntentFilter filter = new IntentFilter("key_to_identify_the_broadcast");
getActivity().getApplicationContext().
registerReceiver(mHandleMessageReceiver, filter);
Finally you can unregister the receiver to avoid any exceptions
#Override
public void onDestroy() {
try {
getActivity().getApplicationContext().
unregisterReceiver(mHandleMessageReceiver);
} catch (Exception e) {
Log.e("UnRegister Error", "> " + e.getMessage());
}
super.onDestroy();
}
You can create separate broadcast receivers in all of your fragments and use the same broadcast to broadcast the data to all of your fragments. You can also use different keys for different fragments and then broadcast using particular key for particular fragment.
I have a MainActivity and a HomeTabs with three tabs (A B C), i set a refresh on tab C .
My structure is when i trigger onRefresh on tab C , i will switch to MainActivity
and load the data again to show the HomeTabs.
My problem is when i click back for finish(); , the layout will show tab C.
I try to finish the Fragment use like:
getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();
or
((MainActivity)getActivity()).removeFragment(getActivity());
Both of them are no working , when i click back , i still can't finish the app immediately.
Some one can teach me what step i miss it , that would be appreciated.
My HomeTabs extends Fragment it use ViewPager and TabLayout add three tabs
MainActivity:
public class MainActivity extends AppCompatActivity {
private FrameLayout frameLayout;
private Toolbar toolBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
frameLayout = (FrameLayout) findViewById(R.id.frameLayout);
// Load the main Fragment
if (savedInstanceState == null) {
switchFragment(HomeTabs.newInstance());
}
//take the onRefresh dataļ¼send data to HomeTabs and open tab C
if (getIntent().hasExtra("refresh")) {
boolean isRefresh = getIntent().getExtras().getBoolean("refresh");
if (isRefresh) {
Bundle bundle = new Bundle();
bundle.putBoolean("refresh", isRefresh);
HomeTabs homeTabs = new HomeTabs();
homeTabs.setArguments(bundle);
switchFragment(homeTabs);
}
}
}
public void switchFragment(Fragment fragment) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.frameLayout, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
// I try to finsh my tab C , it's no working
public void removeFragment(Activity activity) {
activity.onBackPressed();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
new DialogHandler(this).quickDialog(
getResources().getString(R.string.quick),
getResources().getString(R.string.confirm),
getResources().getString(R.string.cancel),
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// If i onRefrsh three times , i will finsh three times... here is my issue.
finish();
}
}, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
}
return super.onKeyDown(keyCode, event);
}
}
Here is my tab C Fragment refresh call back method:
public class MyLineChart extends Fragment implements SwipeRefreshLayout.OnRefreshListener{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_my_line_chart, container, false);
//.....................
return view;
}
#Override
public void onRefresh() {
refreshLayout.setRefreshing(false);
// Both of them are no working.
//((MainActivity)getActivity()).removeFragment(getActivity());
//getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();
Intent intent = new Intent(getActivity(),MainActivity.class);
intent.putExtra("refresh", true);
startActivity(intent);
}
Finally my HomeTabs Fragment take the date and show tab C:
Bundle bundle = getArguments();
if (bundle != null) {
boolean isRefresh = bundle.getBoolean("refresh");
if (isRefresh) {
//tab C position is 2
tabLayout.getTabAt(2).select();
}
}
Try this solution to add below code when you are starting activity again on Refresh click:-
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
OR
Update your MainActivity.java
1) Add function in MainActivity
public void refreshFragment() {
Bundle bundle = new Bundle();
bundle.putBoolean("refresh", isRefresh);
HomeTabs homeTabs = new HomeTabs();
homeTabs.setArguments(bundle);
switchFragment(homeTabs);
}
Now Call that from Fragment Tab C just replacing startActivity(refresh) code:
MainActivity mainActivity = (MainActivity) getActivity();
mainActivity.refreshFragment();
you can add a listener in your fragment that can trigger a function in your parent activity
which means you need to add an interface in your fragmentC code
public class MyLineChart extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private MyLineChartListener fragmentListener;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_my_line_chart, container, false);
//.....................
return view;
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof MyLineChartListener) {
fragmentListener = (MyLineChartListener) context;
} else {
// throw an error
}
}
#Override
public void onRefresh() {
refreshLayout.setRefreshing(false);
// Both of them are no working.
//((MainActivity)getActivity()).removeFragment(getActivity());
//getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();
fragmentListener.onSettingRefresh();
}
public interface MyLineChartListener {
void onSettingRefresh();
}
}
then you need to implement the listener in the MainActivity code as follows
public class MainActivity extends AppCompatActivity implements MyLineChart.MyLineChartListener {
private FrameLayout frameLayout;
private Toolbar toolBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
frameLayout = (FrameLayout) findViewById(R.id.frameLayout);
// Load the main Fragment
if (savedInstanceState == null) {
switchFragment(HomeTabs.newInstance());
}
}
public void switchFragment(Fragment fragment) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.frameLayout, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
// I try to finsh my tab C , it's no working
public void removeFragment(Activity activity) {
activity.onBackPressed();
}
// this function will be called when the fragment is refreshed
#Override
public void onSettingRefresh() {
Bundle bundle = new Bundle();
bundle.putBoolean("refresh", true);
HomeTabs homeTabs = new HomeTabs();
homeTabs.setArguments(bundle);
switchFragment(homeTabs);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
new DialogHandler(this).quickDialog(
getResources().getString(R.string.quick),
getResources().getString(R.string.confirm),
getResources().getString(R.string.cancel),
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// If i onRefrsh three times , i will finsh three times... here is my issue.
finish();
}
}, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
}
return super.onKeyDown(keyCode, event);
}
}
I have an activity "MainActivity" that contains two fragments. Fragment1 has a EditText and a button. When the user presses the button the text inside the EditText will be sent to Fragment2 which only has a TextView. But I can't quite figureout how to send the text from EditText in Fragment1 to TextView in Fragment2. If someone could help? Appreciated. Thanks
Fragment1
package org.pctechtips.myfragmentapp;
/**
* Created by george on 5/16/17.
*/
public class ButtonFragment extends Fragment {
Button bt;
EditText editText;
TextView txtView;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.button_fragment,
container, false);
txtView = (TextView) view.findViewById(R.id.textView_fragment1);
editText = (EditText) view.findViewById(R.id.editText_fragment1);
bt = (Button) view.findViewById(R.id.button_fragment1);
bt.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
buttonClicked(v);
}
});
return view;
}
public void buttonClicked (View view) {
.onButtonClick(edittext.getText().toString());
}
}
MainActivity
package org.pctechtips.myfragmentapp;
public class MainActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*fragments 1 section*/
FragmentManager fm1 = getFragmentManager();
FragmentTransaction ft1 = fm1.beginTransaction();
ButtonFragment bf = new ButtonFragment();
ft1.add(R.id.button_fragment1, bf);
ft1.commit();
/*Fragment 2 section*/
FragmentManager fm2 = getFragmentManager();
FragmentTransaction ft2 = fm2.beginTransaction();
TextviewFragment tf = new TextviewFragment();
ft2.add(R.id.textView_fragment2, tf);
ft2.commit();
}
}
Fragment2
public class TextviewFragment extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.text_fragment, container, false);
}
}
The quick and easy answer is to call getView().findViewById() from the activity (as shown below). The more proper approach is to give your fragments an interface that gets and retrieves the text. Below is the code for the quick and easy method, but when you create a fragment in Android studio it shows you how to do the more proper interface approach.
package org.pctechtips.myfragmentapp;
public class MainActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*fragments 1 section*/
FragmentManager fm1 = getFragmentManager();
FragmentTransaction ft1 = fm1.beginTransaction();
ButtonFragment bf = new ButtonFragment();
ft1.add(R.id.button_fragment1, bf);
ft1.commit();
/*Fragment 2 section*/
FragmentManager fm2 = getFragmentManager();
FragmentTransaction ft2 = fm2.beginTransaction();
TextviewFragment tf = new TextviewFragment();
ft2.add(R.id.textView_fragment2, tf);
ft2.commit();
EditText et = (EditText) ft1.getView().findViewById(YOUR_EDITTEXT_ID);
Button button = (Button) ft1.getView().findViewById(YOUR_BUTTON_ID);
TextView tv = (TextView) ft2.getView().findViewById(YOUR_TEXTVIEW_ID);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
tv.setText(et.getText();)
}
});
}
You can do it by several ways. For example via Activity like in Official Docs. But, I'm prefer send broadcast messages via LocalBroadcastManager like in this answer of war_Hero:
In Sending Fragment(Fragment B - Your ButtonFragment)
public class FragmentB {
private void sendMessage() {
Intent intent = new Intent("custom-event-name");
intent.putExtra("message", "your message");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
And in the Message to be Received Fragment(FRAGMENT A - Your TextviewFragment)
public class FragmentA {
#Override
public void onCreate(Bundle savedInstanceState) {
...
// Register receiver
LocalBroadcastManager.getInstance(this).registerReceiver(receiver,
new IntentFilter("custom-event-name"));
}
// This will be called whenever an Intent with an action named "custom-event-name" is broadcasted.
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String message = intent.getStringExtra("message");
}
};
}
And don't forget to unregister receiver:
protected void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
}
I have an Activity1 that shows a custom dialogfragment- ExampleDialog. I have implemented a listener, SubmitDialogListener for the dialogfragment to communicate with the activity using onSubmit(). In onSubmit(), I am showing some other dialogfragment. My question is, if I show the same ExampleDialog Fragment from Activity2, should Activity2 implement the SubmitDialogListener interface and implement the onSubmit() method in Activity2 again? Or is there a better way to define the onSubmit() method?
import android.support.v4.app.DialogFragment;
// ...
public class Activity1 extends ActionBarActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
......
showDialog();
}
private void showDialog() {
FragmentManager fm = getSupportFragmentManager();
ExampleDialog exDialog = ExampleDialog.newInstance("Some Title");
exDialog.show(fm, "fragment_edit_name");
}
#Override
public void onSubmit() {
//open new fragments
}
}
public class ExampleDialog extends DialogFragment implements SubmitDialogListener {
public interface SubmitDialogListener {
void onSubmit();
}
public ExampleDialog() {
// Empty constructor required for DialogFragment
}
public static ExampleDialog newInstance(String title) {
ExampleDialog frag = new ExampleDialog();
Bundle args = new Bundle();
args.putString("title", title);
frag.setArguments(args);
return frag;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_edit_name, container);
.........
Button button = (Button) v.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
SubmitDialogListener listener = (SubmitDialogListener) getActivity();
listener.onSubmit();
dismiss();
}
});
return view;
}
}
In this case the Activity should implement the SubmitDialogListener not the Dialog Fragment, like this:
public class Activity1 extends ActionBarActivity implements SubmitDialogListener {
#Override
public void onSubmit() {
//open new fragments
}
}
And if you want to use the same dialog fragment in multiple activities, it's generally best to create it in a separate class file.
I want to know how to stop running thread and asyncTask of fragment safely on android.
here is my code:
public class MainActivity extends FragmentActivity {
public Fragment mFragment;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
Button btn_next = (Button) findViewById(R.id.button_next);
btn_next.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
((FragmentOne)mFragment).infoThread.interrupt();
}
});
Intent intent = getIntent();
String start_fragment = intent.getStringExtra("start_fragment");
onShowFragment(start_fragment);
}
public void onShowFragment(String select_fragment) {
Fragment fr = null;
switch (select_fragment) {
case "fragment1":
fr = new FragmentOne();
break;
case "gragment2":
fr = new FragmentTwo();
break;
}
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.fragment_place, fr);
ft.commit();
}
}
public class FragmentOne extends Fragment {
public Thread infoThread;
public View view_one;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view_one = inflater.inflate(R.layout.fragment_one, container, false);
onGetInfo();
return view_one;
}
public void onGetInfo() {
infoThread= new Thread(new Runnable() {
#Override
public void run() {
String response_info = HTTPUtils.HTTPPost(Global.USER_URL,
"name", "abc",
"password", "1234");
processGetInfo(response_info);
}
});
infoThread.start();
}
}
in here, when click btn_next button, FATAL EXCEPTION ERROR occur.
please help me.
try to use:
infoThread.stop()
instead of:
infoThread.interrupt();
You are never initialising mFragment with a value.
Add mFragment = fr; to onShowFragment
But, you're going to have a whole load of different issues if you carry on down this path. You should consider a more robust framework than performing http requests in threads spawned from a Fragment's onCreateView method.