Android: Stopping program flow from continuing if error condition? - android

Within my activity I am trying to use validation within a method (shown below) to carry out two functionalities:
Display toast as error message if there is an error condition
Bring user back to main menu using intents.
The above is working however after the validation is carried out the program flow within that activity is still being carried out. (see second code block below).
How can I ensure that nothing else in the activity is executed after, if the validation block is called in my method? I.e. just return to MainMenu, dont execute rest of code in finally block.
Method containing validation:
public void getAverageAttentionValue() {
// validation to ensure that no dividing by zero
if (totalofAttLevels < 1) {
new Thread() {
public void run() {
StroopGame.this.runOnUiThread(new Runnable() {
public void run() {
//display error message
Toast.makeText(
StroopGame.this,
"Headset unable to read values, please re-connect",
Toast.LENGTH_LONG).show();
(new Handler()).postDelayed(new Runnable() {
public void run() {
Intent openActivity = new Intent(
"com.example.brianapp.MainMenu");
startActivity(openActivity);
device.close();
}
}, 2000);
}
});
}
}.start();
} else {
averageAttLevel = totalofAttLevels / attCount;
attMax = Collections.max(AttentionValues);
}
}
Calling the above method in finally block and the code that is still being called afterwards:
finally {
//calling method containing validation
getAverageAttentionValue();
//I DONT WANT THE CODE BELOW TO BE EXECUTED IF
//THE VALIDATION IN METHOD IS CALLED
// write data from session to SQLite db
writeToDatabase();
// stop audio
tenSecs.stop();
// declaring activity to open
Intent openActivity = new Intent(
"com.example.brianapp.StroopResults");
openActivity.putExtra("singleScore", single);
// Start activity
startActivity(openActivity);
device.close();
}
}

You can do it as :
Take a member variable for e.g boolean isValidateCalled = false; in the your activity. Then set that variable to true if your validate() method is called. And then in finally
finally {
//calling method containing validation
getAverageAttentionValue();
// Check whether validate was called,if not,proceed
if(!isValidateCalled)
{
// write data from session to SQLite db
writeToDatabase();
// stop audio
tenSecs.stop();
// declaring activity to open
Intent openActivity = new Intent(
"com.example.brianapp.StroopResults");
openActivity.putExtra("singleScore", single);
// Start activity
startActivity(openActivity);
}
device.close();
}

Related

Espresso - Check if the screen is Visible or not

I'm trying to write some tests with the new android-test-kit (Espresso). But I can't find any information on how to check if a view is displayed and perform some actions on it (like clicking buttons, e.t.c.). Note that the view I need to check if it exists or not. If it does perform action on the view and if not proceed to the next view.
Any help would be appreciated. I just need a link, or some example code for the basics:
Check if the view exists
If yes,Perform action
If not, proceed to next screen
You can use a classic option "try/catch":
try {
onView(withText("Text")).check(matches(isDisplayed()));
//perform some actions on this view
} catch (NoMatchingViewException notExist) {
//proceed to the next screen
}
Object currentActivity;
#Nullable
private Activity getCurrentActivity() throws Throwable {
getInstrumentation().waitForIdleSync();
getInstrumentation().runOnMainSync(new Runnable() {
public void run() {
Collection resumedActivities = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(RESUMED);
if (resumedActivities.iterator().hasNext()) {
currentActivity = resumedActivities.iterator().next();
}
}
});
return (Activity) currentActivity;
}
with this, you can get the Activity that is currently displayed. After that by doing something like this, you can make a safe code section
HOMESCREEN:
{
for (; ; ) {
if (getCurrentActivity() != null) {
//check if it is the required screen
if (getCurrentActivity().getLocalClassName().toLowerCase().contains("homescreen")) {
//if it is the required screen, break the
//loop and continue execution
break HOMESCREEN;
} else {
//wait for 2 seconds and run the loop again
sleep(2000);
}
} else {
break HOMESCREEN;
}
}
}
sleep(2000) is a custom function which just calls thread.sleep like shown below:
private void sleep(long milliseconds) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
throw new RuntimeException("Cannot execute Thread.sleep()");
}
}
You must control the behavior of your test. So, you must have to add some preconditions, or create the #Rule that will control the behavior, for example by adding parameters depending on which your view will be displayed or not.

Which is the best method for Activity Change For Android Application

I have two activity. I want to go from A to B with fixed time. After going to B i want to come back to A with fixed time. i have searched for it but could not understand where to start. Should i use thread or timer or handler.
I am trying to understand the below codes:
Handler activityChanger = new Handler();
activityChanger.postDelayed(new Runnable(){
startActivity(new Intent(this,about.class));
}, 10000);
It would be a great help if anyone can give me an example.
I have added below code.
Thread switchToActivityB = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(3000);
Intent intent = new Intent(this, About.class);
startActivity(intent);
finish();
} catch (Exception e) {
}
}
});
switchToActivityB.start();
The place to put the code depends of how you want to do. For example, if you want to do this everytime you are in Activity A (that means that when you go to B and then press go back, after a fixed time it will go back to the activity B again), you should put the code in onResume() method.
If you just want to do this once, just put it in onCreate() method
Thread switchToActivityB = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(3000); // The fixed time in milli seconds
Intent intent = new Intent(activityA.this, activityB.class);
startActivity(intent);
finish();
} catch (Exception e) {
// Catch Exception
}
}
});
switchToActivityB.start();
Add this code to Activity A, in onCreate() method
Do the same in Activity B, in onCreate() method
Thread switchToActivityA = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(3000); // The fixed time in milli seconds
Intent intent = new Intent(activityB.this, activityA.class);
startActivity(intent);
finish();
} catch (Exception e) {
// Catch Exception
}
}
});
switchToActivityA.start();
For what you described you should use that either on onStart or onResume methods. If you place it on onCreate it will run just once, as your activities don't get destroyed.
You can use any of the options you described. StartActivity Is a safe method, so you can call it from outside your UI Thread.
You can put the above code in onResume() of 1st activity. Similarly, put the same code with little modification of activity name in "about.java" onResume()..

Not able to execute loop based on thread.sleep

I'm trying to display a series of images from a specific folder in sdcard - in the form of slideshow. filelist[] contains names of all files present in that directory.
I'm filtering out the images here. Next, thread.sleep(1000) does not seem to have any effect. Only the last image in the directory is displayed after a time of 1000ms. Where am I going wrong? Any other way I could accomplish this?
Maybe I've gone completely wrong. I'm a newbie so plz help.
public class List_imgActivity extends Activity {
/** Called when the activity is first created. */
Bitmap[] bitmapArray = new Bitmap[1000];
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button pf=(Button) findViewById(R.id.pick_button);
pf.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
Intent intent = new Intent("org.openintents.action.PICK_DIRECTORY");
intent.setData(Uri.parse("file:///sdcard"));
intent.putExtra("org.openintents.extra.TITLE", "Please select a folder");
intent.putExtra("org.openintents.extra.BUTTON_TEXT", "Use this folder");
startActivityForResult(intent, 1);
}
});
}
protected void onActivityResult(int requestCode, int recievecode, Intent intent)
{
if (requestCode == 1 )
{
Uri uri = intent.getData();
try {
File f=new File(new URI(uri.toString()));
final String nx=f.toString();
if(f.isDirectory()) {
File filelist[] = f.listFiles();
for(int i=0;i<filelist.length;i++)
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String filename = filelist[i].getName();
int pos = filename.lastIndexOf(".");
String ext = filename.substring(pos);
if(ext.equals(".jpg"))
{
TextView tv1= (TextView) findViewById(R.id.textView1);
tv1.setText(filelist[i].toString());
ImageView iv1=(ImageView) findViewById(R.id.imageView1);
bitmapArray[i] = BitmapFactory.decodeFile(filelist[i].toString());
iv1.setImageBitmap(bitmapArray[i]);
}
}
}
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
In Android behaviour like this will make the UI-Thread sleep. This will freeze the whole UI of the phone your App will look crashed to the user and the System will automatically kill your application after a while.
There is a mechanism to change things in specific time intervalls. You should use this handlers for doing this. Handlers
A handler has a postDelayed and sendMessageDelayed methods that allow you to either build a Runnable that will be executed after a certain time or send a message that must be handled by the implementation of your handler.
The initialization of the handler would look something like this:
showNextImageHandler = new Handler() {
#Override
public void handleMessage(android.os.Message msg) {
showNextImage();
}
};
showNextImageHandler.sendMessageDelayed(showNextImageHandler.obtainMessage(), 1000);
This code creates a new handler that calls the function showNextImage every time it receives a message. I would store the Handler in an instance variable of your activity to send further messages later on. After the handler is created a first empty message is send in a way that will delay the posting of the message 1000 milliseconds. After a second the showNextImage function will be called. In this function you can change the view and if a next image exists you can post another delayed message to trigger another call to the function later on.
U Must synchronise the current object before applying Thread.sleep() method

cant create handler inside thread that has not called looper.prepare

Note : I know there are many questions related to this, but still I am not convince, so asking.
I am getting cant create handler inside thread that has not called looper.prepare when I try to show the dialog.
Here is my code...
//this method is called from a different method based on some condition which is inturn called on click a button
private void download() {
thread = new Thread() {
public void run() {
/**** Downloads each tour's Tour.plist file ****/
try {
// do many heavy operations here, like download,
//calling web webvice and starting another activity
This comes at the end
Intent toAudio = new Intent(TourDescription.this,Audio.class);
startActivity(toAudio);
} catch (Exception e) {
}
}
};
thread.start();
}
Now before this actity gets called I am trying to show a dialog. I am trying to place that just before calling Intent.
Can any body please tell me how to do this, as I am not understanding how to solve this
you cannot show a dialog from a child thread.
A dialog can only be showed from within the UI thread/main Thread.
try this from inside the child thread
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO show dialog....
}
});

Android: wait on user input from dialog?

I would like to implement a method that displays a dialog, waits until the dialog is dismissed, and then returns a result depending on the dialog contents. Is this possible?
public String getUserInput()
{
//do something to show dialog
String input = //get input from dialog
return input;
}
I am actually trying to implement an interface which has method "public String getUserInput()", where the returned String must be retrieved via dialog. This is easily done in java, seems impossible in android?
EDIT: Posting some sample code as requested in comment
getInput() must be called from a background thread (I call it from an AsynchTask). getInput() displays a dialog and calls wait. When the ok button is pressed on the dialog, the dialog sets the user input in a member variable and calls notify. When notify is called, getInput() continues and returns the member variable.
String m_Input;
public synchronized String getInput()
{
runOnUiThread(new Runnable()
{
#Override
public void run()
{
AlertDialog.Builder alert = new AlertDialog.Builder(context);
//customize alert dialog to allow desired input
alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton)
{
m_Input = alert.getCustomInput();
notify();
}
});
alert.show();
}
});
try
{
wait();
}
catch (InterruptedException e)
{
}
return m_Input;
}
Is this possible?
No. There is no blocking UI model in Android. Everything is asynchronous.
UPDATE
In response to some of your comments on the question itself, you cannot display a UI from a background thread. As I wrote in this answer, there is no blocking UI model in Android. Just put your code in the button handler for your dialog that you want to have executed when the dialog is accepted, such as in this sample project.
The right way to do this is an event driven program model, ie, "don't call us, we'll call you".
In simple console mode programming, your code tends to call blocking input functions, which don't return until you've gotten a value.
Many gui programming environments work differently - your code is not normally running, but instead it's called by the operating system / window manager when something of potential interest happens. You do something in response to this and promptly return - if you do not, you can't be notified of anything else since the OS has no way to contact you until you return. (In comparison to win32, it's as if the message loop is implemented by Android, and you only get to write the rest of the code that the message loop calls with events - if you don't return promptly, the message loop hangs)
As a result, you need to rethink your concept of program flow. Instead of writing out a to-do list as a simple series of statements, think about it as a sequence of actions which depend on each other and on input. Remember what action you are currently on in a state variable. When you get called with an event such as user input, see if that event means it's now possible to move on to the next step, and if so update your state variable before promptly returning to the OS in order to be able to receive the next event. If the event wasn't what you needed, then just return without updating your state.
If this model won't work for you, what you can do is write a background thread of program logic which runs like a console-mode application using blocking input. But your input functions will really just wait on a flag or something to be notified that input is available. Then on your UI thread where Android delivers events, you update the flag and promptly return. The background thread sees the flag has changed to indicate that data has been provided, and continues execution. (Something like an android terminal emulator takes this to an extreme, where the background component is actually another process - a console mode linux one, and it gets its input using potentially blocking I/O from pipes. The java component accepts android UI events and stuffs characters into the stdin pipe and pulls them out of the stdout pipe to display on the screen.)
Thanks for all the feedback, I was able to solve this using a background thread along with a wait() and notify(). I recognize this isn't the greatest idea for the given paradigm, but it was necessary to conform to a library that I am working with.
I had a hard time understanding all the solutions offered above so far so I found my own one.
I wrap the code thats supposed to be performed after the user input is OK'ed in a runnable, like so:
Runnable rOpenFile = new Runnable() {
#Override
public void run() {
.... code to perform
}
}
Then right below that I pass the name of the runnable function to the user dialog method.
userInput("Open File", rOpenFile);
The userInput method is based on the alertDialog builder like described above. When the user input is Ok'ed it starts the intended runnable.
private void userInput(String sTitle, final Runnable func) {
AlertDialog.Builder aBuilder = new AlertDialog.Builder(this);
aBuilder.setTitle(sTitle);
final EditText input = new EditText(this);
input.setInputType(InputType.TYPE_CLASS_TEXT);
aBuilder.setView(input);
bDialogDone = false;
aBuilder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
final String sText = input.getText().toString();
sEingabe = sText;
func.run();
}
});
aBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
sEingabe = "";
}
});
aBuilder.show();
}
Something like this would do
/**
*
*/
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
/**
* #author
*/
public class TextEntryActivity extends Activity {
private EditText et;
/*
* (non-Javadoc)
* #see android.app.Activity#onCreate(android.os.Bundle)
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_text_entry);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
// title
try {
String s = getIntent().getExtras().getString("title");
if (s.length() > 0) {
this.setTitle(s);
}
} catch (Exception e) {
}
// value
try {
et = ((EditText) findViewById(R.id.txtValue));
et.setText(getIntent().getExtras().getString("value"));
} catch (Exception e) {
}
// button
((Button) findViewById(R.id.btnDone)).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
executeDone();
}
});
}
/* (non-Javadoc)
* #see android.app.Activity#onBackPressed()
*/
#Override
public void onBackPressed() {
executeDone();
super.onBackPressed();
}
/**
*
*/
private void executeDone() {
Intent resultIntent = new Intent();
resultIntent.putExtra("value", TextEntryActivity.this.et.getText().toString());
setResult(Activity.RESULT_OK, resultIntent);
finish();
}
}
The launch is:
public void launchPreferedNameEdit() {
Intent foo = new Intent(this, TextEntryActivity.class);
foo.putExtra("value", objItem.getPreferedNickname());
this.startActivityForResult(foo, EDIT_PREFERED_NAME);
}
You get the result by using
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case EDIT_PREFERED_NAME:
try {
String value = data.getStringExtra("value");
if (value != null && value.length() > 0) {
}
} catch (Exception e) {
}
break;
default:
break;
}
}
CASE: My data was ready to be processes after a preference change listener event and I needed to add a String queried from user. It doesn't appear possible to pop an alert dialog while the options menu is open...so I had to wait. I threw the half complete object into the next activity in the workflow and set its onResume() to check if its placeholder was !null in which case I popped the dialog and finished up the object *"in the button handler of the dialog"*.
Since this is my first post I can't vote for the correct answer given above but want to save anyone else running into this the time and in-elegance of less correct solutions. The dialog is the place.
You can think in terms of a state machine where if you initially require first-time user input you can have a flag set to mark "user input needed" or whatever. Then upon processing an event you check that flag and if set you fire up a dialog as the only action for the event and unset the flag. Then from the dialog event handler after handling user input you can call the code normally intended for the case when a dialog is not needed.
For your reference, I just made a dialog.
It would show and wait then dismiss.
And I deploy Java wait and notify to make it, this function can be copied and run directly.
private final Object lock = new Lock();
private static final class Lock {}
private void showWaitDialog(final String message, final int time_to_wait) { //ms
if(this.isFinishing()) return;
final String TTAG = "[showWaitDialog]";
Log.d(TTAG, "dialog going to show");
final ProgressDialog waitProgress = ProgressDialog.show(this, "WARNING", message, true);
waitProgress.setCancelable(false);
waitProgress.setOnShowListener(new DialogInterface.OnShowListener() { //callback got the asynchronous
#Override
public void onShow(DialogInterface dialog) {
Log.d(TTAG, "dialog showed");
synchronized (lock) {
try {
Log.d(TTAG, "main thread going to wait");
lock.wait();
} catch (InterruptedException e) {
Log.e(TTAG, e.toString());
Log.e(TTAG, "main thread going ahead");
}
}
}
});
new Thread(new Runnable() {
#Override
public void run() {
synchronized (lock) {
try {
Thread.sleep(time_to_wait);
} catch (Exception e) {
Log.d(TTAG, e.toString());
}
lock.notifyAll();
Log.d(TTAG, "dialog notified");
waitProgress.dismiss();
}
}
}).start();
}

Categories

Resources