Manually Disable and enable Android HostApduService? - java

Hi i have created a class that extends HostApduService and there is a scenario where i want to stop or pause the service awaiting some input from the user before resuming the service again. Is this possible?
i could not find any API that manually stops/pauses the HostApduService.
snippet of my HostApduService on what i want it to do
protected byte[] processApdu(byte[] apdu) {
if(isEnabled){
/proccess apdu as normal
}
}
snippet of some action in android on a ui
new View.OnClickListener() {
#Override
public void onClick(View v) {
//disable/pause hostapdu service???
}
});
new View.OnClickListener() {
#Override
public void onClick(View v) {
//enable/resume hostapdu service???
}
});
processApdu always needs to return some bytes to the terminal but i dont want it to and want to disablle/pause it until further notice

To disable:
context.getPackageManager().setComponentEnabledSetting(new ComponentName(context, MyHostApduService.class), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP)
To enable:
context.getPackageManager().setComponentEnabledSetting(new ComponentName(context, MyHostApduService.class), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP)
You could also try saving the enabled/disabled state in Shared Preferences

Related

I want two create two functions in one button

I am working on an app which would store data in Firebase. The issue is that when I click submit, the data stays on the form. I need when I click submit that it returns to the home screen.
I tried using the start activity method like I did when I wanted to move from MainActivity to another class. It would work but then my data will not be saved.
I am grateful for any assistance. Thanks in advance!
buttonSubmitReport.setOnClickListener(v -> {
reports.setDate(textDate.getText().toString().trim());
reports.setTime(textTime.getText().toString().trim());
reports.setReport(editRep.getText().toString().trim());
reff.push().setValue(reports);
reff.child(String.valueOf(maxID+1)).setValue("Reports");
Toast.makeText(submitReport.this,"Thanks for the information!", Toast.LENGTH_LONG).show();
}
});
What I am getting from your problem is that you have one activity from there you are starting another activity for editing the details and on click of some button, you want to save those details and come back to previous activity, right?
To do this just add some listener to that and when it completed simply finish the activity
buttonSubmitReport.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
reports.setDate(textDate.getText().toString().trim());
reports.setTime(textTime.getText().toString().trim());
reports.setReport(editRep.getText().toString().trim());
reff.push().setValue(reports);
reff.child(String.valueOf(maxID + 1)).setValue("Reports")
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
// Write was successful!, here either finish or move to another activity
Toast.makeText(submitReport.this, "Thanks for the information!", Toast.LENGTH_LONG).show();
finish();
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// Write failed
Toast.makeText(submitReport.this, "Failed to store the data", Toast.LENGTH_LONG).show();
}
});
});
You can use firebase value update listener, Once value update performs the operation.
Or you can use the firebase transaction handler.
override fun onComplete(dataBaseError: DatabaseError?, status: Boolean, snapShot: DataSnapshot?) {
//Operation complete call back
}
override fun doTransaction(data: MutableData): Transaction.Result {
//Perform your operation here
return Transaction.success(data)
}
})
You can try it once if possible
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState)
{
buttonSubmitReport.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
InsertData();
ReportsID = Fetch Reports Id and use condition is empty or not
if (TextUtils.isEmpty(ReportsID)) {
InsertData();
} else {
//---Start Activity
}
}
});
}
public bool InsertData()
{
reports.setDate(textDate.getText().toString().trim());
reports.setTime(textTime.getText().toString().trim());
reports.setReport(editRep.getText().toString().trim());
reff.push().setValue(reports);
reff.child(String.valueOf(maxID+1)).setValue("Reports");
Toast.makeText(submitReport.this,"Thanks for the information!", Toast.LENGTH_LONG).show();
}
}

How i can get the context of started activity

I'm trying to show a custom dialog in non-activity class for that i need the context of the foreground running activity which I did started from the main activity.
i get this exception when i run
Unable to add window -- token null is not for an application
I did use the context of a service but it not work
Cod of non-activity class
public void Confirmation_dialog_V2(ReportEvent e){
try{
Log.e("Bugreport","Confirmation");
Log.e("Bugreport","event: "+e.getEventDescription());
getRecording_service().stopRecording();
context= getRecording_service().getBaseContext();
context.setTheme(R.style.CustomTheme);
Log.e("Bugreport","get context");
if(context != null) {
Log.e("Bugreport","context not null");
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
Log.e("Bugreport","in run block");
LovelyStandardDialog dialog =new LovelyStandardDialog(context, LovelyStandardDialog.ButtonLayout.VERTICAL);
dialog.setTopColorRes(R.color.indigo);
dialog.setButtonsColorRes(R.color.darkDeepOrange);
dialog.setIcon(R.drawable.ic_assignment_white_36dp);
dialog.setTitle("Confirm_interaction");
dialog.setMessage("Interaction:"+e.getEventDescription());
dialog.setPositiveButton("Confirm", new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
dialog.setNegativeButton("NO", new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
dialog.setNeutralButton("Contine", new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
Log.e("Bugreport","showing");
dialog.show();
}
});
}
}catch (Exception ex){ex.printStackTrace();}
}
so i need the context of the activity in the foreground with I did started from the main activity.
Main activity
Intent App = getPackageManager().getLaunchIntentForPackage(BugReport.getInstance().getPackageName());
App.addCategory(Intent.CATEGORY_LAUNCHER);
App.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
App.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(App);
You can use Constructor for this problem.When you declare java class in your MainActivity java class that time Add Context with it.
As per your code you have Added ReportEvent , just Add context with that.like below:
public void Confirmation_dialog_V2(Context context,ReportEvent e){
//your code
}
If you will directly add Context in java class then it will show error in Main Java class where you declare JavaClass.and when you Add context there,error will disappear Automatically.
After it all you can use that context anywhere in that Java class.Thank you:)
public void Confirmation_dialog_V2(ReportEvent e,Context context)

Android AlertDialog crashes with BadTokenException?

this is my first post so please bear with me.
I'm a high school developer and recently released an Android app on the play store. I'm using Crashlytics to capture exceptions, and for this some reason it throws this error.
Fatal Exception: android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy#1989547c is not valid; is your activity running?
It was reported specifically on the LG D855, Nexus 5, and the Huawei PLK AL10 occurring on versions 5.0, 5.0.2, 5.1.1 and 6.0.1. I've looked online, and have found that this occurs when an activity does not exist. This error occurs on the initial startup of the app.
The following is the code I use for an Alert Dialog which simply asks if the user wants to see a tutorial (y/n)
public void showTutorialDialog() {
AlertDialog tutorialDialog = new AlertDialog.Builder(this)
.setTitle(R.string.tutorial_question_title)
.setCancelable(false)
.setMessage(R.string.tutorial_question)
.setPositiveButton(getResources().getString(R.string.tutorial_question_pos), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// Take to tutorial
// Assume isn't backer for now..
finish();
Intent i = new Intent(StartupActivity.this, TutorialActivity.class);
i.putExtra("from", "StartupActivity");
startActivity(i);
}
})
.setNegativeButton(getResources().getString(R.string.tutorial_question_neg), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// No tutorial, ask if they are a backer
showBackerDialog();
}
}).show();
Upon the initial start of the app, I load the users purchase details using IabHelper in a separate class. This class, called PurchaseRetriever, retrieves the content of users purchases asynchronously and stores it in an ArrayList. This is how my code works.
if (mManager.isUserFirstTime()) {
// Initialize purchase retriever.
// The rest will be done when the observer reports that purchase data has been retrieved.
mPurchases = PurchaseRetriever.getInstance(StartupActivity.this);
mPurchases.addObserver(new FirstStartupObserver(this));
StartupManager.FIRST = true;
loadImageContent();
It runs using the Observer pattern, so when the purchase details are queried it calls the update() method in FirstStartupObserver, which then by a reference to StartupActivity, calls startupActivity.showTutorialDialog();where the error occurs.
I've tested it on multiple devices I and my friends own personally (Nexus 6, Nexus 5, Nexus 7 tablet, Samsung Galaxy Tab, various devices on Samsung Remote Lab) yet it works fine on my end...
Any advice appreciated, thanks.
Edit: Here is StartupActivity.
/**
* Main startup activity. Determines which activity to launch.
* Puts the user in one place or another depending on if they are a backer.
*/
public class StartupActivity extends AppCompatActivity {
private StartupManager mManager;
private ProgressBar bar;
// --- Used if first time app loading to query purchase info
private PurchaseRetriever mPurchases;
#Override
protected void onCreate(Bundle savedInstanceState) {
// Used in either cases
// If first time, displayed, if not, hidden//
//hideNavBar();
User.init(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_startup);
bar = (ProgressBar)this.findViewById(R.id.progressBar);
mManager = new StartupManager(this);
// Returns true if data was corrupt before
if (mManager.isDataCorrupt()) {
bar.setVisibility(View.VISIBLE);
loadImageContent();
// Reset watch to default black
// Internally starts NewMainActivity
ErrorManager.fixCorruptData(bar, this);
} else {
// Stays true until user selects watch
if (mManager.isUserFirstTime()) {
// Initialize purchase retriever.
// The rest will be done when the observer reports that purchase data has been retrieved.
mPurchases = PurchaseRetriever.getInstance(StartupActivity.this);
mPurchases.addObserver(new FirstStartupObserver(this));
StartupManager.FIRST = true;
loadImageContent();
} else {
// NOT first time starting app.
mPurchases = PurchaseRetriever.getInstance(StartupActivity.this);
mPurchases.addObserver(new AfterFirstStartupObserver(this));
loadImageContent();
}
}
}
// Two main dialogs used
public void showTutorialDialog() {
AlertDialog tutorialDialog = new AlertDialog.Builder(this)
.setTitle(R.string.tutorial_question_title)
.setCancelable(false)
.setMessage(R.string.tutorial_question)
.setPositiveButton(getResources().getString(R.string.tutorial_question_pos), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// Take to tutorial
// Assume isn't backer for now..
finish();
Intent i = new Intent(StartupActivity.this, TutorialActivity.class);
i.putExtra("from", "StartupActivity");
startActivity(i);
}
})
.setNegativeButton(getResources().getString(R.string.tutorial_question_neg), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// No tutorial, ask if they are a backer
showBackerDialog();
}
}).show();
tutorialDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(Color.RED);
tutorialDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(Color.RED);
}
private void showBackerDialog() {
// Show AlertDialog ask if they are kickstarter backer
AlertDialog askDialog = new AlertDialog.Builder(this)
.setTitle(getResources().getString(R.string.startup_dialog_title))
.setCancelable(false)
.setMessage(getResources().getString(R.string.startup_dialog_message))
.setPositiveButton(getResources().getString(R.string.startup_dialog_pos), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// User is a backer, take to watch chooser screen, then it takes to login screen
// Also look at Timer with TimerTask
new Thread(new Runnable() {
#Override
public void run() {
try {
Intent i = new Intent(StartupActivity.this, WatchChooserActivity.class);
i.putExtra("from", "StartupActivityBacker");
startActivity(i);
} finally {
finish();
}
}
}).start();
}
})
.setNegativeButton(getResources().getString(R.string.startup_dialog_neg), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// User is not a backer, take to MainActivity
new Thread(new Runnable() {
#Override
public void run() {
try {
Intent i = new Intent(StartupActivity.this, WatchChooserActivity.class);
i.putExtra("from", "StartupActivityNonBacker");
startActivity(i);
} finally {
finish();
}
}
}).start();
}
}).show();
askDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(Color.RED);
askDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(Color.RED);
}
Here is the code for FirstStartupObserver.'
public class FirstStartupObserver implements Observer {
private StartupActivity startupActivity;
public FirstStartupObserver(StartupActivity startupActivity) {
this.startupActivity = startupActivity;
}
// Called when the observable is done loading purchase detail
// (Only called when user runs app first time)
#Override
public void update(Observable observable, Object data) {
// Set default first-time watch
// Query product data (the Watchfaces purchased in the form of a WatchFace object)
PurchaseRetriever mPurchases = PurchaseRetriever.getInstance(startupActivity);
if (mPurchases.hasSuccess()) {
ArrayList<DynamicLoader.WatchFace> facesOwned = mPurchases.getPurchasedFaces();
for (DynamicLoader.WatchFace f : facesOwned) {
f.setPurchased(true);
}
// Check if coming from v1.4
if (UpgradeManager.isUpgrading(startupActivity)) {
// Then it calls the code below, but after the async task.
String accessCode = UpgradeManager.getOldAccessCode(startupActivity);
String accessToken = UpgradeManager.getOldAccessToken(startupActivity);
UpgradeManager.migrateBacker(startupActivity, accessCode, accessToken);
} else {
// Ask if they want to see tutorial.
// This is when the exception occurs!!!
startupActivity.showTutorialDialog();
}
return;
} else {
Log.d("TAG", "Showing fail dialog");
DialogUtils.showIabFailDialog(startupActivity, this);
}
}
}
token android.os.BinderProxy#1989547c is not valid; is your activity
running?
This means that you're trying to show your popup while your activity is being destroyed or after it's destroyed.
You can check if your activity isDestroyed like below:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && !isDestroyed()) {
showTutorialDialog();
}
If you're supporting below api 17 devices you can try to use isFinishing in else case. I did not test if it's working as expected. (If i'm wrong please correct me.)
else {
if (!isFinishing()) {
showTutorialDialog();
}
}
Or for a quick fix you can surround with try catch
This is usually caused by doing something in an AsyncTask or other background task which holds a reference to the Activity and tries to display the dialog when the work is done. In this case, it sounds like your FirstStartupObserver is holding a reference to the activity and trying to show a dialog, but the activity may have been destroyed by the time PurchaseRetriever completes its work.
Don't try to test the activity state, and don't catch the BadTokenException. That just masks the problem. The simplest solution would be to cancel the PurchaseRetriever when the activity is paused. If you want the background work to survive configuration changes like rotations but still be restricted to the user-perceived lifetime of the activity, do the work in a retained fragment. Finally, if the background work should continue when the user navigates between activities or puts the app in the background, do the work in a Service and save the result where the activity can retrieve it.
token android.os.BinderProxy#1989547c is not valid; is your activity
running?
You are trying to load the AlertDialog too early, when the Activity doesn't exist! In my apps I load a little tutorial when the activity lifecycle is completed:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash_screen);
...
...
...
showTutorialDialog();
}

What happens after onClick is finished. Android

In my app after they press an on screen button. In the listener I do some check to see if they win. When they win i set a boolean like so:
button.setOnClickListener( new View.OnClickListener()
{
#Override
public void onClick(View view)
{
/** check some things **/
aWin = true;
}
}
I am wondering. Where does the code go after the onClick. Am i suppose to call the function in the onClick?
I have looked everywhere for an answer, I am very new to android programming.
If by "the function" you mean a funcion that you have developed, then Yes, you should call whatever function you want to execute in the onClick method.
For example:
button.setOnClickListener( new View.OnClickListener()
{
#Override
public void onClick(View view)
{
/** check some things **/
aWin = true;
//Example
this.informUser(aWin) //Call your function here
}
}
If by "the funcion" you mean the onClick, then no, you shouldn't call it, Android OS should do it for you.
Where does the code go after the onClick. Am i suppose to call the
function in the onClick?
It depends on what you do in the onClick.
For example :
button.setOnClickListener( new View.OnClickListener()
{
#Override
public void onClick(View view)
{
/** check some things **/
aWin = true;
}
}
In your code above, the code will stop at aWin = true;.
Now lets say you want to go to another Activity after a click happened :
button.setOnClickListener( new View.OnClickListener()
{
#Override
public void onClick(View view)
{
/** check some things **/
Intent i = new Intent(this, AnotherActivity.class);
startActivity(i);
}
}
The onClick will end when your apps go to another activity.
UPDATE
Lets say you want to "refresh" your TextView after a click happened :
button.setOnClickListener( new View.OnClickListener()
{
#Override
public void onClick(View view)
{
/** check some things **/
aWin = true;
if(aWin)
myText.setText("WIN");
else
myText.setText("LOSE");
}
}
Feel free to comment if you still have some questions (although no guarantee i can answer it) :)

Android: Prevent multiple onClick events on a button (that has been disabled)

A button triggers an action that should only be invoked once. The button is disabled and hidden in the onClick handler before the action is performed:
someButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
someButton.setEnabled(false);
someButton.setClickable(false);
someButton.setVisibility(View.GONE);
performTaskOnce();
}
});
private void performTaskOnce() {
Log.i("myapp", "Performing task");
//Do something nontrivial that takes a few ms (like changing the view hierarchy)
}
Even though the button is disabled immediately, it is nonetheless possible to trigger multiple "onClick" events by tapping multiple times very quickly. (i.e. performTaskOnce is called multiple times). Is seems that the onClick events are queued before the the button is actually disabled.
I could fix the problem by checking in every single onClick handle whether the corresponding button is already disabled but that seems like a hack. Is there any better way to avoid this issue?
The problem occurs on Android 2.3.6, I cannot reproduce it on Android 4.0.3. But given the rarity of 4.x devices it is not an option to exclude older devices.
You could set a boolean variable to true when the button is clicked and set it to false when you're done processing the click.
This way you can ignore multiple clicks and not having to disable the button possibly avoiding annoying flickering of the button.
boolean processClick=true;
someButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(processClick)
{
someButton.setEnabled(false);
someButton.setClickable(false);
someButton.setVisibility(View.GONE);
performTaskOnce();
}
processClick=false;
}
});
private void performTaskOnce() {
Log.i("myapp", "Performing task");
//Do something nontrivial that takes a few ms (like changing the view hierarchy)
}
In the interest of keeping DRY:
// Implementation
public abstract class OneShotClickListener implements View.OnClickListener {
private boolean hasClicked;
#Override public final void onClick(View v) {
if (!hasClicked) {
onClicked(v);
hasClicked = true;
}
}
public abstract void onClicked(View v);
}
// Usage example
public class MyActivity extends Activity {
private View myView;
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myView.setOnClickListener(new OneShotClickListener() {
#Override public void onClicked(View v) {
// do clicky stuff
}
});
}
}
Bit late but this might be of use to someone. In my case I am calling another activity so;
Declare a boolean;
boolean clickable;
In the click listener;
if(clickable){
// Launch other activity
clickable = false;
}
Enable when onResume is called;
#Override
public void onResume() {
Log.e(TAG, "onResume");
super.onResume();
clickable = true;
}
You can use RxView(com.jakewharton.rxbinding2.view.RxView) is an extension around RxJava that created by Jake Wharton.
To integrate it to project you should use implementation 'com.jakewharton.rxbinding3:rxbinding:3.1.0'
Simple Java usage:
RxView.clicks(yourButton)
.sample(500, TimeUnit.MILLISECONDS)
.subscribe { action() }
In Kotlin you can create extension function to handle your clicks:
View.singleClick(action: () -> Any) {
RxView.clicks(this)
.sample(500, TimeUnit.MILLISECONDS)
.subscribe { action() }
}
Sample:
Kotlin
yourButton.singleClick({
//do some stuff here
})
Java
SingleClickListenerKt.singleClick(yourButton, () -> {
doSomeStuff();
return null;
});
Note: you can use any RxJava operators like debounce, map, first, etc if you wish.
declare a varieble
and use it as
boolean boo = false;
someButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(boo==false){
someButton.setEnabled(false);
someButton.setClickable(false);
someButton.setVisibility(View.GONE);
boo = true;
}
}
});
by this you prevent multiple clicks on your button
hope it help

Categories