I'm trying to develop a Beacon Android application using AltBeacon specification whereby the application will start the service, stop, and repeat the service again. As of now, I'm able to start and stop the services however, I'm unable to repeat to the very first 'If' statement. May I know what am I missing?
b1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view)
{
// Enter details
if (major.getText().toString().equals("") || minor.getText().toString().equals(""))
{
SuperActivityToast.create(getActivity(), new Style(), Style.TYPE_BUTTON)
.setText("Please fill Major and Minor details!")
.setDuration(Style.DURATION_LONG)
.setFrame(Style.FRAME_LOLLIPOP)
.setColor(PaletteUtils.getSolidColor(PaletteUtils.MATERIAL_PURPLE))
.setAnimations(Style.ANIMATIONS_POP).show();
}
// If user has entered
{
final Beacon beacon = new Beacon.Builder()
.setId1(uuid1)
.setId2(major.getText().toString())
.setId3(minor.getText().toString())
.setManufacturer(0x0118)
.setTxPower(-69)
.setRssi(-66)
.setBluetoothName("Hall 1")
.setDataFields(Arrays.asList(new Long[] {0l}))
.build();
BeaconParser beaconParser = new BeaconParser()
.setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25");
// Making the instance of BeaconTransmitter
final BeaconTransmitter beaconTransmitter = new BeaconTransmitter(getActivity(), beaconParser);
// Start Advertising the above Beacon Object
beaconTransmitter.startAdvertising(beacon);
// Toasting the message that beacon succesfully made
SuperActivityToast.create(getActivity(), new Style(), Style.TYPE_BUTTON)
.setText("Successfully Started!")
.setDuration(Style.DURATION_LONG)
.setFrame(Style.FRAME_LOLLIPOP)
.setColor(PaletteUtils.getSolidColor(PaletteUtils.MATERIAL_PURPLE))
.setAnimations(Style.ANIMATIONS_POP).show();
// Making some animation and changing the text of button
AlphaAnimation alphaAnimation = new AlphaAnimation(1,0);
alphaAnimation.setDuration(1500);
alphaAnimation.setFillEnabled(true);
alphaAnimation.setInterpolator(new BounceInterpolator());
b1.startAnimation(alphaAnimation);
b1.setText("Stop Broadcasting");
b1.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
beaconTransmitter.stopAdvertising();
b1.setText("Broadcast Beacon");
}
});
}
}
});
Related
I'm building a camera app with Camera2 API, relatively new to Android development. Everything is working just working out the bugs. But I have a switch camera button, going from the front camera to the back or vise-versa. If the user continuosly presses the button, the app will crash. Trying to set it up in a way that it finishes everything it needs to do before the button can be used again.
I have the button set to enabled, but after press, it disables the button until everyting finishes, then renables, but that doesn't seem to work:
//The button to switch the camera to front and back camera.
mChangeCamera = (ImageButton) findViewById(R.id.change_camera);
mChangeCamera.setEnabled(true);
mChangeCamera.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mChangeCamera.setEnabled(false);
closeCamera();
// stopBackgroundthread();
if (mTextureView.isAvailable()) {
setUpCamera(mTextureView.getWidth(), mTextureView.getHeight());
transformImage(mTextureView.getWidth(), mTextureView.getHeight());
connectCamera();
} else {
mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
}
mChangeCamera.setEnabled(true);
}
});
there has to be a simple way to do this, but not finding anyting from searchs. Anyone know how I can set it up not to crash when the user smashes the button?
Alight, so I ended up figuring out how to do this. You can use a handler with a post delay like so:
mChangeCamera = (ImageButton) findViewById(R.id.change_camera);
mChangeCamera.setEnabled(true);
mChangeCamera.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mChangeCamera.setEnabled(false);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
mChangeCamera.setEnabled(true);
}
},1000);
closeCamera();
// stopBackgroundthread();
if (mTextureView.isAvailable()) {
setUpCamera(mTextureView.getWidth(), mTextureView.getHeight());
transformImage(mTextureView.getWidth(), mTextureView.getHeight());
connectCamera();
} else {
mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
}
}
});
i did this by calculate time between multiple button presses...
create global variable in your class first
private long mLastClickTime = 0;
and a final int for duration between clicks
public static final int CLICK_TIME = 400;
then paste this code in on click of button
if (SystemClock.elapsedRealtime() - mLastClickTime < CLICK_TIME) {
return; //button pressed repeatedly so do nothing
}
mLastClickTime = SystemClock.elapsedRealtime();
// button is not pressed repeatedly so add your desired action
and of course you can increase the CLICK_TIME value if error still occurs
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();
}
Below is the oncreate to my activity. My issue is that when the activity is started it is completely unresponsive until I press the back button. Once I press the back button it works perfectly.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_packs);
count = 0;
Bundle extras = getIntent().getExtras();
if(extras != null || !equals("")){
name = extras.getString("name");
}
else{name="PackActivity";}
//getActionBar().setTitle(name);
ActionBar actionBar = getActionBar();
//actionBar.setBackgroundDrawable(R.drawable.navigation_bar_colour_image);
//actionBar.setHomeButtonEnabled(true);
actionBar.setTitle(name);
actionBar.setDisplayHomeAsUpEnabled(false);
//actionBar.hide();
database = new DataObjectDataSource(this.getApplicationContext());
//load all the packs from the DB
packs = loadPacks();
//make the request for GetPacks
sortArrayById();
if(isOnline(this)) {
HTTPRequest.getHTTPRequest(HTTPRequest.getPacksURL, this);
}
else{
dialog("No internet connection available","their is limited functionality available in offline mode",1);
}
gridView = (GridView) findViewById(R.id.packGrid);
adapter = new PackGridAdapter(this, getApplicationContext(), packs);
gridView.setAdapter(adapter);
gridView.setOnItemClickListener(this);
System.out.println(" pack_ids ");
}
I have included the dialog function as the unresponsiveness comes after it have been dismissed.
public boolean dialog(String mes,String message,int type){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
// Add the buttons
if(type==2){
builder.setMessage(message)
.setTitle(mes);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
});
}
// Create the AlertDialog
final AlertDialog dialog = builder.create();
dialog.show();
if(type==2){
final Timer t = new Timer();
t.schedule(new TimerTask() {
public void run() {
dialog.dismiss();
// when the task active then close the dialog
t.cancel(); // also just top the timer thread, otherwise, you may receive a crash report
}
}, 5000);
}
return true;
}
2 Things:
1st confirm that your ActionBar code is working (comment the actionbar part to make sure that is not culprit here) to see if the activity is responsive or not
If the 1st doesn't work, and even after commenting ActionBar activity is unresponsive .. then
2nd comment these lines:
if(isOnline(this)) {
HTTPRequest.getHTTPRequest(HTTPRequest.getPacksURL, this);
}
else{
dialog("No internet connection available","their is limited functionality available in offline mode",1);
}
I suspect you're doing some network operation on your UI Thread, that could be the cause of Activity not Responding or it must have something to do with the dialog method you're using. If you show that method code, it could lead further to diagnose.
The app I am working on has a login/register which connects to a mysql database, At first I was running everything on the UI Thread I later found out it was not working because of the against running long code on Android's UI Thread. I attempted to edit my code to run the long task on a new Thread that i added.
. Now my app registers the I see the result in mysql but my app keeps closing because of this error
android.view.ViewRootImpl$CalledFromWrongThreadException:
Only the original thread that created a view hierarchy can touch its views.
the error is understandable but I don't know how to run the View or Views back to the UI Thread.
I've done some research about the runOnuithread but I dont know where to place it in my code, or weather I placed the new Thread I added before in the wrong place to begin with please
can anyone help my fix this
here is a snippet of the code
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.register);
// Importing all assets like buttons, text fields
inputFullName = (EditText) findViewById(R.id.registerName);
inputEmail = (EditText) findViewById(R.id.registerEmail);
inputPassword = (EditText) findViewById(R.id.registerPassword);
btnRegister = (Button) findViewById(R.id.btnRegister);
btnLinkToLogin = (Button) findViewById(R.id.btnLinkToLoginScreen);
registerErrorMsg = (TextView) findViewById(R.id.register_error);
// Register Button Click event
btnRegister.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
/** According with the new StrictGuard policy, running long tasks on the Main UI thread is not possible
So creating new thread to create and execute http operations */
new Thread (new Runnable() {
#Override
public void run() {
//
String name = inputFullName.getText().toString();
String email = inputEmail.getText().toString();
String password = inputPassword.getText().toString();
UserFunctions userFunction = new UserFunctions();
JSONObject json = userFunction.registerUser(name, email, password);
// check for login response
try {
//
//
if (json.getString(KEY_SUCCESS) != null) {
registerErrorMsg.setText("");
String res = json.getString(KEY_SUCCESS);
if(Integer.parseInt(res) == 1){
// user successfully registred
// Store user details in SQLite Database
DatabaseHandler db = new DatabaseHandler(getApplicationContext());
JSONObject json_user = json.getJSONObject("user");
// Clear all previous data in database
userFunction.logoutUser(getApplicationContext());
db.addUser(json_user.getString(KEY_NAME), json_user.getString(KEY_EMAIL), json.getString(KEY_UID), json_user.getString(KEY_CREATED_AT));
// Launch Dashboard Screen
Intent dashboard = new Intent(getApplicationContext(), MainActivity.class);
// Close all views before launching Dashboard
dashboard.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(dashboard);
// Close Registration Screen
finish();
}else{
// Error in registration
registerErrorMsg.setText("Error occured in registration");
}
}//
} catch (JSONException e) {
e.printStackTrace();
}
}
}).start();
}
});
// Link to Login Screen
btnLinkToLogin.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent i = new Intent(getApplicationContext(),
LoginActivity.class);
startActivity(i);
// Close Registration View
finish();
}
});
}
}
Since you seem to have network code mixed in with UI code, I'm not going to try and write it for you. I can tell you how it should be and assume that you can rearrange the code yourself since you know what all of it does.
Ok, inside your run() you put your network code then when you need to update the UI you can have
runOnUiThread(new Runnable()
{
#Override
public void run()
{
// code to update UI
}
});
With that said, I recommend using AsyncTask for your network operations. This makes it much easier as it already has the functions for background stuff and updating the UI. You start the task and doInBackground() runs and that is where you do all of your network operations. Then you can update the UI in any of AsyncTasks other 3 methods.
See this answer for an example of using AsyncTask, along with the link to the docs above.
I am trying to implement play/pause in a single button however when i try to press it again it just stars the song again overlapping the sound playing. i have search ways and tried this method and it seems it is not working for me. thank you
private OnClickListener handler1 = new OnClickListener(){
public void onClick(View v){
MediaPlayer mpE = MediaPlayer.create(GuitarTuner.this, R.raw.test2 );
if (mpE.isPlaying()) {
mpE.pause();
} else {
mpE.start();
}
}
};"
You are creating the the media player every time. Instead try moving
MediaPlayer mpE = MediaPlayer.create(GuitarTuner.this, R.raw.test2 );
to outside of the handler.
MediaPlayer mpE = MediaPlayer.create(GuitarTuner.this, R.raw.test2 );
play.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (mpE.isPlaying()) {
mpE.pause();
play.setBackgroundResource(R.drawable.play);
} else {
mpE.start();
play.setBackgroundResource(R.drawable.pause);
}
}
});