I want to show the same dialog in different activities. I tried to make a BaseActivitiy. The Activities extends my BaseActivity. That worked so far, but now I want to update the Activity which shows the dialog when the dialog is closed. Update means in my case to fill a listview with data from a SQLite database.
I also tried to retrieve the classname to use the update method of those activities. But it is not possible to change the update method to static, because of the non-static SQL methods...
Do you have any idea?
Activity:
public class MyActivity extends Dialogs {
...
#Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
int idx = info.position;
switch (item.getItemId()) {
case CONTEXTMENU_ID:
showMyDialog(this,DIALOG_ID);
break;
}
return true;
}
public void update() {
...
}
}
DialogsClass
public class Dialogs extends Activity {
#Override
protected Dialog onCreateDialog(int id) {
...
}
...
//Called on Dialog-Butten press
private void ReloadActivity(){
if(DialogCalledByClass.contains("MyActivity")) {
MyActivity.update();// It doesn't worke because non-static....
}
else if(DialogCalledByClass.contains("MyActivity2")) {
}
}
public void showMyDialog(Context ctx,int id) {
showDialog(id);
DialogCalledByClass =ctx.getClass().toString();
}
}
That's what I have tried...
For example... Instead of create a BaseActivity you could create your own Dialog:
class myDialog extends AlertDialog {
Activity myActivity;
public myDialog(Activity myAct){
myActivity=myAct;
}
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.my_dialog);
...
...
}
#Override
public void dismiss(){
myActivity.update();
}
#Override
public void cancel(){
myActivity.update();
}
}
I don't know if I've understood your question, but it's an idea. I hope it help you.
I found a Solution. Thanks to you David!! Sry I couldn't vote up because to less reputation...
private void ReloadActivity(){
if(DialogCalledByClass.contains("MyActivity")){
try {
Method m = DialogActivity.getClass().getMethod("Update");
try {
m.invoke(DialogActivity);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} catch (SecurityException e) {
error.d(TAG, "SecurityException"+ e);
e.printStackTrace();
} catch (NoSuchMethodException e) {
Log.d(TAG, "NoSuchMethodException"+ e);
}
}
else if(DialogCalledByClass.contains("MyActivity2")){
}
}
public void showMyDialog(Activity act,int id){
showDialog(id);
DialogCalledByClass = act.getClass().toString();
DialogActivity = act;
}
Related
I created a TabLayout with one MainActivity and two fragments in Android.
But how do you get the second Fragment to receive the button event and call the first Fragment function?
I tried the following but it does not work and I ask.
public interface CustomSearchPOI {
void requestSearch(String query);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
customSearchPOI = (CustomSearchPOI)context;
} catch (ClassCastException ex) {
throw new ClassCastException(context.toString() + "must implement CustomSearchPOI");
}
}
Second Fragment Code
if(info_cursor != null) {
info_cursor.moveToFirst();
while(!info_cursor.isAfterLast()) {
if(info_cursor.getInt(0) == id) {
out_subject.setText(info_cursor.getString(1));
out_college.setText(info_cursor.getString(2));
out_classroom.setText(info_cursor.getString(3));
break;
}
info_cursor.moveToNext();
}
}
choice_dialog.setPositiveButton(getString(R.string.Location_navigate), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
TabsFragment.viewPager.setCurrentItem(0);
customSearchPOI.requestSearch(out_college.getText().toString());
}
});
choice_dialog.setNegativeButton(getString(R.string.tt_modify), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
update_timetable_dialog(id);
}
});
choice_dialog.show();
Call function Code
#Override
public void requestSearch(String query) {
String FRAGMENT_TAG = "LOCATION_TAG";
Fragment fragment = new MapFragment();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(fragment, FRAGMENT_TAG).commitAllowingStateLoss();
try {
((MapFragment)getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG)).searchPOI(query);
} catch(NullPointerException ex) {
ex.printStackTrace();
Log.d("[TAG]", fragment.getTag());
}
}
MainActivity Code
public void searchPOI(String query) {
query = Searchcheck(query);
TMapData data = new TMapData();
if(!TextUtils.isEmpty(query)) {
data.findAllPOI(query, new TMapData.FindAllPOIListenerCallback() {
#Override
public void onFindAllPOI(final ArrayList<TMapPOIItem> arrayList) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
tMapView.removeAllMarkerItem();
for (TMapPOIItem poi : arrayList) {
addMarker(poi);
}
if(arrayList.size() > 0) {
TMapPOIItem poi = arrayList.get(0);
moveMap(poi.getPOIPoint().getLatitude(), poi.getPOIPoint().getLongitude());
if(poi.getPOIPoint().getLatitude() > 36.832311 && poi.getPOIPoint().getLongitude() < 127.165038) {
Snackbar.make(coordinatorLayout, getString(R.string.No_place), Snackbar.LENGTH_LONG).show();
if(location_me.getVisibility() != View.INVISIBLE) {
location_me.hide();
}
return;
}
dst = new TMapPoint(poi.getPOIPoint().getLatitude(), poi.getPOIPoint().getLongitude());
searchRoute(src, dst);
}
}
});
}
});
}
}
First Fragment Code (function to call)
According to the Google development documentation, direct communication between fragments and fragments is impossible.
So when I try to call Fragment function from Fragment through Activity, I get NullPointerException error.
I used the try catch syntax to see if there was an error in the tag name or an error in the query, but neither of them was a problem.
FragmentX:
public class MyFragment extends Fragment{
interface MyInterface{
void doSomething();
}
public void someMethodInYourFragment(){
((MyInterface)getContext()).doSomething();//throws ClassCastException if not implemented in Activity
}
}
Class X:
public class MyActivity extends Activity implements MyFragment.MyInterface{
#Override
public void doSomething(){
//do stuff here
}
}
Hi I just created app for loading data from the website once the button is clicked in android.I want to change the app for loading data when the application open.How will I do it?
Here is my code..
public class PrimaryActivity extends Activity {
private static final String URL = "http://livechennai.com/powershutdown_news_chennai.asp";
ProgressDialog mProgressDialog;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_primary);
Button btnFetchData = (Button) findViewById(R.id.btnData);
btnFetchData.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
new FetchWebsiteData().execute();
}
});
}
private class FetchWebsiteData extends AsyncTask<Void, Void, String[]> {
String websiteTitle, websiteDescription,websiteDescription1,websiteDescription2,websiteDescription3,listValue,listValue1;
ProgressDialog progress;
#Override
protected void onPreExecute() {
super.onPreExecute();
//some code here
}
#Override
protected String[] doInBackground(Void... params) {
ArrayList<String> hrefs=new ArrayList<String>();
try {
// parsing here
}
} catch (IOException e) {
e.printStackTrace();
}
//get the array list values
for(String s:hrefs)
{
//website data
}
//parsing first URL
} catch (IOException e) {
e.printStackTrace();
}
//parsing second URL
} catch (IOException e) {
e.printStackTrace();
}
try{
List<String> listString = new ArrayList<String>(Arrays.asList(resultArray));
listString.addAll(Arrays.asList(resultArray1));
String [] outResult= new String[listString.size()];
int i=0;
for(String str: listString){
outResult[i]=str;
i++;
}
return outResult;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String[] result) {
ListView list=(ListView)findViewById(R.id.listShow);
ArrayAdapter<String> arrayAdapter=new ArrayAdapter<String>(getBaseContext(),android.R.layout.simple_list_item_1,result);
list.setAdapter(arrayAdapter);
mProgressDialog.dismiss();
}
}
}
How to load the list view when we open the app? help me to get the exact answer?
Just load it in onCreate. This is what will be called when the app is opened first. Then read about other events like onResume.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_primary);
new FetchWebsiteData().execute();
}
Call FetchWebsiteData().execute() from one of the activity lifecycle methods such as onStart, onCreate, or onResume - please refer to docs to determine which fits in your case.
Put the method which does the fetching i.e. new FetchWebsiteData().execute(); outside of the code of button click and in the activity.onResume() method.
onResume is called everytime an app comes to foreground, if you put it oncreate(), the method will be called only when the activity is created.
Can somebody answer this question for me:
For testing purposes I have created an activity with a for loop in which I'm creating 10 AlertDialogs or 10 DialogFragments.
Immediately after the activity is started I'm pressing the home button to send the app in the background.
If I'm running the showDialog() method to create the DialogFragments the app will crash with:
IllegalStateException: Can not perform this action after onSaveInstanceState
this is expected behavior.
But if I run the showAlert() method to create the AlertDialogs and same as before I'm sending the app to the background the app doesn't crash. When I return to the activity I can see all 10 AlertDialogs.
The question is why does the activity state loss happen with DialogFragment and not with AlertDialog?
I am still changing the UI after the activity's state has been saved. The platform on which I have tested is Android 4.4.2
public class Main extends FragmentActivity
{
private FragmentActivity activity = this;
private MyAsynk myAsynk;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_main);
myAsynk = new MyAsynk();
myAsynk.execute();
}
private class MyAsynk extends AsyncTask<Void, Void, Void>
{
private boolean run = false;
public MyAsynk()
{
run = true;
}
#Override
protected Void doInBackground(Void... params)
{
for(int i = 0; i < 10 && run; i++)
{
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
// showAlert("loop " + i);
showDialog("loop " + i);
}
return null;
}
public void stop()
{
run = false;
}
}
#Override
public void onBackPressed()
{
super.onBackPressed();
if(null != myAsynk)
{
myAsynk.stop();
myAsynk = null;
}
}
private void showAlert(final String txt)
{
try
{
Main.this.runOnUiThread(new Runnable()
{
#Override
public void run()
{
new AlertDialog.Builder(activity).setMessage(txt)
.setPositiveButton("Ok", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
try
{
if(null != dialog)
{
dialog.dismiss();
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
})
.show();
}
});
}
catch(Exception e)
{
e.printStackTrace();
}
}
private void showDialog(final String txt)
{
try
{
Main.this.runOnUiThread(new Runnable()
{
#Override
public void run()
{
MyDialogFragment newFragment = MyDialogFragment.newInstance(txt);
FragmentTransaction ft = Main.this.getSupportFragmentManager().beginTransaction();
newFragment.show(ft, "newFragment");
}
});
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
MyDialogFragment.java :
public class MyDialogFragment extends DialogFragment
{
private MyDialogFragment instance;
public static MyDialogFragment newInstance(String text)
{
MyDialogFragment f = new MyDialogFragment();
Bundle args = new Bundle();
args.putString("text", text);
f.setArguments(args);
return f;
}
public MyDialogFragment()
{
instance = this;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View v = inflater.inflate(R.layout.my_dialog_fragment, container, false);
TextView tv = (TextView) v.findViewById(R.id.tv);
Button bu = (Button) v.findViewById(R.id.bu);
bu.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
try
{
if(null != instance && instance.isVisible())
{
instance.dismiss();
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
});
tv.setText(getArguments().getString("text"));
return v;
}
}
The answer is very simple, though a bit underwhelming.
The oft-seen java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState exception is actually thrown by the FragmentManager class. The reason why is explained very well in this post by Alex Lockwood.
DialogFragments are Fragments (and thus managed by FragmentManager). Therefore, showing dialogs in this way can provoke the exception. However, the implementation of AlertDialog is completely different: it doesn't use Fragments at all (indeed, it actually predates Fragments). Hence, no exceptions.
First time if I run my application then the control goes to onPostExecute() after doinBackground() is complete .But if I re run the application on the device without uninstalling then onPostExecute() is never executed.
I have an activity from where I am calling my asynTask .
CODE:
public class AddThing extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
try {
Class.forName("android.os.AsyncTask");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
private View.OnClickListener onSave = new View.OnClickListener() {
startAddThingType2Task();
}
}
private class ThingCallback implements ActionCallback {
Context cntxt;
public ThingCallback(Context context) {
// TODO Auto-generated constructor stub
this.cntxt = context;
}
public void onSuccess(ArrayList<?> objects) {
setProgressBarIndeterminate(false);
Intent intent = new Intent(getApplicationContext(),DocketDetail.class);
startActivityForResult(intent, 1);
}
public void onFailure(Exception exception) {
Toast.makeText(cntxt, "Unable to add docket. Error is: "+ exception.getMessage(), Toast.LENGTH_LONG).show();
}
}
private void startAddThingType2Task() {
final AddThingType2 task = new AddThingType2(AddThing.this,new ThingCallback(this));
runOnUiThread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
task.execute();
}
});
}
My asyncTask Class is:
public class AddThingType2Task2 extends AsyncTask<Void, Void, Boolean> {
public ActionCallback callback = null;
private Context context;
private Exception ePriv = null;
private Activity activity;
public AddThingType2(Activity activity,ActionCallback callback, ) {
this.callback = callback;
this.context = context;
this.activity = activity;
}
#Override
protected void onPostExecute(Boolean result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
if (result == true) {
callback.onSuccess(null);
} else {
callback.onFailure(ePriv);
}
}
#Override
protected Boolean doInBackground(Void... params) {
// TODO Auto-generated method stub
Boolean retval = false;
try {
retval = true;
}
} catch (Exception e) {
Log.e("AddThingType2Task", e.getMessage());
ePriv = e;
}
return retval;
}
}
ActionCallback interface has two methods - onSuccess() and OnFailure() in it.
Edit
I'm using commonsware wakeful intent service also in my application .
For the first time its working like charm but on re-run onpostExecute() not working...
Please help !!
Regards
Upon re-run i am getting this in logcat :
09-20 17:37:28.515: W/MessageQueue(9311): Handler{4060df08} sending message to a Handler on a dead thread
09-20 17:37:28.515: W/MessageQueue(9311): java.lang.RuntimeException: Handler{4060df08} sending message to a Handler on a dead thread
09-20 17:37:28.515: W/MessageQueue(9311): at android.os.MessageQueue.enqueueMessage(MessageQueue.java:196)
09-20 17:37:28.515: W/MessageQueue(9311): at android.os.Handler.sendMessageAtTime(Handler.java:457)
09-20 17:37:28.515: W/MessageQueue(9311): at android.os.Handler.sendMessageDelayed(Handler.java:430)
09-20 17:37:28.515: W/MessageQueue(9311): at android.os.Handler.sendMessage(Handler.java:367)
09-20 17:37:28.515: W/MessageQueue(9311): at android.location.LocationManager$ListenerTransport.onStatusChanged(LocationManager.java:206)
09-20 17:37:28.515: W/MessageQueue(9311): at android.location.ILocationListener$Stub.onTransact(ILocationListener.java:75)
09-20 17:37:28.515: W/MessageQueue(9311): at android.os.Binder.execTransact(Binder.java:320)
09-20 17:37:28.515: W/MessageQueue(9311): at dalvik.system.NativeStart.run(Native Method)
public class AddThing extends Activity {
private ThingCallback callback;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ThingCallback = new ThingCallback(this);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
try {
Class.forName("android.os.AsyncTask");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
private View.OnClickListener onSave = new View.OnClickListener() {
startAddThingType2Task();
}
}
private class ThingCallback implements ActionCallback {
Context cntxt;
public ThingCallback(Context context) {
this.cntxt = context;
}
public void onSuccess(ArrayList<?> objects) {
setProgressBarIndeterminate(false);
Intent intent = new Intent(getApplicationContext(),DocketDetail.class);
startActivityForResult(intent, 1);
}
public void onFailure(Exception exception) {
Toast.makeText(cntxt, "Unable to add docket. Error is: "+ exception.getMessage(), Toast.LENGTH_LONG).show();
}
}
private void startAddThingType2Task() {
final AddThingType2 task = new AddThingType2(AddThing.this, callback);
task.execute();
}
Are you using any other Thread then the AsyncTask? If not there is no need to use runOnUiThread. Remove it and don't make the AsyncTask reference final. An AsyncTask can never be executed twice, that's why you have to instantiate it new everytime you use it again. The final keyword will prevent a new instantiation and makes the reference immutable.
private void startAddThingType2Task() {
AddThingType2 task = new AddThingType2(AddThing.this,new ThingCallback(this));
task.execute();
}
If you need the runOnUiThread, consider to declare the AsyncTask instance as a field. That way you don't have to make it final to use it in runOnUiThread.
Edit:
You would have something like this:
public class AddThing extends Activity {
// Your field
AddThingType2 task;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
try {
Class.forName("android.os.AsyncTask");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
private View.OnClickListener onSave = new View.OnClickListener() {
startAddThingType2Task();
}
private void startAddThingType2Task() {
// no final needed and you can instantiate it multiple times
task = new AddThingType2(AddThing.this, callback);
task.execute();
}
}
put this class loading in application's onCreate
public class MyApplication extends android.app.Application{
public void onCreate(){
try {
Class.forName("android.os.AsyncTask");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
I programmed an quiz-app and if I touch one of the answers in an AsyncTask if the answer is correct I set the color to green or if it is false to red.
But now during the time the AsyncTask runs I can press other buttons like the "change question" button or on another one of the answers. This is then done after the AsyncTask has finished it's work. So the next question is loaded and it automatically answers the next question or uses one of the jokers what ever.
I tried to setEnabled(false) the Buttons but they are still bugging.
How do I prevent this?
private void disableOrDisableButtons(boolean boo) {
buttonAnswer1.setEnabled(boo);
buttonAnswer2.setEnabled(boo);
buttonAnswer3.setEnabled(boo);
buttonAnswer4.setEnabled(boo);
}
and here I start the AsyncTask
disableOrDisableButtons(false);
new PrepareAdapter().execute(null, null, null);
in my AsyncTask
#Override
protected void onPreExecute() {
disableOrDisableButtons(false);
if (correctAnswerAtButton != buttonClicked) {
switch (buttonClicked) {
case 1:
buttonAnswer1.setTextColor(Color.RED);
break;
case 2:
buttonAnswer2.setTextColor(Color.RED);
break;
case 3:
buttonAnswer3.setTextColor(Color.RED);
break;
case 4:
buttonAnswer4.setTextColor(Color.RED);
break;
}
if (buttonClicked != 0) { // 0.. if second chance joker used
wrongAnswer = true;
}
}
switch (correctAnswerAtButton) {
case 1:
buttonAnswer1.setTextColor(Color.GREEN);
return;
case 2:
buttonAnswer2.setTextColor(Color.GREEN);
return;
case 3:
buttonAnswer3.setTextColor(Color.GREEN);
return;
case 4:
buttonAnswer4.setTextColor(Color.GREEN);
return;
}
}
I you want to disable the whole interface while the AsyncTask runs, you can use code such as the following to display a dialog:
public abstract class BaseAsyncTask<Param, Result> extends AsyncTask<Param, Void, Result> implements DialogInterface.OnCancelListener {
private static final String TAG = "BaseAsyncTask";
private ProgressDialog dialog = null;
protected Context ctx = null;
protected Exception exception = null;
public BaseAsyncTask(Context ctx) {
this.ctx = ctx;
}
#Override
protected void onPreExecute() {
dialog = ProgressDialog.show(ctx, WLConstants.MSG_TITLE_LOADING_DIALOG, WLConstants.MSG_LOADING_DIALOG, true);
dialog.setCancelable(true);
dialog.setOnCancelListener(this);
if (ctx instanceof WozzonActivity) {
((WozzonActivity) ctx).setCurrentDialog(dialog);
}
}
#Override
protected Result doInBackground(Param... parameters) {
try {
return inBackground(parameters);
} catch (Exception ex) {
exception = ex;
Log.e(TAG, ex.getClass().getName(), ex);
return null;
}
};
#Override
protected void onPostExecute(Result result) {
try {
dialog.dismiss();
} catch (Exception ex) {
}// TODO:
if (result == null) {
onException(exception);
} else {
onResult(result);
}
}
protected void onException(Exception ex) {
if (ex != null && ex instanceof WozzonException) {
Toast.makeText(ctx, ex.getMessage(), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(ctx, WLConstants._ERROR_MSG, Toast.LENGTH_SHORT).show();
}
}
public abstract void onResult(Result result);
public abstract Result inBackground(Param... parameters) throws Exception;
#Override
public void onCancel(DialogInterface theDialog) {
cancel(true);
}
}
You need to use the onPreExecute() method of the ASyncTask().
Your problem is not related to threads at all. Try setTextColor(#ff0000) and settextColor(#00ff00), instead of settextColor(Color.RED) and setTextColor(Color.GREEN).
This is the way i use it now to lock my screen during the AsyncTask. For me it is perfect now. Hope it can help u.
private class PrepareAdapter extends AsyncTask<Void, Void, Integer>
implements DialogInterface.OnCancelListener {
private Dialog dialog = null;
#Override
protected void onPreExecute() {
// To disable the whole screen --> setCancelable(false);
dialog = new Dialog(WerWeissWasQuizActivity.this, android.R.style.Theme_Translucent_NoTitleBar_Fullscreen);
dialog.setCancelable(false);
dialog.show();
}
#Override
protected Integer doInBackground(Void... params) {
dialog.dismiss();
return 0;
}
#Override
protected void onPostExecute(Integer result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
//do other stuff...
}
#Override
public void onCancel(DialogInterface dialog) {
// TODO Auto-generated method stub
cancel(true);
}
}