I have the following:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
....
populate();
handler = new Handler();
t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
doReload1();
populate();
}
});
}
}, 300, 30000);
}
private void populate() {
if (playlists.length != 0) {
MyListView = (ListView) findViewById(R.id.MyListView);
for (String item : playlists) {
Log.d("DEBUG", "item=" + item);
}
String[] adapterPlaylists = new String[playlists.length];
for (int i = 0; i < playlists.length; i++) {
adapterPlaylists[i] = playlists[i];
}
adapter1 = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, adapterPlaylists);
MyListView.setAdapter(adapter1);
adapter1.notifyDataSetChanged();
MyListView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View v,
int position, long id) {
dialogwait = ProgressDialog.show(Playlist.this,
"Loading...", "Please wait..", true);
Intent i = new Intent(getBaseContext(), ViewPlaylist.class);
i.putExtra("id", idPlaylist[position]);
i.putExtra("timer", timerPlaylist[position]);
startActivity(i);
finish();
}
});
} else
System.out.println("playlist null");
}
#Override
protected void onPause() {
super.onPause();
System.out.println("onPause Playlist!!!!!!");
dialogwait.dismiss();
t.cancel();
}
The thing is that here:
dialogwait = ProgressDialog.show(Playlist.this,
"Loading...", "Please wait..", true);
I create a ProgressDialog and I dissmis it in onPause().
But onPause gets called right after onCreate() before I even the ProgressDialog is created.
Any idea why?ANy solution?Thanks
This is because a Dialog in Android, does not block - meaning that the thread running behind it (in this case your Activity and in particular your onItemClickListener) will continue to execute.
It looks like you want to display a loading dialog, to let the user know that the item he clicked is being loaded. I suggest you move that dialog to the next activity (the one started from onClick), and then display and dismiss the dialog from there.
I think that the problem could be that you are calling finish() in your OnItemClickListener. This will cause the current Activity to end as soon as you click on an item which, because of your onPause() implementation will immediately close the dialog.
Maybe you need to display the dialog when your ViewPlaylist Activity is created rather than in this Activity.
anything on top of your current activity (a dialog or any other activity) makes it a background activity, thus onPause is called. if anything, dialog.dismiss() should be called in activities' onResume. in your implementation, you're showing a dialog when a button is clicked, thus pausing your activity and calling dismiss. you should call dismiss only when the process associated with your dialog is finished, thus telling your user that you're ready to do something else - in your case launch another activity.
launch your activity inside your dialog's onDismiss.
for example:
AlertDialog alert = new AlertDialog.Builder(this).create();
alert.setOnDismissListener(new OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
// start the other activity
}
});
Related
In my app I have implemented this custom dialog (which has a fairly complex layout) by extending DialogFragment. I expect this dialog to pop up when I click a button in my layout. (Which I have successfully achieved). But the problem is that the dialog shows up in a janky manner.
My custom dialog class:
public class CustomizeDialog extends DialogFragment implements AdapterView.OnItemSelectedListener {
// field declarations go here
#NonNull
#Override
public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.customize_dialog, null);
builder.setView(view)
.setTitle("Customize")
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setPositiveButton("Let's go!", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent();
intent.setAction("fromDialog");
intent.putExtra("ratio",getRatio(paperSizeSpinner.getSelectedItem().toString()));
if(isOrientationSpinnerVisible){
intent.putExtra("isCustom",false);
intent.putExtra("orientation",orientationSpinner.getSelectedItem().toString());
} else {
intent.putExtra("isCustom",true);
}
intentProvider.getIntent(intent);
}
});
widthEditText = view.findViewById(R.id.width_et);
heightEditText = view.findViewById(R.id.height_et);
widthEditText.setEnabled(false);
heightEditText.setEnabled(false);
paperSizeSpinner = view.findViewById(R.id.paper_size_spinner);
orientationSpinner = view.findViewById(R.id.orientation_spinner);
// ArrayList for populating paperSize spinner via paperSizeAdapter
ArrayList<String> paperSizes = new ArrayList<>();
paperSizes.add("A0");
paperSizes.add("A1");
paperSizes.add("A2");
paperSizes.add("A3");
paperSizes.add("A4");
paperSizes.add("A5");
paperSizes.add("Custom");
// ArrayList for populating orientation spinner via orientationAdapter
ArrayList<String> orientation = new ArrayList<>();
orientation.add("Portrait");
orientation.add("Landscape");
// arrayAdapters containing arraylists to populate spinners
ArrayAdapter paperSizeAdapter = new ArrayAdapter(getActivity(), android.R.layout.simple_spinner_dropdown_item, paperSizes);
ArrayAdapter orientationAdapter = new ArrayAdapter(getActivity(), android.R.layout.simple_spinner_dropdown_item, orientation);
paperSizeSpinner.setAdapter(paperSizeAdapter);
orientationSpinner.setAdapter(orientationAdapter);
paperSizeSpinner.setSelection(4);
paperSizeSpinner.setOnItemSelectedListener(this);
orientationSpinner.setOnItemSelectedListener(this);
return builder.create();
}
// These are some important complex ui functionalities
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (parent.getId() == R.id.paper_size_spinner) {
if (position == 6) {
widthEditText.setEnabled(true);
heightEditText.setEnabled(true);
orientationSpinner.setEnabled(false);
isOrientationSpinnerVisible = false;
} else {
widthEditText.setEnabled(false);
heightEditText.setEnabled(false);
orientationSpinner.setEnabled(true);
isOrientationSpinnerVisible = true;
}
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
// interface used to communicate with the parent activity
public interface IntentProvider {
// this method is used to provide the intent to the parent activity
void getIntent(Intent intent);
}
// instantiating the interface object and throwing error if parent activity does not implement this interface
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
try {
intentProvider = (IntentProvider) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() + " must implement IntentProvider");
}
}
}
MainActivity class:
public class MainActivity extends AppCompatActivity implements CustomizeDialog.IntentProvider {
// field declarations go here
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = findViewById(R.id.image);
// instantiating the dialog
final CustomizeDialog dialog = new CustomizeDialog();
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// showing the dialog on click
dialog.show(getSupportFragmentManager(),"");
}
});
}
// via this method I receive the intent from the dialog
// I know intent might not be the best option for this function but let's let it be here for now
#Override
public void getIntent(Intent intent) {
ratio = intent.getFloatExtra("ratio",3);
isCustom = intent.getBooleanExtra("isCustom",false);
orientation = intent.getStringExtra("orientation");
launchChooser();
}
}
Let me know in the comments if you want the layout code for the dialog.
What I tried:
Implementing threading so that my dialog is ready in a background thread and show it onButtonClick. But this is not allowed in general as any other thread except UI thread aren't supposed to touch UI related events.
Using onCreateView instead of onCreateDialog to inflate the layout directly.
Making the dialog a global variable, initialized it in onCreate and then show the dialog onButtonClick.
Switched to CONSTRAINT LAYOUT
Using an activity as a dialog by setting the dialog theme to the activity in the manifest file.
Launched my app in a device with better hardware than mine.
BUT NOTHING WORKED
What I want:
Why is my dialog janky? and what I need to do to make the dialog pop up faster?
In case anybody wants here's the link to my app repo on github.
AlertDialog and DialogFragment frameworks are slow because they need to some time to do calculations and fragment stuffs. So a solution to this problem is, using the Dialog framework straight away.
Use the Dialog framework's constructor to initialize a Dialog object like this:
Dialog dialog = new Dialog(context, R.style.Theme_AppCompat_Dialog);
// the second parameter is not compulsory and you can use other themes as well
Define the layout and then use dialog.setContentView(R.layout.name_of_layout).
Use dialog.findViewById(R.id.name_of_view) to reference views from the dialog's layout file
And then implement the logic just like anyone would do in an activity class. Find out the best implementation for your use case by reading the official documentation.
I'm working on app which is required user in active feature like if user is not available on the application more than 15 min. it shows some popup on the last activity we used, when we click okay it redirects to login screen.
It is working absolutely fine when i opened back my app exactly after 15 minutes to around 30 minutes .
My problem is now, when i open my app after 45 min or more than 1 hour, it doesn't work, it doesn't show in activity popup. it just opened the last activity i used.
I tried with below code added in splash activity:
if (!isTaskRoot()
&& getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)
&& getIntent().getAction() != null
&& getIntent().getAction().equals(Intent.ACTION_MAIN)) {
finish();
return;
}
Here is my BaseActivity class used for in active state checking
public class MyBaseActivity extends AppCompatActivity {
AlertDialog alertDialog;
Context context;
public static final long DISCONNECT_TIMEOUT = 900000; // 15 min = 15 * 60 * 1000 ms
private Handler disconnectHandler = new Handler(){
public void handleMessage(Message msg) {
}
};
private Runnable disconnectCallback = new Runnable() {
#Override
public void run() {
LayoutInflater li = LayoutInflater.from(MyBaseActivity.this);
View promptsView = li.inflate(R.layout.acount_status_dialogue, null);
final TextView userInput = (TextView) promptsView.findViewById(R.id.txtTitle);
final TextView userInput1 = (TextView) promptsView.findViewById(R.id.txtTitle1);
userInput1.setText("USER IN-ACTIVE");
userInput.setText("Due to user is inactive from last 15 minutes. Please Login Again");
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(MyBaseActivity.this,R.style.DialogLevelsStyle);
// set prompts.xml to alertdialog builder
alertDialogBuilder.setView(promptsView);
// set dialog message
alertDialogBuilder
.setCancelable(false)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
//do things
Intent i = new Intent(MyBaseActivity.this, SignInActivity.class);
//i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
finish();
Constant.val = 1;
AccountUtils.setValue("1");
}
});
// create alert dialog
alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
// Perform any required operation on disconnect
}
};
public void resetDisconnectTimer(){
Log.i("Main", "Invoking logout timer");
//disconnectHandler.removeCallbacks(disconnectCallback);
disconnectHandler.postDelayed(disconnectCallback, DISCONNECT_TIMEOUT);
}
public void stopDisconnectTimer(){
Log.i("Main", "cancel timer");
disconnectHandler.removeCallbacks(disconnectCallback);
}
#Override
public void onUserInteraction(){
resetDisconnectTimer();
}
#Override
public void onResume() {
super.onResume();
resetDisconnectTimer();
}
#Override
public void onStop() {
if (Constant.isAppIsInBackground(this)) {
stopDisconnectTimer();
resetDisconnectTimer();
}else {
stopDisconnectTimer();
}
super.onStop();
//stopDisconnectTimer();
}
}
Please find out my issue. thanks in advance.
Save the current time when the user put your app to background (for example in SharedPreferences), and when the user starts again your app calculate the diff and show what you want on the screen.
I have added a popup activity inside my app which is popping after 15 seconds of my app start. But when I am opening another activity and coming back to my main activity the popup showing again. I want it to appear only the first time when user is opening the app. What changes I should make? Appreciate the help.
Here is the popup code:
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (context != null) {
AlertDialog.Builder alert = new AlertDialog.Builder(context, R.style.MyAlertDialogStyle)
.setTitle("Title")
.setMessage("Message")
.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// continue with delete
Intent intent = new Intent(MainActivity.this, WebActivity.class);
startActivity(intent);
}
})
.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int which) {
dialogInterface.dismiss();
// do nothing
}
});
mDialog = alert.create();
mDialog.getWindow().getAttributes().windowAnimations = R.style.MyAlertDialogStyle;
if (!((Activity) context).isFinishing())
mDialog.show();
// .setIcon(R.drawable.inr1)
// .show();
}
}
}, 15000);
You can do this if it needs to pop up only on application start
public class MyApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
//Set some flag on global constant
}
}
save a tag(counter) in sharedPrefrances for that When the application starts up interpretation is the first time app start
You can use a global variable in the application class like this.
public class global extends Application
// some Boolean variable to hold status
And make sure you put this class inside android manifests application tag
android:name
Add this code in your MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
if(sharedPreferences.getBoolean("IS_FIRST_TIME", true)) {
//show your dialog here
//...
//change the value of your sharedPreferences
sharedPreferences.edit().putBoolean("IS_FIRST_TIME", false).apply();
}
}
please check the activity lifecycle.
Note:Remove Handler.
Note 2:Create method and call the dialog
Note 3:check the below method in lifecycle.
onPause ():
Called as part of the activity lifecycle when an activity is going into the background, but has not (yet) been killed. The counterpart to onResume(). When activity B is launched in front of activity A, this callback will be invoked on A. B will not be created until A's onPause() returns, so be sure to not do anything lengthy here.
save a boolean inside sharedpreferences read its value and determine weather running for the first time or not.
here is the code that will help you.
public void firstimeRun(boolean value) {
SharedPreferences sharedPreferences = getPrefrenceManager();
sharedPreferences.edit().putBoolean("key", value).apply();
}
public boolean isRunningForthefirstTime() {
SharedPreferences sharedPreferences = getPrefrenceManager();
return sharedPreferences.getBoolean("key", false);
}
private SharedPreferences getPrefrenceManager() {
return PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
}
Type finish(); after your startActivity(intent);
Before referring me to other threads on this forum and marking my question as duplicate kindly read my question. I have to create a global application timeout. No matter which activity is user on, after specific amount of time the user will be displayed AlertDialog that his session has expired and he can exit or renew his session. I have read different solutions and used service as my solution.
public class InActivityTimer extends Service {
MyCounter timer;
#Override
public void onCreate() {
timer = new MyCounter(20 * 1000,1000);
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
timer.start();
return super.onStartCommand(intent, flags, startId);
}
private class MyCounter extends CountDownTimer{
public MyCounter(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
Intent intent = new Intent("timeout_action");
sendBroadcast(intent);
stopSelf();
}
#Override
public void onTick(long millisUntilFinished) {
// Need AlertDialog code here
Toast.makeText(getApplicationContext(), ("Time Remaining: " + millisUntilFinished/1000)+"", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onDestroy() {
timer.cancel();
super.onDestroy();
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
The problem is that I can display the Toast without any problem but the AlertDialog is not displayed when called inside onFinish().
The first problem is to display the AlertDialog for whole application bearing in mind that the AlertDialog is displayed for some context. Also if somehow the AlertDialog is displayed then how to close the Application. On Activity I just close the activity by calling finish() so should I clear the Activities stack in this case?
The second complex part that I am facing is to display a popup when user click "Time remaining" link in the application which will show how much time is remaining for the Session to be timed out. This time should be exactly same as the time remaining in the service.
I can also use BroadcastReceiver and send update to the activity once the time is finished but wouldn't that be Activity specific because I want the timeout to act same regardless of which activity is user on. I want to avoid writing the same code on each activity.
Kindly guide me through with some solution.
If you use a fragment based design for your app, you can keep a root FragmentActivity in which all other elements of the app are displayed. This way you can use the context of the root FragmentActivity every time, to display your Dialog.
Additional: "Could you kindly refer to me some article.."
What you are doing is not common, and I would have to google search just like you to find any existing example similar to your case. I can however fill in a bit more detail on what I have proposed above.
If you are unfamiliar with using Fragments, read the Developer Documentation.
public class MainActivity extends FragmentActivity {
private static final int SPLASH_SCREEN_FRAGMENT = 0;
private static final int HOME_SCREEN_FRAGMENT = 1;
...
#Override
protected void onCreate(Bundle. savedInstanceState) {
super.onCreate(savedInstanceState);
// show your first fragment
Fragment splashFragment = new SplashFragment();
getSupportFragmentManager().beginTransaction().replace(android.R.id.content, splashFragment).commit();
// Start your service using the context of your FragmentActivity
// Your FragmentActivity will always be the current activity, and you will display
// all other elements of your app inside it as fragments
Intent intent = new Intent(this, InActivityTimer.class);
startService(intent);
}
// method for switching the displayed fragment
private void fragmentSwitcher(int fragmentType) {
Fragment currentFragment = new Fragment();
switch (currentFragmentType) {
case SPLASH_SCREEN_FRAGMENT:
currentFragment = new SplashScreenFragment();
break;
case HOME_SCREEN_FRAGMENT:
currentFragment = new HomeScreenFragment();
break;
...
}
getSupportFragmentManager().beginTransaction().replace(android.R.id.content, currentFragment).commit();
}
}
I have solved my issue with rather very simple approach.
#Override
public void onFinish() {
Intent intent = new Intent(getBaseContext(), TimeoutActivity.class);
startActivity(intent);
stopSelf();
}
and below is the onCreate method for my TimeoutActivity.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ContextThemeWrapper ctw = new ContextThemeWrapper(TimeoutDialogActivity.this, R.style.Theme_Base_AppCompat_Dialog_FixedSize);
final AlertDialog alertDialog = new AlertDialog.Builder(ctw).create();
alertDialog.setCancelable(false);
alertDialog.setTitle("Session Timeout !");
alertDialog.setTitle("Your session has expired.");
alertDialog.setButton(AlertDialog.BUTTON_NEGATIVE, "Logout", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
alertDialog.dismiss();
finish();
}
});
alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "Exit", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
alertDialog.dismiss();
finish();
}
});
alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, "Renew Session", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
alertDialog.dismiss();
finish();
});
alertDialog.show();
}
I have a requirement of having a activity as dialog (Not an Alert dialog, instead a progress dialog). There are no ui components in this activity since this activity does server interaction, based on server response next activities are started. Only a progress dialog with cancel button needs to be shown in this activity. Now the problem is when ever this activity is launched just before progress dialog is displayed a small black rectanagle is visible for a second or more, also when this activity is finished this is visible. How to get rid of this ? or is there any better way of haveing a progress dialog as activity ?
-Thanks & regards,
Manju
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityAsDialogActivity.this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
String str ="Hellow World";
txtView = (TextView)findViewById(R.id.txtview);
this.setFinishOnTouchOutside(false);
txtView.setText(R.string.select_dialog);
ActivityAsDialogActivity.this.setTitle(R.string.app_name);
mProgressHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (mProgress >= MAX_PROGRESS) {
mProgressDialog.dismiss();
Intent intent = new Intent(ActivityAsDialogActivity.this, ActivityOne.class);
startActivity(intent);
finish();
} else {
mProgress++;
mProgressDialog.incrementProgressBy(1);
mProgressHandler.sendEmptyMessageDelayed(0, 100);
}
}
};//end of handler
showDialog(DIALOG_PROGRESS);
mProgressDialog.setProgress(0);
mProgressHandler.sendEmptyMessage(0);
}//end of onCreate()
#Override
public void onBackPressed(){
Log.d("Manju ==>"," back key pressed");
finish();
}
#Override
public void finish(){
Log.d("Manju ==>", " inside finish()");
super.finish();
}
In Creating Global Dialog, I used a transparent activity with a dialog inside. I think you can do the same thing. I do not recall facing the problem you are facing, and it worked perfectly.
Check it out