I have made an app for my android phone to control a robot-car via a Raspberry Pi. The code works, but now I'm trying to port the app to an Android Wear app. However, when I try to run the app on my Wear device, it crashes on startup. From the error log, it comes from the SetOnClickListeners. How should I fix these errors? Thanks in advance!
edit: The errors given by logcat are RuntimeExceptions and a NullPointerException http://puu.sh/ctfF4/49f0abe2ef.png
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonConnect = (Button) findViewById(R.id.buttonConnect);
buttonConnect.setOnClickListener(this);
buttonDisconnect = (Button) findViewById(R.id.buttonDisconnect);
buttonDisconnect.setOnTouchListener(this);
buttonReverse = (Button) findViewById(R.id.buttonReverse);
buttonReverse.setOnTouchListener(this);
buttonLeft = (Button) findViewById(R.id.buttonLeft);
buttonLeft.setOnTouchListener(this);
buttonForward = (Button) findViewById(R.id.buttonForward);
buttonForward.setOnTouchListener(this);
buttonRight = (Button) findViewById(R.id.buttonRight);
buttonRight.setOnTouchListener(this);
}
Not sure if helpful:
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouch(View v, MotionEvent event) {
if ((R.id.buttonForward == v.getId())) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
socketCommand("forward");
break;
case MotionEvent.ACTION_UP:
socketCommand("stop");
break;
}
}
else if ((R.id.buttonReverse == v.getId())) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
socketCommand("backwards");
break;
case MotionEvent.ACTION_UP:
socketCommand("stop");
break;
}
}
else if ((R.id.buttonRight == v.getId())) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
socketCommand("right");
break;
case MotionEvent.ACTION_UP:
socketCommand("stop");
break;
}
}
else if ((R.id.buttonLeft == v.getId())) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
socketCommand("left");
break;
case MotionEvent.ACTION_UP:
socketCommand("stop");
break;
}
}
return false;
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.buttonConnect: {
System.out.println("ONCLICK CONNECT");
SocketConnect.connect();
break;
}
case R.id.buttonDisconnect: {
SocketConnect.closeConnection();
break;
}
}
}
Thanks in advance!
You're probably creating a version of one of your existing layouts to work with the dpi requirements of your Android wear device, no?
I bet you don't have one or more of the following views with these specified ids in your activity_main.xml file:
buttonConnect
buttonDisconnect
buttonReverse
buttonLeft
buttonForward
buttonRight
Which will result in a NullPointerException.
Related
I was creating Ontouchlistener But i got 2 error. 1st unexpected token and 2nd Cannot resolve constructor 'Intent(anonymous android.view.View.OnTouchListener, java.lang.Class<com.krish.galaxypdfviewer.Website>)'
And when i tried onclick listener it worked without any error but i want to use Ontouchlistener
Here is the code whats wrong here?
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FloatingActionButton actionButton = findViewById(R.id.action_button);
defineView();
handleIntent();
defineActionBar();
checkPermission();
long start;
actionButton.setOnTouchListener(new View.OnTouchListener(){
#Override
public boolean onTouch(final View v, final MotionEvent event){
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
start=System.currentTimeMillis();
return true;
case MotionEvent.ACTION_UP:
if(System.currentTimeMillis()-start<500){ //Click is less than 500ms, you can adjust this value later...
//Do what you want on click over here...
}else{
openWebsite(); //It's a long click, do what you want over here...
}
return true;
default:
return false;
}
});
public void openWebsite() {
Intent intent = new Intent(this, Website.class);
startActivity(intent);
}
There's a missing closing curly brace for the onTouch method.
actionButton.setOnTouchListener(new View.OnTouchListener(){
#Override
public boolean onTouch(final View v, final MotionEvent event){
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
start=System.currentTimeMillis();
return true;
case MotionEvent.ACTION_UP:
if(System.currentTimeMillis()-start<500){ //Click is less than 500ms, you can adjust this value later...
//Do what you want on click over here...
}else{
openWebsite(); //It's a long click, do what you want over here...
}
return true;
default:
return false;
}
} // this one closes onTouch
});
I made simple dark/light mode switcher. The application OnCreate detects the mode you are on and than changes the boolean. I'm toggling this boolean and theme with button but for some reason it changes to false after second click. It only does that when the boolean is true. On false it works fine. Here's my code:
ImageButton dark_light;
boolean isDarkMode;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dark_light = findViewById(R.id.dark_light);
int nightModeFlags =
getApplicationContext().getResources().getConfiguration().uiMode &
Configuration.UI_MODE_NIGHT_MASK;
switch (nightModeFlags) {
case Configuration.UI_MODE_NIGHT_YES:
dark_light.setImageResource(R.drawable.light);
isDarkMode = true;
break;
case Configuration.UI_MODE_NIGHT_NO:
dark_light.setImageResource(R.drawable.dark);
isDarkMode = false;
break;
}
dark_light.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (!isDarkMode) {
dark_light.setImageResource(R.drawable.light);
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
isDarkMode = true;
} else {
dark_light.setImageResource(R.drawable.dark);
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
isDarkMode = false;
}
Log.d("Dark_Light", String.valueOf(isDarkMode));
}
});
}
Whenever night mode is toggled, onCreate will be called again.
getApplicationContext().getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK; always gives you the initial configuration so you are always writing the same value to isDarkMode whenever the night mode is toggled.
To get the current night mode configuration, use AppCompatDelegate.getDefaultNightMode() instead
int nightModeFlags = AppCompatDelegate.getDefaultNightMode();
switch (nightModeFlags) {
case AppCompatDelegate.MODE_NIGHT_YES:
dark_light.setImageResource(R.drawable.light);
isDarkMode = true;
break;
case AppCompatDelegate.MODE_NIGHT_NO:
dark_light.setImageResource(R.drawable.dark);
isDarkMode = false;
break;
}
I want to implement a drag and drop but it turned out to be ridiculously time consuming, here is the problematic code:
public class MyTouchListener implements View.OnTouchListener {
public static float sharedX,sharedY;
public boolean onTouch(View view, MotionEvent motionEvent) {
sharedX = motionEvent.getX();
sharedY = motionEvent.getY();
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
ClipData data = ClipData.newPlainText("", "");
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
view.startDrag(data, shadowBuilder, view, 0);
view.setVisibility(View.INVISIBLE);
return true;
case MotionEvent.ACTION_CANCEL:
break;
case MotionEvent.ACTION_MOVE:
view.setVisibility(View.VISIBLE);
break;
case MotionEvent.ACTION_UP:
view.setVisibility(View.VISIBLE);
break;
}
return false;
}
}
The action down and action cancel are being fired, although action cancel not giving correct result (motionevent.getX isn't a sane, normal value)
None of the other events fire. I can't figure out why and I gave up trying.
I have a basic hangman game, and the buttons to make the guesses are all placed on screen with ImageButtons (I had this working perfectly).
I declare the image button ID's like so:
private static final int[] BUTTON_IDS = {
R.id.imageButtonA, R.id.imageButtonB, R.id.imageButtonC, R.id.imageButtonD, R.id.imageButtonE,
R.id.imageButtonF, R.id.imageButtonG, R.id.imageButtonH, R.id.imageButtonI, R.id.imageButtonJ,
R.id.imageButtonK, R.id.imageButtonL, R.id.imageButtonM, R.id.imageButtonN, R.id.imageButtonO,
R.id.imageButtonP, R.id.imageButtonQ, R.id.imageButtonR, R.id.imageButtonS, R.id.imageButtonT,
R.id.imageButtonU, R.id.imageButtonV, R.id.imageButtonW, R.id.imageButtonX, R.id.imageButtonY, R.id.imageButtonZ
};
private List<ImageButton> buttonLetters = new ArrayList<ImageButton>();
Edited to show solution: I register their OnClick by doing:
for (int id: BUTTON_IDS) {
final ImageButton buttonLettersUsage = (ImageButton)findViewById(id);
if (buttonLetters != null) {
assert buttonLettersUsage != null;
buttonLettersUsage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(HangmanActivity.this, " " + buttonLettersUsage.getId(), Toast.LENGTH_SHORT).show();
switch (buttonLettersUsage.getId()){
case R.id.imageButtonQ:
strGuessed = "Q";
break;
case R.id.imageButtonW:
strGuessed = "W";
break;
case R.id.imageButtonE:
strGuessed = "E";
break;
// ... Repeat for rest of buttons ...
default:
break;
}
btnGuessClicked(theIncorrectGuesses, theWord);
buttonLettersUsage.setVisibility(View.INVISIBLE);
}
});
}
}
The problem is now, I've been working on the app some more since implementing this part, and all the buttonLettersUsage.getId()'s have changed.
My question is:
Will they change at any time?
I've not put any new components onto the activity, why have they changed?
Is there a better way to find out which button has been pressed, and give a different value for strGuessed depending on which has been pressed?
Many thanks.
Don't use the numerical ids in the switch case use it as follows.
switch (buttonLettersUsage.getId()){
case R.id.imageButtonA:
strGuessed = "Q";
break;
case R.id.imageButtonB:
strGuessed = "W";
break;
case R.id.imageButtonC:
strGuessed = "E";
break;
// ... Repeat for rest of buttons ...
default:
break;
}
And also don't implement onClickListener like this, use your Activity to implement View.OnClickListener and then set the listener in loop as
buttonLettersUsage.setOnClickListener(this);
Where this is the context of your activity which implements the OnClickListener
YourActivity implements View.OnClickListener{
then in oncreate(){
//add is buton
View buttonAdd = findViewById(R.id.add);
buttonAdd.setOnClickListener(this);}
then
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.add:
{
}
break;}
I'm relatively a rookie/beginner with Java/Android programming. I've been trying to make it so while I press a given button in my application it produces a DTMF tone, but when I try to use setOnTouchListener the Android Studio shows me that error. It also gives me an error for MotionEvent which states Expression expected
Here are the important parts of the code:
boolean pressedCCW = false;
class SendCCWTone extends AsyncTask<Void,Void,Void>{
#Override
protected Void doInBackground(Void... arg0){
ToneGenerator toneGen;
toneGen = new ToneGenerator(AudioManager.STREAM_DTMF,100);
while(pressedCCW){
toneGen.startTone(ToneGenerator.TONE_DTMF_1);
}
toneGen.stopTone();
toneGen.release();
createLog("CCW");
return null;
}
}
final Button buttonCCW = (Button) findViewById(R.id.counter_clockwise);
buttonCCW.setOnTouchListener(new View.OnTouchListener(){// Where the error is
#Override
public boolean onTouch(View v, MotionEvent event){// Where the other error is located
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
if(pressedCCW == false){
pressedCCW = true;
new SendCCWTone().execute();
}
break;
case MotionEvent.ACTION_UP:
pressedCCW = false;
}
return true;
}
});
You are creating OnTouchListener inside of setOnClickListener. If you need TouchListener then you should register using setOnTouchListener instead of setOnClickListener
buttonCCW.setOnTouchListener(new View.OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event){
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
if(pressedCCW == false){
pressedCCW = true;
new SendCCWTone().execute();
}
break;
case MotionEvent.ACTION_UP:
pressedCCW = false;
}
return true;
}
});
This problem can be solved if you place setOnTouchListener inside the onCreate() method of your activity.
Rather than use setOnClickListener, you can set onClick in the XML and point to a method (it does the same thing and looks nicer). In this case, you'd have a method like produceSound:
public void produceSound(View view) {
// your onClick method
}
and in the activity's XML, find where that button, counter_clockwise, is and add: android:onClick="produceSound" to the button's XML.
More here if you're curious: How exactly does the android:onClick XML attribute differ from setOnClickListener?
However, if you're using onTouch, then you will have to stick with what everyone else is suggesting. XML does not support an android:onTouch attribute.
Try to add this to your code :
implements View.OnTouchListener
and use setOnTouchListner instead of setOnClickListener.
buttonCCW.setOnListener(new View.OnTouchListener(){// Where the error is
#Override
public boolean onTouch(View v, MotionEvent event){// Where the other error is located
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
if(pressedCCW == false){
pressedCCW = true;
new SendCCWTone().execute();
}
break;
case MotionEvent.ACTION_UP:
pressedCCW = false;
}
return true;
}
});