I am trying to implement a WebSocket client in Android Studio.
My code works fine but I'd like to clear the text boxes after the data has been set. When I tried to clear my EditText boxes after the 'SEND' button is clicked I found that they were being cleared before they were being used.
If I use the following code the contents of the text boxes gets sent,
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
start = (Button) findViewById(R.id.send);
output = (TextView) findViewById(R.id.output);
client = new OkHttpClient();
add = (EditText) findViewById(R.id.add_str);
cmd = (EditText) findViewById(R.id.cmd_str);
key = (EditText) findViewById(R.id.key_str);
data = (EditText) findViewById(R.id.data_str);
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
start();
}
});
}
But if I use the following...
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
start = (Button) findViewById(R.id.send);
output = (TextView) findViewById(R.id.output);
client = new OkHttpClient();
add = (EditText) findViewById(R.id.add_str);
cmd = (EditText) findViewById(R.id.cmd_str);
key = (EditText) findViewById(R.id.key_str);
data = (EditText) findViewById(R.id.data_str);
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
start();
add.getText().clear();
cmd.getText().clear();
key.getText().clear();
data.getText().clear();
}
});
}
I just get an empty string sent. How do I stop this? I have tried setting a sent flag that is only set after the text has been sent...
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
start();
if (sent){
add.getText().clear();
cmd.getText().clear();
key.getText().clear();
data.getText().clear();
sent = false;
}
}
});
...but the text never gets cleared.
Edit #1: Full MainActivity listing
package qdivision.org.websocketexample;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;
public class MainActivity extends AppCompatActivity {
private Button start;
private TextView output;
private OkHttpClient client;
public EditText add;
public EditText cmd;
public EditText key;
public EditText data;
public boolean sent = false;
private final class EchoWebSocketListener extends WebSocketListener {
private static final int NORMAL_CLOSURE_STATUS = 1000;
#Override
public void onOpen(WebSocket webSocket, Response response) {
String addStr = add.getText().toString();
String cmdStr = cmd.getText().toString();
String keyStr = key.getText().toString();
String dataStr = data.getText().toString();
String dataFrame = "<" + addStr + "," + cmdStr + "," + keyStr + "," + dataStr + ">";
webSocket.send(dataFrame);
webSocket.close(NORMAL_CLOSURE_STATUS, "Goodbye !");
sent = true;
}
#Override
public void onMessage(WebSocket webSocket, String text) {
output("Receiving : " + text);
}
#Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
output("Receiving bytes : " + bytes.hex());
}
#Override
public void onClosing(WebSocket webSocket, int code, String reason) {
webSocket.close(NORMAL_CLOSURE_STATUS, null);
//output("Closing : " + code + " / " + reason);
}
#Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
output("Error : " + t.getMessage());
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
start = (Button) findViewById(R.id.send);
output = (TextView) findViewById(R.id.output);
client = new OkHttpClient();
add = (EditText) findViewById(R.id.add_str);
cmd = (EditText) findViewById(R.id.cmd_str);
key = (EditText) findViewById(R.id.key_str);
data = (EditText) findViewById(R.id.data_str);
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
start();
/*add.getText().clear();
cmd.getText().clear();
key.getText().clear();
data.getText().clear();*/
}
});
}
private void start() {
Request request = new Request.Builder().url("ws://192.168.1.84:81/").build(); //"ws://echo.websocket.org"
EchoWebSocketListener listener = new EchoWebSocketListener();
WebSocket ws = client.newWebSocket(request, listener);
client.dispatcher().executorService().shutdown();
}
private void output(final String txt) {
runOnUiThread(new Runnable() {
#Override
public void run() {
output.setText(output.getText().toString() + "\n\n" + txt);
}
});
}
}
First of all, about the sent flag. If you are using another thread for settings its value, does not mean, this thread has to wait for it to read the value. In the if statement, if it is not true, it will skip the body. So, as soon as start() is called, assuming that start() is running on another thread, this thread will read the next statement and skip the loop.
Try using something like an OnCompleteListener() provided with the API that you are using.
The same logic goes with the editText.getText().clear(). If you are trying to read the text in start() after any HTTP call, the program will not wait for it and execute the remaining statements.
Hope that helps
Since onOpen happens asynchronously, the values that you're trying to pass are already cleared by that time. The simplest way would be to assign the values from your EditTexts to variables and then read them in onOpen. You could also add a constructor to your Websocket implementation that accepts String as a parameter.
Maybe you can try:
data.setText("");
editText.getText().clear();
will clear the text box.
Related
Has anyone tried this API?
I'm developing a privileged system app to scan the network.
For some reason I get error 2 'Wrong parameters' when I try using it.
Granted the app MODIFY_PHONE_STATE permission, and still get the error
Here's an extract:
public class ScannerActivity extends Activity implements View.OnClickListener {
private final int PHONE_STATE_REQUEST = 1;
private Button scanButton;
private TextView resultsTextView;
private class RadioCallback extends TelephonyScanManager.NetworkScanCallback {
private List<CellInfo> mCellInfoResults;
private int mScanError;
#Override
public void onResults(List<CellInfo> cellInfoResults) {
mCellInfoResults = cellInfoResults;
ScannerActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
for (CellInfo cellInfo:mCellInfoResults) {
resultsTextView.append(" " + cellInfo.toString() + " ");
}
}
});
}
#Override
public void onError(int error) {
mScanError = error;
ScannerActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
resultsTextView.append(" Error: " + mScanError);
}
});
}
#Override
public void onComplete() {
ScannerActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
resultsTextView.append(" Scan Completed! ");
}
});
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scanner);
scanButton = (Button) findViewById(R.id.scan_button);
scanButton.setOnClickListener(this);
resultsTextView = (TextView) findViewById(R.id.results_text_view);
}
public void onClick(View view) {
NetworkScanRequest networkScanRequest;
RadioAccessSpecifier radioAccessSpecifiers[];
int bands[];
ArrayList<String> PLMNIds = new ArrayList<String>(Arrays.asList("42501"));
TelephonyManager telephonyManager = (TelephonyManager) getApplicationContext()
.getSystemService(Context.TELEPHONY_SERVICE);
bands[0] = AccessNetworkConstants.UtranBand.BAND_1;
radioAccessSpecifiers = new RadioAccessSpecifier[1];
radioAccessSpecifiers[0] = new RadioAccessSpecifier(
AccessNetworkConstants.AccessNetworkType.UTRAN,
bands,
null);
networkScanRequest = new NetworkScanRequest(
NetworkScanRequest.SCAN_TYPE_ONE_SHOT,
radioAccessSpecifiers,
0,
60,
false,
0,
PLMNIds);
telephonyManager.requestNetworkScan(networkScanRequest, AsyncTask.SERIAL_EXECUTOR,new RadioCallback());
}
}
Does anyone has an idea what parameters did i pass wrong?
I first thought that it might be LTE / 3G issue, but I get the same results both for UTRAN & EUTRAN.
I also ruled out SIM issue - the same error happens with 2 different SIMS, both successfully scanning the network form settings app for example.
OK, figured it out - for anyone who may come across this issue -
searchPeriodicity & incrementalResultsPeriodicity cannot be 0, despite the documentation,
and irrelevance of these parameters for one shot scan.
I'm a newbie android programmer that want to set text from another class
Here is the code:
MainActivity.java
EventHandler eventHandler = new EventHandler();
reader.Events.addEventsListener(eventHandler);
This one another Class but still inside the MainActivity
class EventHandler implements RfidEventsListener {
// Read Event Notification
public void eventReadNotify(RfidReadEvents e){
TagData[] myTags = myReader.Actions.getReadTags(100);
if (myTags != null)
{
for (int index = 0; index < myTags.length; index++)
{
System.out.println("Tag ID " + myTags[index].getTagID());
//I want to settext here
}
}
}
// Status Event Notification
public void eventStatusNotify(RfidStatusEvents e) {
System.out.println("Status Notification: " +
e.StatusEventData.getStatusEventType());
}
}
Thanks.. Regards
You can only manipulate UI elements, when your code is executed on the UI thread.
class EventHandler implements RfidEventsListener {
// Read Event Notification
public void eventReadNotify(RfidReadEvents e){
TagData[] myTags = myReader.Actions.getReadTags(100);
if (myTags != null)
{
for (int index = 0; index < myTags.length; index++)
{
System.out.println("Tag ID " + myTags[index].getTagID());
//I want to settext here
final String myText = myTags[index].getTagID();
runOnUiThread(new Runnable() {
#Override
public void run() {
myEditText.setText(myText);
}
});
}
}
}
// Status Event Notification
public void eventStatusNotify(RfidStatusEvents e) {
System.out.println("Status Notification: " +
e.StatusEventData.getStatusEventType());
}
}
This can be easily achieved by: (tested example)
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
/**
* This class was created by Anthony M Cannon on 16/05/2018.
*/
public class MainActivity extends AppCompatActivity {
private TextView textView;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
EventHandler handler = new EventHandler();
handler.test();
}
class EventHandler {
void test() {
textView.setText("Hello, from EventHandler.");
}
}
}
Here is my situation.
In this screen, I click the comments button.
The Comment activity opens and I type what I want.
The comment is added successfully in firebase and it takes me back in detail activity.
So far everything is great! Now let's add another comment. Now you see I get duplicate comments.
I hope you see that too. Now in the DetailActivity I have a method called queryFirebaseDb() and that method is called inside both onCreate() and onResume() methods. If I don't use the onResume() method the data will not be display after clicking the back button from the CommentActivity. You see where I am going now right? The question is how to avoid duplicate data after coming back from CommentActivity. Here is my code.
public class DetailActivity extends AppCompatActivity {
ArrayList<Comment> commentArrayList;
ImageView mImageView;
TextView mTitle;
TextView mDate;
TextView mDescription;
TextView mAuthor;
ToggleButton mFavBtn;
private TextView noCommentsTextView;
private TextView commentsTextView;
private ImageButton imageButton;
private FloatingActionButton mShareBtn;
private String newsTitle;
private String newsImage;
private String newsDate;
private String newsDescription;
private static String NEWS_SHARE_HASHTAG = "#EasyNewsApp";
private String date1;
private String date2;
private String newsUrl;
private String newsAuthor;
private Cursor favoriteCursor;
private DatabaseReference mDatabase;
private static Bundle bundle = new Bundle();
private Uri uri;
private RecyclerView mRecyclerView;
private DisplayCommentsAdapter displayCommentsAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
Toolbar toolbar = (Toolbar) findViewById(R.id.detail_toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Intent i = getIntent();
mAuthor = (TextView) findViewById(R.id.detail_author);
mImageView = (ImageView) findViewById(R.id.detail_image_view);
mTitle = (TextView) findViewById(R.id.detail_title);
mDate = (TextView) findViewById(R.id.detail_publish_date);
mDescription = (TextView) findViewById(R.id.detail_description);
noCommentsTextView = (TextView)findViewById(R.id.noCommentsTextView);
commentsTextView = (TextView)findViewById(R.id.commentsTextView);
mShareBtn = (FloatingActionButton) findViewById(R.id.share_floating_btn);
mFavBtn = (ToggleButton) findViewById(R.id.fav_news_btn);
imageButton = (ImageButton)findViewById(R.id.detail_comment_image_btn);
mRecyclerView = (RecyclerView)findViewById(R.id.recycler_comments);
LinearLayoutManager manager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(manager);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.addItemDecoration(new SimpleDividerItemDecoration(this));
commentArrayList = new ArrayList<>();
mDatabase = FirebaseDatabase.getInstance().getReference();
mFavBtn.setTextOn(null);
mFavBtn.setText(null);
mFavBtn.setTextOff(null);
newsAuthor = i.getStringExtra("author");
newsImage = i.getStringExtra("image");
newsTitle = i.getStringExtra("newsTitle");
newsDate = i.getStringExtra("date");
newsDescription = i.getStringExtra("description");
newsUrl = i.getStringExtra("url");
date1 = newsDate.substring(0, 10);
date2 = newsDate.substring(11, 19);
Picasso.with(this).load(newsImage)
.placeholder(R.drawable.ic_broken_image)
.into(mImageView);
mTitle.setText(newsTitle);
mAuthor.setText("Author: " + newsAuthor);
mDescription.setText(newsDescription);
mDate.setText(date2 + ", " + date1);
mShareBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent shareIntent = createShareNewsIntent();
startActivity(shareIntent);
}
});
imageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent commentIntent = new Intent(DetailActivity.this, CommentActivity.class);
commentIntent.putExtra("newsTitle",newsTitle);
startActivity(commentIntent);
}
});
/**
* Handling the add/remove news part. We check if the specific news article
* exists in favourite.db.
*/
favoriteCursor = getContentResolver().query(FavouriteContract.FavouriteEntry.CONTENT_URI,
null,
FavouriteContract.FavouriteEntry.COLUMN_NEWS_TITLE + "=?",
new String[]{newsTitle},
null);
/**
* If yes then set the toggle button to true
*/
if (favoriteCursor.getCount() > 0) {
try {
mFavBtn.setChecked(true);
} finally {
favoriteCursor.close();
}
}
/**
* Else click the toggle button to add the news article as favourite
*/
mFavBtn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, final boolean isChecked) {
/**
* If checked the add the news article as favourite.
*/
if (isChecked) {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... voids) {
ContentValues contentValues = new ContentValues();
contentValues.put(FavouriteContract.FavouriteEntry.COLUMN_NEWS_TITLE, newsTitle);
contentValues.put(FavouriteContract.FavouriteEntry.COLUMN_NEWS_AUTHOR, newsAuthor);
contentValues.put(FavouriteContract.FavouriteEntry.COLUMN_NEWS_DESCRIPTION, newsDescription);
contentValues.put(FavouriteContract.FavouriteEntry.COLUMN_NEWS_URL, newsUrl);
contentValues.put(FavouriteContract.FavouriteEntry.COLUMN_NEWS_URL_TO_IMAGE, newsImage);
contentValues.put(FavouriteContract.FavouriteEntry.COLUMN_NEWS_PUBLISHED_AT, newsDate);
//The actual insertion in the db.
uri = getContentResolver().insert(FavouriteContract.FavouriteEntry.CONTENT_URI, contentValues);
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
Toast.makeText(DetailActivity.this, "Article with title: " + newsTitle + " was added", Toast.LENGTH_SHORT).show();
}
}.execute();
} else {
/**
* If you uncheck the toggle button then delete the news article from the favourite db.
*/
Uri newsTitleOfFavNews = FavouriteContract.FavouriteEntry.buildNewsUriWithTitle(newsTitle);
//String title = uri.getPathSegments().get(1);// Get the task ID from the URI path
getContentResolver().delete(
newsTitleOfFavNews,
null,
null);
Toast.makeText(DetailActivity.this, "News article deleted from favourites ", Toast.LENGTH_SHORT).show();
}
}
});
queryFirebaseDb();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.detail_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
if(item.getItemId() == R.id.detail_browser_btn){
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(newsUrl));
startActivity(browserIntent);
} if(item.getItemId() == android.R.id.home){
NavUtils.navigateUpFromSameTask(this);
return true;
}
return true;
}
private Intent createShareNewsIntent() {
Intent shareIntent = ShareCompat.IntentBuilder.from(this)
.setType("text/plain")
.setText(NEWS_SHARE_HASHTAG + "\n\n\n" + newsTitle
+ "\n\n\n" + newsDescription
+ "\n\n\n" + newsDate)
.getIntent();
return shareIntent;
}
#Override
protected void onStart() {
super.onStart();
//queryFirebaseDb();
}
#Override
protected void onRestart() {
super.onRestart();
queryFirebaseDb();
//displayCommentsAdapter.notifyDataSetChanged();
}
public void queryFirebaseDb(){
/**
* Querying the database to check if the specific article has comments.
*/
mDatabase = FirebaseDatabase.getInstance().getReference();
Query query = mDatabase.child("comments").orderByChild("newsTitle").equalTo(newsTitle);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
for(DataSnapshot dataSnapshots : dataSnapshot.getChildren()){
Comment comment = dataSnapshots.getValue(Comment.class);
//mUserDatabase = FirebaseDatabase.getInstance().getReference().child("Users").child(userId);
commentArrayList.add(comment);
displayCommentsAdapter = new DisplayCommentsAdapter(this,commentArrayList);
mRecyclerView.setAdapter(displayCommentsAdapter);
displayCommentsAdapter.setCommentsData(commentArrayList);
//Log.d(LOG_TAG, String.valueOf(commentArrayList.size()));
}
noCommentsTextView.setVisibility(View.GONE);
//commentsTextView.setVisibility(View.VISIBLE);
}else{
//Toast.makeText(DisplayComments.this,"There are no comments posted",Toast.LENGTH_LONG).show();
noCommentsTextView.setVisibility(View.VISIBLE);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
/*
#Override
protected void onPause() {
super.onPause();
bundle.putBoolean("ToggleButtonState", mFavBtn.isChecked());
}
#Override
public void onResume() {
super.onResume();
mFavBtn.setChecked(bundle.getBoolean("ToggleButtonState",false));
}
*/
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mFavBtn.setChecked(savedInstanceState.getBoolean("ToggleButtonState",false));
savedInstanceState.putParcelableArrayList("newsList",commentArrayList);
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("ToggleButtonState",mFavBtn.isChecked());
outState.getParcelableArrayList("newsList");
}
}
and
public class CommentActivity extends AppCompatActivity {
private static final String REQUIRED = "Required";
private static final String TAG = CommentActivity.class.getSimpleName();
Toolbar toolbar;
DatabaseReference mDatabase;
EditText titleEt;
EditText bodyEt;
Button commentBtn;
String newsTitle;
Intent i;
String name;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_comment);
toolbar = (Toolbar) findViewById(R.id.comment_toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle("Add comment");
mDatabase = FirebaseDatabase.getInstance().getReference();
titleEt = (EditText) findViewById(R.id.comment_title);
bodyEt = (EditText) findViewById(R.id.comment_body);
commentBtn = (Button) findViewById(R.id.comment_btn);
i = getIntent();
newsTitle = i.getStringExtra("newsTitle");
commentBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
submitPost();
}
});
}
private void submitPost() {
final String title = titleEt.getText().toString();
final String body = bodyEt.getText().toString();
// Title is required
if (TextUtils.isEmpty(title)) {
titleEt.setError(REQUIRED);
return;
}
// Body is required
if (TextUtils.isEmpty(body)) {
bodyEt.setError(REQUIRED);
return;
}
// Disable button so there are no multi-posts
setEditingEnabled(false);
Toast.makeText(this, "Posting...", Toast.LENGTH_SHORT).show();
// [START single_value_read]
final String userId = FirebaseAuth.getInstance().getCurrentUser().getUid();
mDatabase.child("Users").child(userId).addListenerForSingleValueEvent(
new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Get user value
User user = dataSnapshot.getValue(User.class);
// [START_EXCLUDE]
if (user == null) {
// User is null, error out
Log.e(TAG, "User " + userId + " is unexpectedly null");
Toast.makeText(CommentActivity.this,
"Error: could not fetch user.",
Toast.LENGTH_SHORT).show();
} else {
// Write new post
name = dataSnapshot.child("name").getValue().toString();
Calendar c = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
String strDate = sdf.format(c.getTime());
writeNewPost(userId,strDate,name,newsTitle, title, body);
}
// Finish this Activity, back to the stream
setEditingEnabled(true);
finish();
// [END_EXCLUDE]
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "getUser:onCancelled", databaseError.toException());
// [START_EXCLUDE]
setEditingEnabled(true);
// [END_EXCLUDE]
}
});
// [END single_value_read]
}
private void writeNewPost(String userId,String date,String
commentAuthor, String newsTitle, String commentTitle, String
commentBody){
String key = mDatabase.child("comments").push().getKey();
Comment comment = new Comment(userId, date,
commentAuthor,newsTitle,commentTitle,commentBody);
Map<String, Object> commentValues = comment.toMap();
Map<String, Object> childUpdates = new HashMap<>();
childUpdates.put("/comments/" + key, commentValues);
mDatabase.updateChildren(childUpdates);
}
private void setEditingEnabled(boolean enabled) {
titleEt.setEnabled(enabled);
bodyEt.setEnabled(enabled);
if (enabled) {
commentBtn.setVisibility(View.VISIBLE);
} else {
commentBtn.setVisibility(View.GONE);
}
}
}
UPDATE
I used this
#Override
protected void onRestart() {
super.onRestart();
finish();
startActivity(getIntent());
}
and voila!
Some stuff I thought you would know when doing Android:
Basically, in android, you need to understand how the life cycle works. So, when you call queryFirebaseDb() from onCreate and from onResume, your app is doing two queries at the same time when activity starts initially.
Lifecycle is like this OnCreate -> onResume. So, it makes sense that when activity starts, query gets executed once on onCreate than on onResume based on your logic.
Answer is here
I noticed that you are using ArrayList<Comment> commentArrayList;, which is an ArrayList structure, which lets you have duplicate data. And, if you look into the behavior of Firebase and how your query is structured, it is like this,
Query query = mDatabase.child("comments").orderByChild("newsTitle").equalTo(newsTitle);
This query means that you are taking all the comments, the previous comment and the new comment, (not just new comment), which I think you either just want (1) to get recently added comment or (2) to replace the old comments with new one.
The first way of doing this sounds complicated to me, though that is not impossible. But, second way of doing is rather easy.
Therefore, to solve this,
simply, replace the arrayList you have with this data.
if(dataSnapshot.exists()){
ArrayList<Comment> tempComments = new ArrayList();
for(DataSnapshot dataSnapshots : dataSnapshot.getChildren()){
Comment comment = dataSnapshots.getValue(Comment.class);
//mUserDatabase = FirebaseDatabase.getInstance().getReference().child("Users").child(userId);
tempComments.add(comment);
//Log.d(LOG_TAG, String.valueOf(commentArrayList.size()));
}
commentArrayList = tempComments; //assuming you want to store the data in the class fields
displayCommentsAdapter = new DisplayCommentsAdapter(this,commentArrayList);
mRecyclerView.setAdapter(displayCommentsAdapter);
displayCommentsAdapter.setCommentsData(commentArrayList);
noCommentsTextView.setVisibility(View.GONE);
//commentsTextView.setVisibility(View.VISIBLE);
}
I'm trying to make a button compare its value to some other variable. In the onClick method i get an error saying Variable is accessed within inner class, needs to be declared final. The problem is that the variable is supposed to be changed, so i cannot make it final. How can i fix this? Here is my code:
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class GameActivity extends Activity implements View.OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
int partA = 9;
int partB = 9;
int correctAnswer = partA * partB;
int wrongAnswer1 = correctAnswer++;
int wrongAnswer2 = correctAnswer--;
TextView textObjectA = (TextView)findViewById(R.id.textPartA);
TextView textObjectB = (TextView)findViewById(R.id.textPartB);
Button buttonObjectChoice1 = (Button)findViewById(R.id.buttonChoice1);
Button buttonObjectChoice2 = (Button)findViewById(R.id.buttonChoice2);
Button buttonObjectChoice3 = (Button)findViewById(R.id.buttonChoice3);
buttonObjectChoice1.setText("" + correctAnswer);
buttonObjectChoice2.setText("" + wrongAnswer1);
buttonObjectChoice3.setText("" + wrongAnswer2);
buttonObjectChoice1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int answerGiven = Integer.parseInt("" + buttonObjectChoice1.getText());
if(correctAnswer==answerGiven) {
}
}
});
buttonObjectChoice1.setOnClickListener(this);
buttonObjectChoice1.setOnClickListener(this);
}
public void onClick(View view) {}
}
Two approaches:
Make buttonObjectChoice1 final:
#Override
protected void onCreate(Bundle savedInstanceState) {
...
final Button buttonObjectChoice1 =(Button)findViewById(R.id.buttonChoice1);
...
buttonObjectChoice1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int answerGiven = Integer.parseInt("" + buttonObjectChoice1.getText());
...
}
});
}
Convert view at runtime:
buttonObjectChoice1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Button btn = (Button)v;
int answerGiven = Integer.parseInt("" + btn.getText());
...
}
});
Advantage of approach 2 is, it will reduce workload of compiler to generate accessor methods to access buttonObjectChoice1 object.
Try to declare the variables as private field of your class and update it accordingly in the method.
I have this onClickListener method on my login activity in my android app:
btnLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(txtEmail.getWindowToken(), 0);
imm.hideSoftInputFromWindow(txtPassword.getWindowToken(), 0);
String password = txtPassword.getText().toString();
String email = txtEmail.getText().toString();
if ((txtEmail.length() == 0) || (txtPassword.length() == 0)) {
Toast.makeText(LoginMember.this, "You need to provide values for Email and Password", Toast.LENGTH_SHORT).show();
return;
}
//Go ahead and perform the transaction
String[] params = {email,password};
new EndpointsAsyncTaskInsert(LoginMember.this).execute(params);
}
});
It sends data to Google App Engine without any problems, already my EndpointsAsyncTask class defined, etc etc
Now, my problem is, I need to also go to another activity after this, I'm not realyl sure, but If I remember well I could do this automatically when logged in by using SQLite, don't know how to accomplish it here.
Already have the activities I need declared on manifest.
It should be something like this:
#Override
public void onClick(View v){
Intent intent = new Intent(LoginMember.this, WelcomeScreen.class);
startActivity(intent);
}
My problem is that I don't know how to "add" or "append" this activity transaction into this logic, I'm fairly new to android and google app engine, Any ideas???
Thanks in advance!
EDIT
This is my EndpointsAsyncTaskInsert code:
package com.kkoci.shairlook;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.Toast;
import com.appspot.shairlook1.userEndpoint.UserEndpoint;
import com.appspot.shairlook1.userEndpoint.model.User;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.extensions.android.json.AndroidJsonFactory;
import com.google.api.client.googleapis.services.AbstractGoogleClientRequest;
import com.google.api.client.googleapis.services.GoogleClientRequestInitializer;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
/**
* Created by kristian on 04/07/2015.
*/
public class EndpointsAsyncTaskInsert extends AsyncTask<String, Void, User> implements GoogleClientRequestInitializer {
private static UserEndpoint myApiService = null;
private Context context;
EndpointsAsyncTaskInsert(Context context) {
this.context = context;
}
#Override
public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
// put it here no in MyClass
abstractGoogleClientRequest.setDisableGZipContent(true);
}
// class MyClass{} // you don't need it
#Override
protected User doInBackground(String... params) {
User response = null;
if (myApiService == null) { // Only do this once
UserEndpoint.Builder builder = new UserEndpoint.Builder(AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(), null)
// options for running against local devappserver
// - 10.0.2.2 is localhost's IP address in Android emulator
// - turn off compression when running against local devappserver
.setRootUrl("https://shairlook1.appspot.com/_ah/api/")
.setGoogleClientRequestInitializer(this);
// end options for devappserver
myApiService = builder.build();
}
try {
User users = new User();
users.setEmail(params[0]);
users.setPassword(params[1]);
users.setName(params[2]);
response = myApiService.insertUser(users).execute();
} catch (Exception e) {
Log.d("Could not Add User", e.getMessage(), e);
}
return response;
}
}
SECOND EDIT
This is how it looks right now, it's giving me 'java.lang.NoClassDefFoundError' on this line: new EndpointsAsyncTaskInsert(LoginMember.this) {
:
public class LoginMember extends Activity {
private static
//DbAdapter dbAdapter = null;
//EditText txtUserName;
EditText txtPassword;
EditText txtEmail;
Button btnLogin;
TextView Forgot_text;
Button twitter;
Button facebook;
//Button btnRegister;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
txtPassword = (EditText) findViewById(R.id.et_pw);
txtEmail = (EditText) findViewById(R.id.et_email);
btnLogin = (Button) findViewById(R.id.btn_login);
twitter = (Button) findViewById(R.id.twitter);
facebook = (Button) findViewById(R.id.facebook);
Forgot_text = (TextView) findViewById(R.id.Forgot_text);
btnLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(txtEmail.getWindowToken(), 0);
imm.hideSoftInputFromWindow(txtPassword.getWindowToken(), 0);
String password = txtPassword.getText().toString();
String email = txtEmail.getText().toString();
if ((txtEmail.length() == 0) || (txtPassword.length() == 0)) {
Toast.makeText(LoginMember.this, "You need to provide values for Email and Password", Toast.LENGTH_SHORT).show();
return;
}
//Go ahead and perform the transaction
String[] params = {email,password};
//new EndpointsAsyncTaskInsert(LoginMember.this).execute(params);
/**try{ Intent k = new Intent(LoginMember.this, WelcomeScreen.class);
startActivity(k);
}catch(Exception e){
}**/
new EndpointsAsyncTaskInsert(LoginMember.this) {
protected void onPostExecute(User result) {
super.onPostExecute(result);
// Do something with result
Intent intent = new Intent(LoginMember.this, WelcomeScreen.class);
startActivity(intent);
}
}.execute(params);
}
});
}
public void getUser(View v) {
new EndpointsAsyncTask(this).execute();
}
public void insertUser(View v) {
new EndpointsAsyncTaskInsert(this).execute();
}
}
ok, i see, maybe you should do this, i haven't tryied this yet, but could help you:
Before onCreate method, declare a var of this way:
Activity currentActivity;
then inside onCreate method do this:
currentActivity=this;
so then, when you make you Asyctask, make this:
new EndpointsAsyncTaskInsert(currentActivity.getApplicationContext()).execute(params);
Hope that helps, let's me know if was helpFull, if not i try to help you in another way.
Regards.
In EndpointsAsyncTask class there should be method named onPostExecute() which is executed when your async task is completed. This is the place where you should notify your activity to go to another activity.
There are numerous way to do that.
You can create an Interface class for instance
public interface OnTaskFinishListener{
void onFinish();
}
and then implement this interface in your caller class:
public class YourActivity extends Activity implements OnTaskFinishListener {
void onFinish(){
Intent intent = new Intent(LoginMember.this, WelcomeScreen.class);
startActivity(intent);
}
}
When you create asynctask you should pass this reference as a parameter in its constructor and keep it in task fields and when the task is done call the onFinish method.
public EndpointsAsyncTaskInsert extends AsyncTask...{
private OnTaskFinishListener listener;
public EndpointsAsyncTaskInsert(OnTaskFinishListener listener){
this.listener = listener;
}
protected void onPostExecute(..){
//notify the listener
listener.onFinish();
}
}
Second and more loosely coupled way is to use an event bus library, for example, greenrobots EventBus https://github.com/greenrobot/EventBus, then you can post an event when your task is finished, and then you can receive that event in your activity without setting up any listeners.
You can make an anonymous version of your AsyncTask class and override the onPostExecute to start the new activity after it is done.
new EndpointsAsyncTaskInsert(LoginMember.this) {
protected void onPostExecute(User result) {
super.onPostExecute(result);
// Do something with result
Intent intent = new Intent(LoginMember.this, WelcomeScreen.class);
startActivity(intent);
}
}.execute(params);
Maybe this might work
if ((txtEmail.length() == 0) || (txtPassword.length() == 0)) {
Toast.makeText(LoginMember.this, "You need to provide values for Email and Password", Toast.LENGTH_SHORT).show();
return;
}
else{
String[] params = {email,password};
new EndpointsAsyncTaskInsert(LoginMember.this).execute(params);
}
In the class which extends the Asynctask override the onpostexecute method and add the following code
Intent in=new Intent(Login.this,Welcome.class);
in.putExtra("email",email);
in.putExtra("password",password);
startActivity(in);
You can use bundle to send data from one activity to another and retrieve from the bundle in the Welcome activity
Intent in=getIntent();
String email=in.getStringExtra("email");