Edit: My original question is below the line. I decided to go with a much simpler approach to setting up a button and assigning a click function. I found it at the following link. He does a good job of explaining the difference between the 2 approaches...
Android User Interface Design: Basic Buttons
I realize this is a popular question, but in all of the examples I've looked at the problem seems to be a simple detail that's been overlooked, and the detail is never the same. I'm sure this is basic. I'm just starting out with programming for Android and this is a modification of existing code.
The app has one button on a blank page, and I want the button click to send an int to my Arduino via the Amarino API. Here is my MainActivity code
package com.example.buttontest1;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Button;
import android.view.View;
import android.view.View.OnClickListener;
import at.abraxas.amarino.Amarino;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
public class MainActivity extends Activity{
private Button button;
private static final String DEVICE_ADDRESS = "00:06:66:4B:E4:23";
public Context foo1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Amarino.connect(this, DEVICE_ADDRESS);
setContentView(R.layout.main);
addListenerOnButton();
}
public void addListenerOnButton() {
//Select a specific button to bundle it with the action you want
button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
Amarino.sendDataToArduino(this, DEVICE_ADDRESS, 'j', 1);
}
});
}
protected void onStop() {
super.onStop();
// stop Amarino's background service, we don't need it any more
Amarino.disconnect(this, DEVICE_ADDRESS);
}
}
The error I see is this, referring to line 38:
The method sendDataToArduino(Context, String, char, int) in the type
Amarino is not applicable for the arguments (new
View.OnClickListener(){}, String, char, int)
So there's a problem with the context and the method?
Amarino.sendDataToArduino(this, DEVICE_ADDRESS, 'j', 1);
this here refers toView.OnClickListener's current instance. The compilation error basically says, sendDataToArduino() expects the first argument as Context but you are passing a OnClickListener
sendDataToArduino expects its first argument to be of type Context. You are passing it a View.onClickListener. Instead of passing this as the first argument, try setting up a context as mentioned here and pass that as the first argument.
Try adding the following in your onCreate method after the super call:
MainActivity.context = getApplicationContext();
Also add the following method after onCreate:
public static Context getAppContext() {
return MainActivity.context;
}
Now call the method with:
Amarino.sendDataToArduino(getApppContext(), DEVICE_ADDRESS, 'j', 1);
Teh api expects the object of Context but you pass this to:
Amarino.sendDataToArduino(this, DEVICE_ADDRESS, 'j', 1);
this is not an object of Context instead it is OnClickListener object.
Related
I have created a method in MainActivity class. I know I can call that in onCreate method and other methods in that same class. But can I call that method outside onCreate and other methods but in MainActivity class?
When I try to do that, I get an error.
The error I am getting is "Invalid method declaration" but I have already declared the method below. I am just calling it here.
package com.example.android.kabaddicounter;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
//Can we call this method here? Its giving an error
displayForPakistan(25);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void displayForPakistan(int score){
TextView scoreView = (TextView) findViewById(R.id.score_pakistan);
scoreView.setText(String.valueOf(score));
}
public void displayForIndia(int score){
TextView scoreView = (TextView) findViewById(R.id.score_india);
scoreView.setText(String.valueOf(score));
}
}
The answer is no you can't, unlike other codeflows the android codeflow runs only through callback functions called from the devices internal system.
You can for example call a method from other method but if that method will not be call from any of the callbacks , both will never get excited
With that been said, you have the exception of listener which can also call methods but there are just another type of callbacks
Read about activitys lifecycle to learn more
I'm trying to create a game log, to show what happened on each round of the game. The log is in another activity but I want to be updated constantly with whatever the player does. A player just presses buttons that do certain things. It's too much code to post, but I have made a new bundle, and an intent.
In MainActivity.
Bundle bundle = new Bundle();
Intent GameLogSwitch = new Intent(getApplicationContext(),GameLog.class);
I am trying to put this to send to the other activity but I don't know if you can put variables in it. otherwise it works with simple words such as ("key","It works")
GameLogSwitch.putExtra("Break","---BREAK---"+"\n"+Player1Name+": "+GreenResult.getText()+"("+GrTop1+","+GrTop2+","+GrTop3+")"+"\n"+Player2Name+": "+RedResult.getText()+"("+RdTop1+","+RdTop2+","+RdTop3+")");
and then of course I have this when the gamelog button is pressed
startActivity(GameLogSwitch);
Now in Gamelog.class i have this.
package com.example.adam.snookerproject;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class GameLog extends AppCompatActivity {
private TextView GameLogText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game_log);
GameLogText = (TextView) findViewById(R.id.GameLogText);
Intent GameLogSwitch = getIntent();
String myString = GameLogSwitch.getStringExtra("Break");
GameLogText.append(myString);
}
}
I have a couple of questions. First, why does append only work once with my string when I start the activity i.e when I go back and press the same button again it won't write the same thing again underneath?
Secondly, it doesn't seem to work for my "Break" key, does this have to do with the fact that there are variables in the text I'm sending? It only works for simple text like GameLogSwitch.putExtra("key","It works");
There must be an easier way to do this! Thank you.
UPDATE 1: The answer from Drv does seem to work, but when I try to do GameLogText.append(AppConstants.log) it just replaces everything in the textview no matter how many times I press the button. I think the activity is just resetting each time I start it again. Any way around this?
Make a global string in Constants class and use it wherever you want:
public class AppConstants{
public static String log="";
}
Edit the string in the class where you are sending it in intent:
AppConstants.log="---BREAK---"+"\n"+Player1Name+": "+GreenResult.getText()+"("+GrTop1+","+GrTop2+","+GrTop3+")"+"\n"+Player2Name+": "+RedResult.getText()+"("+RdTop1+","+RdTop2+","+RdTop3+")";
And use it in your class as:
package com.example.adam.snookerproject;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class GameLog extends AppCompatActivity {
private TextView GameLogText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game_log);
GameLogText = (TextView) findViewById(R.id.GameLogText);
//get your log here using AppConstants.log
}
}
Try to use getContext() instead of getApplicationContext, then check your string in debug mode
Use Callback or Interface. Fire the Interface from the Main Activity and Implement the call Interface in the Activity where you want the Textview to be Updated. Inside that method Update your Text View.
Read here More about Communication between Activity Activity and Fragment Activity
(Posted solution on behalf of the OP).
I managed to append using "\n"+AppConstants.log at the end of each output.
I am writing a code for going to the next page after clicking a button so I have written the code that I have mentioned below i just want to confirn that it is correct as i cant check it now, I know this is silly but I need help
package com.example.myfirstapp;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class DetailsActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_details);
Button btnNextScreen = (Button) findViewById(R.id.btnNextScreen);
btnNextScreen.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent nextScreen = new Intent(getApplicationContext(), JewelInfo.class);
// TODO Auto-generated method stub
startActivity(nextScreen);
}
});
}
}
Assuming that your JewelInfo extends from an Activty it looks fine.
I think you should use Intent nextScreen = new Intent(DetailsActivity.this, JewelInfo.class); instead of getApplicationContext()
The correctness of code is never checked just by looking at a bit of code. Syntactically, it seems to not contain an error. Semantically, how should we know? You need to define what you want to do, how you want it to look, etc. Basically, what are the requirements?
We can then validate the code against the requirements but not assess the correctness as that is only discerned by executing the code and evaluating the result of the execution on the device it is executed against the requirements.
use DetailsActivity.this instead of getApplicationContext(), and declare your JewelInfo activity on the manifest file : <activity android:name=".JewelInfo" />.Check this tutorial about how to switch between activities and pass data between them
I have been playing around with various examples trying to familiarize myself with AsyncTask. So far all the examples I have seen have had the AsyncTask included into the onCreate method of the main activity. Which I don't like very much, so I was wanting to see how hard it would be to separate it into its own class. So far I have this:
the main activity
package com.example.asynctaskactivity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.app.Activity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.example.asynctaskactivity.ShowDialogAsyncTask;
public class AsyncTaskActivity extends Activity {
Button btn_start;
ProgressBar progressBar;
TextView txt_percentage;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn_start = (Button) findViewById(R.id.btn_start);
progressBar = (ProgressBar) findViewById(R.id.progress);
txt_percentage= (TextView) findViewById(R.id.txt_percentage);
Log.v("onCreate","Attempt set up button OnClickListener");
btn_start.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v) {
btn_start.setEnabled(false);
new ShowDialogAsyncTask().execute();
}
});
Log.v("onCreate","Success!");
}
}
the new seperate AsyncTask class
package com.example.asynctaskactivity;
import android.os.AsyncTask;
import android.os.SystemClock;
import android.util.Log;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
public class ShowDialogAsyncTask extends AsyncTask<Void, Integer, Void>{
int progress_status;
#Override
protected void onPreExecute() {
// update the UI immediately after the task is executed
Log.v("onPreExecute","1");
super.onPreExecute();
Log.v("onPreExecute","2");
//Toast.makeText(AsyncTaskActivity.this,"Invoke onPreExecute()", Toast.LENGTH_SHORT).show();
progress_status = 0;
Log.v("onPreExecute","3");
txt_percentage.setText("downloading 0%");
Log.v("onPreExecute","4");
}
#Override
protected Void doInBackground(Void... params) {
Log.v("doInBackground","1");
while(progress_status<100){
progress_status += 2;
publishProgress(progress_status);
SystemClock.sleep(300);
}
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
progressBar.setProgress(values[0]);
txt_percentage.setText("downloading " +values[0]+"%");
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
//Toast.makeText(AsyncTaskActivity.this,"Invoke onPostExecute()", Toast.LENGTH_SHORT).show();
txt_percentage.setText("download complete");
btn_start.setEnabled(true);
}
}
Originally this was all in the main activity, hence the mentions to the elements that the asynctask should in theory update. Obviously at present this is causing runtime errors, which then got me thinking. How can I have the file seperate but still update the UI thread.
Sorry if this is a stupid question, quite new to android development and background threads in particular.
How can I have the file seperate but still update the UI thread.
Okey. So at first you know that main advantage of AsyncTask added in Activity as inner class is that you have direct access to all UI elements and it makes possible pretty "lightweight" UI updates.
But if you decided to make AsyncTask separated from Activity(which also have some benefits e.q. code is more clean and app logic is separated from appearance) class you can:
You can pass UI elements via constructor of class
You can create various setters
You can create some interface that will hold callbacks. Look at Android AsyncTask sending Callbacks to UI
This is all what you need i guess.
Add a callback interface, and let your Activity implement it.
public interface MyAsyncTaskCallback{
public void onAsyncTaskComplete();
}
In the postexecute:
myAsyncTaskCallback.onAsyncTaskComplete();
In the constructor of your AsyncTask you could pass the instance of MyAsyncTaskCallback (your Activity).
Your best way of handling this is via a Handler. Instantiate one in the activity and override the method handleMessage(). When you create ShowDialogAsyncTask class just pass in the handler and maintain a reference to it. On postExecute you can construct a message and send it via the handler method sendMessage().
A previous answer mentioned using an interface and a callback paradigm. This will work, however, there is a chance that the activity can be destroyed and won't be present when the postExecute method is executed so you would need to test for this.
I have huge problem. Have searching answer from many places but I do not find answer to question.
I have 2 classes in java. One is "main" and other is "menu"
On main, there is editText where person can type name and button ok.
When you press ok, I want to specific thing happen. That is where I need help. I am newcomer in Android.
I want that in other class, where will be main application and stuff, the entered name would be displayed. For example "Welcome " + name
I have tried many ways but I do not get it to work. So I want it to get one of 2 possible ways.
Set string in class 1 and then when it goes class 2, then it imports the string from class 1 to class 2 so I can use it.
I set string in class 2 and then in Class 1 I change the string in class 2, so the main 'data' string is actually in class 2, where I will continue using it if needed!
I have searched it from many places, used google and this database, but haven't found answer.
My codes are really nothing much, so no point pasting them here :).
Thanks for the help!
edit:// Ok, here are some codes then :)
package viimane.voimalus.incule;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class ViimaneVoimalusActivity extends Activity {
public static final String PREFS_NAME = "MyPrefsFile";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button oknupp = (Button) findViewById(R.id.nimiOK);
oknupp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
startActivity(new Intent("viimane.voimalus.in" +cule.REALMENU"));
}
});
}
}
package viimane.voimalus.incule;
import android.app.Activity;
import android.os.Bundle;
import android.widget.EditText;
public class RealMenu extends Activity {
EditText nimesisestus;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.peamenu);
}
}
You didn't show any code at all, so the answer won't be too detailed.
You can pass a String in the intent used to start the second activity, using putExtra method. In the second activity you may get the string by calling getStringExtra(). If you don't know much about starting activity and intents, there are many resources on the web, for example - this one.
To receive text input use EditText and to put text on the screen (that the user can't cange) use TextView.
Those are starting points. Next time I hope the question will be more focused.
Pass the string as parameter to the constructor of the menu class like this:
menu m = new menu(mystring);
then in the constructor save the atribute to your class
private String mystring;
menu(String mystring)
{
this.mystring = mystring;
}