I am trying to implement an administration mode when the user tap 7 times on back button.
Then, A dialog message will be called with editText asking for a password. if the password matches with the one in the database, I set passwordMacthes as TRUE and return it to whatever calls the dialog setTapCount and to start administration mode activity.
However, return passordMatches always return FALSE because it finishes the execution before the dialogMessage verifies the password and be dismissed or canceled by the user.
here is my setTapCount method :
public static boolean setTapCount(Context context){
tapCount = tapCount + 1;
if(tapCount == 7){
tapCount = 0;
dialogMessage(context);
return passwordMatches;
}else{
return false;
}
}
Does anyone know how to call the line below of dialogMessage(context) only once it is finished ?
thanks
Move that line to the handler for the accept button in the dialog, and rewrite your app to be event-driven (e.g., have setTapCount() accept a result listener object that can be notified of what the user did, rather than return a boolean).
Related
I'm developing an app which has background processes, few of the features in my app shall only work if user turn on the screen and also unlock the "Lock Screen". There are actions for SCREEN_ON, SCREEN_OFF and USER_PRESENT.
I reset a flag on SCREEN_OFF event and set it on USER_PRESENT event, this works fine but here I have another issue;
In settings there is an options "Lock instantly with power button", if it is unchecked, device will not lock until 5 seconds of sleep.
Now, SCREEN_OFF event is called and USER_PRESENT event is never called, if user turn off screen and turn it on within 5 seconds.
Is there is any action for USER_NOT_PRESENT or DEVICE_LOCKED so I can reset my flag there?
NOTE: I can work around if I know the settings "lock_screen_lock_after_timeout" and "power_button_instantly_locks". However I can get "lock_screen_lock_after_timeout" settings as follow but don't know how to get "power_button_instantly_locks"
ContentResolver mResolver = ctx.getContentResolver();
long timeout = Settings.Secure.getLong(mResolver, "lock_screen_lock_after_timeout", 0);
Thank you. Any other approach shall also be appreciated.
Use reflection to get the setting value of power_button_instantly_locks.
See the code below:
/**
*This function is used to detect the system setting: Power button instantly locks. To see whether this setting is enabled or not.
* #return true if Power button instantly locks is enabled, otherwise, false.
*/
private boolean isPowerButtonInstantlyLocksOn(){
String LOCK_PATTERN_UTILS="com.android.internal.widget.LockPatternUtils";
String POWER_BUTTON_INSTANTLY_LOCKS="getPowerButtonInstantlyLocks";
boolean isPowerButtonInstantlyLocks=false;
try{
Class<?> lockPatternUtilsClass=Class.forName(LOCK_PATTERN_UTILS);
Object lockPatternUtils=lockPatternUtilsClass.getConstructor(Context.class).newInstance(this);
// According to the source code of Android 6, the function getPowerButtonInstantlyLocks is declared with a parameter "int userId"
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
Method method = lockPatternUtilsClass.getMethod(POWER_BUTTON_INSTANTLY_LOCKS,new Class[]{int.class});
isPowerButtonInstantlyLocks=Boolean.valueOf(String.valueOf(method.invoke(lockPatternUtils,userID())));
}else {
Method method = lockPatternUtilsClass.getMethod(POWER_BUTTON_INSTANTLY_LOCKS);
isPowerButtonInstantlyLocks=Boolean.valueOf(String.valueOf(method.invoke(lockPatternUtils,null)));
}
}catch (Exception e){
Crashlytics.logException(e);
e.printStackTrace();
}
return isPowerButtonInstantlyLocks;
}
/**
* This function is used to check the current userID
* #return
*/
private int userID(){
// myUserId is a hidden function in Class UserHandle that we want to use to return the current user ID
String MY_USER_ID="myUserId";
int userId=0;
try{
// android.os.Process.myUserHandle() is called to get a UserHandle instance
// myUserHandle requires API 17, but it is OK, cause the function userID() will only be called at API 23
if (Build.VERSION.SDK_INT>Build.VERSION_CODES.JELLY_BEAN){
UserHandle userHandle=android.os.Process.myUserHandle();
Method method = UserHandle.class.getMethod(MY_USER_ID);
userId=Integer.valueOf(String.valueOf(method.invoke(userHandle,null)));
}
}catch (Exception e){
Crashlytics.logException(e);
e.printStackTrace();
}
return userId;
}
I'm not keen on the standard behavior of the Play Games Service to automatically attempt a connection when the app is first launched, so I have disabled this. In my main menu I have a 'display scores' button. What I want to happen when the user presses this button is this:
If the user is connected (logged in), go ahead and display the leaderboard
If the user is not connected, then display the connection dialog. Once connected, display the leaderboard
On the main menu, I will have an extra button "Log out" which will display only if the user is connected / logged in.
When the user clicks the button, I am carrying out the following:
Code
if (buttonPressed()){
//Display connection dialogue and initiate log in
getGameHelper().beginUserInitiatedSignIn();
//Check if the user is signed in before continuing
if (getGameHelper.isSignedIn()){
startActivityForResult(Games.Leaderboards.getLeaderboardIntent(getApiClient(), myLeaderBoardID), 1);
}
}
If the user isn't connected: The user is presented with a connection dialogue - this works fine. They can then log in. Once they have done this, nothing else happens (the code has moved on and therefore does not display the leaderboard because the user isn't logged in - if I don't have the check to see if the user is signed in here the app would just crash). If the user then presses the button again, it will display the leaderboard.
How can I do all this with just one button press?
What I want is, if the user isn't logged in, to display the log-in dialogue, then as soon as the user has logged in, display the leaderboard. I need to make startActivityForResult wait until the user has completed sign in.
In short
I need to make my code wait until it's connected to Play before attempting to display the Leaderboard.
Any help would be appreciated
You can be notified of successful/failed sign-in as follows:
getGameHelper().setup(
new GameHelper.GameHelperListener() {
#Override
public void onSignInSucceeded() {
// execute code on successful sign-in
// for example, here you could show your leaderboard
}
#Override
public void onSignInFailed() {
// execute code on failed sign-in
}
};
);
You should of course do this before you attempt to sign-in. You can then show your leaderboard when sign-in succeeds. This code should be placed where you create your game helper (i.e. before the buttonPressed() code is executed).
Once this code is in place, you should change your buttonPressed() code to look as follows:
if ( buttonPressed() ) {
// check if user already signed-in and show leaderboard; otherwise do sign-in
if ( getGameHelper.isSignedIn() ) {
startActivityForResult( Games.Leaderboards.getLeaderboardIntent( getApiClient(), myLeaderBoardID ), 1 );
}
else {
getGameHelper().beginUserInitiatedSignIn();
// NOTE: do nothing further here; show the leaderboard in
// the listener's onSignInSucceeded()
}
}
One final note: the listener you create will be called for all sign-in operations, so if you need to have this functionality in multiple places (for example, if you want to do the same with achievements) then you will need to use some signal as to what needs to happen on successful sign-in and take the correct action in onSignInSucceeded().
Signalling an action for sign-in success:
Add this code to you class (global scope)
public final static int NO_ACTION = 0;
public final static int SHOW_LEADERBOARD = 1;
public final static int SHOW_ACHIEVEMENTS = 2;
public int signInAction = NO_ACTION;
Next set the action just before signing-in (based on where the sign-in occurs):
if ( buttonPressed() ) {
// check if user already signed-in and show leaderboard; otherwise do sign-in
if ( getGameHelper.isSignedIn() ) {
startActivityForResult( Games.Leaderboards.getLeaderboardIntent( getApiClient(), myLeaderBoardID ), 1 );
}
else {
// NEW: request leaderboard to be shown upon sign in
signInAction = SHOW_LEADERBOARD;
// NEW----------------------------------------------
getGameHelper().beginUserInitiatedSignIn();
// NOTE: do nothing further here; show the leaderboard in
// the listener's onSignInSucceeded()
}
}
And finally change the listener to respond the set sign-in action:
getGameHelper().setup(
new GameHelper.GameHelperListener() {
#Override
public void onSignInSucceeded() {
if ( signInAction == SHOW_LEADERBOARD ) {
// show your leaderboard here
}
else if ( signInAction == SHOW_ACHIEVEMENTS ) {
// show achievements here
}
// important! reset the sign-in action so that any subsequent sign-in
// attempts do not re-use the currently set action!
signInAction = NO_ACTION;
}
#Override
public void onSignInFailed() {
// execute code on failed sign-in
// important! it should also be cleared in case of an error
signInAction = NO_ACTION;
}
};
);
Of course, this is just one way to achieve this, but it should work just fine for most purposes. Just be sure to set the signInAction to the appropriate value before you perform the sign-in - and be sure to clear it when sign-in is complete.
I have some code, but it is not working as expected. My logic doesn't seem to be faulty, so I think it is an implementation error. My code:
public boolean[] party_check(){
Date date_ET = new Date(party_dateET.getYear(), party_dateET.getMonth(), party_dateET.getDayOfMonth());///Date is deprecated,
///but easy to handle
///this is used to test the date contained in the datepicker, party_dateET. If it is before the day today, then it will not write,
///and a message is displayed
boolean[] return_array = new boolean[4];
///EditText party_titleET;
///EditText party_timeET;
///EditText party_dateET;
///EditText party_venueET;
return_array[0] = true;
if(party_titleET.getText().length() == 0){
return_array[1] = false;
return_array[0] = false;
}else{
return_array[1] = true;
}
if(date_ET.before(Calendar.getInstance().getTime()) == true){
return_array[2] = false;
return_array[0] = false;
///tests that the date entered is not invalid, ie. is in the future.
///not test for time. I could say that if time == 00:00, then don't run, or use a listener to check if it has changed,
///using a boolean value. But this would not really benefit the task much, so I haven't. It would also
///take more coding, and more complex coding.
}else{
return_array[2] = true;
}
if(party_venueET.getText().length() == 0){
return_array[3] = false;
return_array[0] = false;
}else{
return_array[3] = true;
}
return return_array;
///return_array[0] - 1st value in array - is used as toggle as to whether the party is ready or not.
///return_array[1-4] are used to indicate to the user which textbox is empty/ has a problem.
}
However it does not do what I expect it to do when I return the boolean array. This is used for testing whether the user has entered a text value into the EditText's.
However it does not work as expected. Is my logic faulty, or I have implemented it wrong? Thanks for the help!!
The hint does not get returned, when you use getText(). You can use getHint() though.
Text and Hint are different properties.
So the Text will be empty, if the hint is shown.
Let's say that the hint is a "dress" for the text (not to let it "naked"), but it's not the text itself.
I'm pretty new to Android development, in the later states of my first serious project. Briefly, the program will ssh into a Linux host and perform commands. But I find myself really getting tied into knots trying to finish this.
I'm using ganymed-ssh2 to do the ssh grunt-work.
When an Activity button is hit, I want the program to start a SSH session, verify the host fingerprint - prompting for acceptance if necessary, and then issue remote commands as programed. But this seemingly simple few steps, are getting very complicated by the following:
The ssh cannot be performed in the UI thread, so I have to start an AsyncTask, so all of what I describe in the next hassles are not in the foreground UI thread.
To activate the ssh fingerprinting code, I need to make a call like this inside my AsyncTask class:
#Override
protected String doInBackground(String... command) {
String result;
result = "";
try {
/* Create a connection instance */
Connection conn = new Connection(connect.getHost(), connect.getPort());
/* Now connect */
ConnectionInfo info = conn.connect(new AdvancedVerifier());
boolean isAuthenticated = false;
// first try public key if defined
if (connect.getPrivateKey() != null)
isAuthenticated = conn.authenticateWithPublicKey
(connect.getUserid(), connect.getPrivateKey(), null);
// if failed, or not defined, try password if provide
if (!isAuthenticated && connect.getPassword() != null)
isAuthenticated = conn.authenticateWithPassword(connect.getUserid(),
new String (connect.getPassword()));
// all else, get out
if (!isAuthenticated)
throw new IOException("Authentication failed.");
/* Create a session */
Session sess = conn.openSession();
sess.execCommand(command[0]);
}
However, the conn.connect(new AdvancedVerifier()) line causes a callback interface class of AdvancedVerifier to be called, interrupting the execution path at the connect call to call this class:
class AdvancedVerifier implements ServerHostKeyVerifier
{
public boolean verifyServerHostKey(String hostname, int port,
String serverHostKeyAlgorithm,
byte[] serverHostKey) throws Exception
{
final String host = hostname;
final String algo = serverHostKeyAlgorithm;
/* Check database - code removed*/
/* assuming fingerprint needs verification */
String hexFingerprint =
KnownHosts.createHexFingerprint(serverHostKeyAlgorithm,
serverHostKey);
String msg = "Hex Fingerprint: " + hexFingerprint;
/* right here, I need to display dialog of fingerprint,
and ask user for to continue;
If user accepts, return true, else return false.
If return true, the above class continues after connect(), if false
it is aborted.
*/
return UserAccepts? true : false;
}
}
Well this, in my limited experience, seems to raise lots of truely messy code.
First, I need to reattach back to the UI thread, display a dialog, then if user selects
OK, to then return "true" from verifyServerHostKey(), detach UI thread, and allow the ssh connection code to resume. All without the ability to use modal dialogs.
Frankly, I don't really know where to begin and am looking for ideas, guidance, etc.
I finally worked out at least one way to solve the problem. Using a wait/notify combination between my AdvancedVerifier class and using a AlertDialog in onProgressUpdate, I was able to pause the verifier class while the user accepts/rejects the host fingerprint.
Don't know if there is a better way, but I think I can work with this.
I have a strange scenario here.
I have this code:
// For checking if the person is logged in.
first_time_check();
setContentView(R.layout.main);
// ...next lines of code
and the first_time_check() function checks if the user is logged in for the first time. If their user_id is not in the SharedPreferences, I redirect them to log in:
public void first_time_check()
{
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences( ProblemioActivity.this);
String user_id = prefs.getString( "user_id", null ); // First arg is name and second is if not found.
String first_time_cookie = prefs.getString( "first_time_cookie" , null );
// About setting cookie. Check for first time cookie
if ( first_time_cookie == null )
{
// This user is a first-time visitor, 1) Create a cookie for them
first_time_cookie = "1";
// 2) Set it in the application session.
prefs.edit().putString("first_time_cookie", first_time_cookie ).commit();
// Make a remote call to the database to increment downloads number
// AND send me an email that it was a new user.
}
else
{
// If not first time, get their id.
// If user_id is empty, make them an account.
// If id not empty, call the update login date and be done.
if ( user_id == null )
{
// User id is null so they must have logged out.
Intent myIntent = new Intent(ProblemioActivity.this, LoginActivity.class);
ProblemioActivity.this.startActivity(myIntent);
}
else
{
// Make a remote call to the database to increment downloads number
}
}
return;
}
So after the code executes the
Intent myIntent = new Intent(ProblemioActivity.this, LoginActivity.class);
ProblemioActivity.this.startActivity(myIntent);
it still executes below the original code that calls this functions.
Any idea how that can happen?
Thanks!!
This is excerpted from the Dev Guide
Shutting Down an Activity
You can shut down an activity by calling its finish() method.
You can also shut down a separate activity that you previously
started by calling finishActivity().
Note: In most cases, you should not explicitly finish an activity
using these methods. As discussed in the following section about the
activity lifecycle, the Android system manages the life of an
activity for you, so you do not need to finish your own activities.
Calling these methods could adversely affect the expected user
experience and should only be used when you absolutely do not want
the user to return to this instance of the activity.
Calling finish() on the activity seems appropriate here as you do not want the user to return to this activity.