Android bundles and messages (some times multiple) - android

Still new to android/java and quite confused about bundles, messaging and handlers (apologies if my terminology is not quite correct). I have a custom dialog class which can display multiple dialogs. Listeners are set up to pass back data via a handler to the main calling activity.
The data passed back might be one item or many. In my testing I am attempting to send two items back. I have tried this a number of ways. I am always successful in transmitting a single item and having the handler receive it and extract it. I fail when doing multiple items (in slightly different ways.)
If I put two items into the bundle and send just one message, the handler appears to only receive the 2nd bundle item, not the first.
If I put one item in the bundle, send, clear the bundle and then put the 2nd item in the bundle and send, nothing seems to be received by the handler and the activity hangs.
I have also used the output of msg.toString() and note that if two messeages are sent, the "when" of the second is 0. Don't know if that matters or not.
Also, I have tried passing message by use of msg.sendToTarget as well as handler.sendMessage(msg) but it does not seem to matter which is used.
Code snips and output here: http://pastebin.com/xtUatEVu
I've left in but commented out some of the other things tried. I really do not understand what I am doing wrong.

Well after some extensive experimentation I've discovered a few things. The primary problem was that a message can only be used once, i.e, it is not a reusable envelope which you can put new letters and send again. Additionally, make sure the bundle key is unique. Note that I also discovered msg.what which is used to store the dialogID.
The Handler
private Handler uiMsgHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
Log.i(TAG, "%%%% in the uiMsgHandler");
// msg.what() contains the dialogID. The bundle key is the itemID
if (msg != null) {
int DlgId = 0;
int ItemId = 0;
String value = ""; //leave it to each case to recast the value
String element = "";
Bundle b = new Bundle();
Set<String> s = null;
b = msg.getData();
Log.i(TAG,"bundle is "+b);
DlgId = msg.what;
Log.i(TAG,"DigId is "+DlgId);
switch (DlgId) {
case 1:
s = b.keySet(); //find the set of keys in this message bundle
Log.i(TAG,"s is "+s.toString());
Log.i(TAG,"s.size is "+s.size());
if (s.size() < 100) { // we allow up to 100 items, 99 is reserved
Iterator itr = s.iterator();
while (itr.hasNext()) {
element = (String) itr.next();
ItemId = Integer.parseInt(element.substring(0,1));
value = b.getString(element);
Log.i(TAG,"ItemID is "+ItemId+" value is "+value+" itr.next "+itr.hasNext());
// now we can handle each specific item
switch (ItemId) {
case 1:
Log.i(TAG,"Bundle data for Dialog "+DlgId+" Item "+ItemId+" is "+value);
// do something
// close the dialog
break;
case 2:
Log.i(TAG,"Bundle data for Dialog "+DlgId+" Item "+ItemId+" is "+value);
// do something
// close the dialog
break;
case 99:
Log.i(TAG,"Bundle data for Dialog "+DlgId+" Item "+ItemId+" is "+value);
// Cancel button was pressed
// close the dialog
break;
default: /* item out of range */
Log.i(TAG,"Error ItemID OoR: DialogID "+DlgId+" with message item id "+ItemId+" is out of range");
// close the dialog and toast w/ message
break;
} // end of ItemID switch
} // end of ItemID iterator while
} else { // end of number of items size check
Log.i(TAG,"too many items, must be < 100 but is "+s.size());
}
break; // end of case 1
default: /* dialog id was out of range */
Log.i(TAG,"Error: dialog id was out of range");
Log.i(TAG,"Bundle data for Dialog "+DlgId+" Item "+ItemId+"is "+value.substring(2));
// close the dialog
// toast with a message
break;
} // end of Dialog switch
} // msg null check
}
};
=====================================================================
Portion of the custom dialog
acceptButton = (Button) dialogview.findViewById(r_id_accept);
rejectButton = (Button) dialogview.findViewById(r_id_reject);
acceptButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Inform the user the button has been clicked
Log.i(TAG, "ACCEPT BUTTON PRESSED");
// now we are going to do the messaging
// addOptQty is item id 01
// addOptPrice is item id 02
// msg.what contains the dialogID
msg.what=id;
b.putString("1",""+addOptQty);
b.putString("2",""+addOptPrice);
msg.setData(b);
// now send the message to the handler
try {
mResponseHandler.sendMessageDelayed(msg,10);
} catch (Exception e) {
Log.i(TAG, "ERROR SENDING MESSAGE");
}
}
});
rejectButton.setOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View v) {
//Inform the user the button has been clicked
Log.i(TAG,"LOCI BUTTON PRESSED");
msg.what=id;
b.putString("99","CANCEL");
msg.setData(b);
// now send the message to the handler
try {
mResponseHandler.sendMessageDelayed(msg,10);
} catch (Exception e) {
Log.i(TAG, "ERROR SENDING MESSAGE");
}
}
});

Related

how to add counter in android studio to quit an application

I am getting an error when I set the counter to subtract and close the application. I get an error "cannot assign value to final variable counter". If the user logins in 3 times with no success quit the application.
final int counter = 3;
//Set the OKButton to accept onClick
OKButton.setOnClickListener(new View.OnClickListener() {
#Override
//once onClick is initalized it takes user to page menu
public void onClick(View v) {
//display text that was inputed for userText and passText
user = userText.getText().toString();
pass = passText.getText().toString();
//create if loop which checks if user and pass equals the credentials
if (user.equals("pshivam") && pass.equals("Bway.857661")) {
//display toast access welcome
String welcome = "Access Granted.";
//Create a Toast to display the welcome string in the MainActivity.
Toast.makeText(MainActivity.this, welcome, Toast.LENGTH_SHORT).show();
setContentView(R.layout.account_main);
}
//create else if loop which checks if user or pass does not equals the credentials
else if (!user.equals("pshivam") || !pass.equals("Bway.857661")){
//displays previous entry
userText.setText(user);
passText.setText(pass);
//allows user to re-enter credentials.
user = userText.getText().toString();
pass = passText.getText().toString();
//display toast access fail
String fail = "Access Denied! Please Try again.";
//Create a Toast to display the fail string in the MainActivity.
Toast.makeText(MainActivity.this, fail, Toast.LENGTH_SHORT).show();
counter--;
if(counter == 0){
finish();
}
}
}
});
}
}
Do something like this :
OKButton.setOnClickListener(new View.OnClickListener() {
int counter = 3;
#Override
//once onClick is initalized it takes user to page menu
public void onClick(View v) {
You can also call a function from inside onClick which will decrement the variable, or use a static field declared in your class
This How to increment a Counter inside an OnClick View Event and How do I use onClickListener to count the number of times a button is pressed? might help.
Edit:
What you are doing in else part doesn't make sense. You are setting text for userText and passText that you just got using getText() from these. Then you are storing these same values to user and pass. But you aren't using these variables anywhere and they get new values when onClick is called again. Why not keep it simple :
else {
//display toast access fail
String fail = "Access Denied! Please Try again.";
//Create a Toast to display the fail string in the MainActivity.
Toast.makeText(MainActivity.this, fail, Toast.LENGTH_SHORT).show();
counter--;
if(counter == 0){
finish();
}
}

Android Service does not update UI after running

I have an interesting issue that I have been trying to fix for over a week. Its on Android and involves a service running in the background to send a message on an app.
It is quite complex so I'll list the stages below:
1 - User enters message
2 - User selects 'send' button which launches the apps main service (ComService/START_STICKY) and activity (HomeScreen) hides the EditText box used for the message, replacing it with a TextView with the words 'Sending'
3 - Service spawns worker thread
4 - Service gets entered text off of activity and connects to server
5 - Service sends the message and then gets result from server
6 - Service disconnects from server
7 - Service updates activity to show sent message and shows the edit text
box again, as well as hides the TextView with the 'Sending' word
The issue is with stage 7. It uses a handler and message to communicate with the activity, as well as a separate class which holds the state of all of the activities in the app (to check if the UI is ok to update), but I commented this out from the code and the issue still exists so it is not this. The current set up works completely fine when the debugger is attached without any issues (why there is no logcat) and on the odd occasion when closing the app down and starting it up again. The problem begins when the debugger is detached and the app closed (via recent apps) for over around 5 seconds. The service completed its job by sending the message, as the message is added to the database and the user on the other end gets it, it is only the updating of the UI that is a problem, everything else seems to work fine!
Before sending the message, the service also connects to the server if there are any unread messages to indicate to other users that the user just read it. It follows very similar steps as above but was commented out and the issue still stays the same.
Ill post the code for the relevant steps below:
Stage 2
// Starts service to communicate with the server to send a message
Intent service = new Intent(this, ComService.class);
service.putExtra(ComService.requestType, ComService.sendTextMessage);
startService(service);
Stage 3
// Run when the service is being created
#Override
public int onStartCommand(Intent newIntent, int flags, int startId)
{
intent = newIntent;
currentInstance = this;
// Launches processing thread
ServiceHelper serviceHelper = new ServiceHelper(newIntent, this);
serviceHelper.start();
return Service.START_STICKY;
}
Stage 4/5/6/7
// Sends a message with only text content
public void startText()
{
// Initialises the class holding activity data
StateManager sm = new StateManager(context);
// Gets the data ready to be sent
if(sm.getHomeScreen())
{
// Friend id and time
friendId = HomeScreen.getFriendId();
// Gets the message text
messageTextContent = HomeScreen.getTextMessage(); // STAGE 4
}
else
{
allGood = false;
}
try
{
// Checks if any errors
if(allGood)
{
// Checks if message to be sent is blank
if(!messageTextContent.equals("") & messageTextContent.equals(" ") & !(messageTextContent == "") & !(messageTextContent == " "))
{
// Connects
(sh.new Utility()).connect(); // STAGE 4
// Checks if logged in
if((sh.new CheckLogin()).start())
{
// Sends request
sh.getNetwork().sendData(ServiceHelper.sendMessageTextRequest);
// Sends the friend id who message is addressed to
sh.getNetwork().sendData(friendId);
// Gets message date
messageDate = sh.getNetwork().getDataAsString();
// Sends the message type
sh.getNetwork().sendData(textType);
// Sends the message text
sh.getNetwork().sendData(messageTextContent); // STAGE 5
// Gets the message number
messageNumber = Integer.parseInt(sh.getNetwork().getDataAsString());
// Gets result and check if successful
String result = sh.getNetwork().getDataAsString(); // STAGE 5
if(!result.equals(ServiceHelper.requestSuccessful))
{
// Not successful
allGood = false;
errorMessage = result;
}
else
{
// Successful and saves data to database
addDatabaseTextMessage();
}
// Sends received indicator
sh.getNetwork().sendData(ServiceHelper.receivedIndicator);
}
else
{
allGood = false;
errorMessage = tryAgainMsg;
}
// Closes connection
(sh.new Utility()).finishConnection(); // STAGE 6
// Gets current friend record
UserDatabase db = new UserDatabase(context);
FriendRecord fr = db.getFriendRecord(Integer.parseInt(friendId));
// Increments message numbers by one and updates database
fr.setTotalExchanged(fr.getTotalExchanged() + 1);
db.updateFriendRecord(fr);
}
else
{
allGood = false;
errorMessage = msgBlank;
}
}
else
{
allGood = false;
errorMessage = tryAgainMsg;
}
} catch(IOException e)
{
allGood = false;
errorMessage = checkConnectionMsg;
// Adds to log cat
Log.e(this.getClass().getSimpleName(), e.getMessage());
} catch(Exception e2)
{
allGood = false;
errorMessage = tryAgainMsg;
// Adds to log cat
Log.e(this.getClass().getSimpleName(), e2.getMessage());
}
// Decides on result
if(allGood)
{
// Refreshes the ui
if(sm.getHomeScreen()) // STAGE 6
{
Message msg = HomeScreen.homeScreenInterface.obtainMessage(HomeScreen.sendSuccess); // STAGE 7
HomeScreen.homeScreenInterface.sendMessage(msg); // STAGE 7
}
}
else
{
// Indicates error on ui
if(sm.getHomeScreen())
{
Message msg = HomeScreen.homeScreenInterface.obtainMessage(HomeScreen.messageSendError); // STAGE 7
msg.obj = errorMessage; // STAGE 6
HomeScreen.homeScreenInterface.sendMessage(msg); // STAGE 7
}
}
}
State 7 (updating UI)
// Deals with service responses
public static Handler homeScreenInterface = new Handler()
{
#Override
public void handleMessage(Message msg)
{
switch(msg.what)
{
...
...
case HomeScreen.sendSuccess:
// Enables and clears input
HomeScreen.messageInput.setEnabled(true);
HomeScreen.messageInput.setText("");
// Shows the message send menu and hides sending text
HomeScreen.sendMenu.setVisibility(View.VISIBLE);
HomeScreen.sendingText.setVisibility(View.GONE);
// Clears message variable
message = "";
attachment = null;
try
{
// Reloads the message list
messageFriendId = "";
currentInstance.loadMessageList(true);
} catch (Exception e)
{
currentInstance.loadingScreen.open("Error", "Try again later!", true, "Ok", currentInstance);
}
// Checks if the message is sending
isMessageSending = false;
break;
...
...
}
}
};
Try using Broadcast Receiver instead of a handler to refresh your ui.
http://developer.android.com/reference/android/content/BroadcastReceiver.html
private BroadcastReceiver bReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("UPDATE")) {
String text = intent.getStringExtra("output");
updateUI(text);
}
else if(intent.getAction().equals("RESTART")) {
//other stuff
Board.this.startService(i);
}
}
};
//from Service
Intent intent = new Intent();
intent.setAction("UPDATE");
intent.putExtra("output",modifiedSentence);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
//onStart
LocalBroadcastManager bManager = LocalBroadcastManager.getInstance(this);
IntentFilter filter = new IntentFilter();
filter.addAction("UPDATE");
filter.addAction("RESTART");
bManager.registerReceiver(bReceiver, filter);
//onPause
LocalBroadcastManager bManager = LocalBroadcastManager.getInstance(this);
bManager.unregisterReceiver(bReceiver);

Trying to get an Android jabber app to check for a string in new messages and return a toast message

I have been able to create the if statement that checks for the string and it returns the toast message that i created but it keeps showing the toast message every time i open the chat. even if the most recent message doesn't contain the string I am looking for so i am assume it isn't checking to see if it is the last message received and it doesn't check to see if it is unread. the code is below. the reason i am trying to do this is because my parents share a facebook account and i want an easy way to display if the message is signed mom or dad. the code below only has the check for mom once it works i will be adding the check for dad signature. I am using the open source message client Xabber. Thank you for help.
public void setVisibleChat(String account, String user) {
final boolean remove = !AccountManager.getInstance()
.getArchiveMode(account).saveLocally();
AbstractChat chat = getChat(account, user);
if (chat == null)
chat = createChat(account, user);
else {
// Mark messages as read and them delete from db if necessary.
final ArrayList<MessageItem> messageItems = new ArrayList<MessageItem>();
for (MessageItem messageItem : chat.getMessages()) {
if (!messageItem.isRead()) {
messageItem.markAsRead();
messageItems.add(messageItem);
}
if (chat.getLastText().contains("Mom") && (!messageItem.isRead()));{
Toast.makeText(Application.getInstance(), "Message from Mom!", Toast.LENGTH_SHORT).show();
}
}
Application.getInstance().runInBackground(new Runnable() {
#Override
public void run() {
Collection<Long> ids = getMessageIds(messageItems, remove);
if (remove)
MessageTable.getInstance().removeMessages(ids);
else
MessageTable.getInstance().markAsRead(ids);
}
});
}
visibleChat = chat;
}
You've got an extra semi-colon here
if (chat.getLastText().contains("Mom") && (!messageItem.isRead())); <------
So your next block of code containing the Toast show statement will always be executed.
Remove the semi-colon

How can I cancel a toast message that I defined in a previous activity from another intent?

I'm having trouble closing my toast message that I'm creating in the activity BarcodeActivity after I pass over the intent to another class, UPCHandler. Since I can't pass toasts through intents, I haven't been able to find a way to manipulate the toast message from the UPCHandler intent.
BarcodeActivity:
public void didScanBarcode(String barcode, String symbology)
{
// Remove non-relevant characters that might be displayed as rectangles
// on some devices. Be aware that you normally do not need to do this.
// Only special GS1 code formats contain such characters.
String cleanedBarcode = "";
for (int i = 0 ; i < barcode.length(); i++)
{
if (barcode.charAt(i) > 30)
{
cleanedBarcode += barcode.charAt(i);
}
}
try
{
//stops scanner
mBarcodePicker.stopScanning();
Log.e("CleanedUPC", cleanedBarcode);
/* Toast Setup */
LayoutInflater inflater = getLayoutInflater();
View layout = inflater.inflate(R.layout.toast_layout,
(ViewGroup) findViewById(R.id.toast_layout_root));
TextView text = (TextView) layout.findViewById(R.id.text);
text.setText("Fetching your results...");
Toast toast = BarcodeActivity.toast;
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast.setDuration(Toast.LENGTH_LONG);
toast.setView(layout);
toast.show();
#Override
public String dataRetreived()
{/*
Intent i = new Intent(getApplicationContext(), UPCHandler.class);
Bundle bundle = new Bundle();
bundle.put("value", inputTransacVal.getText());
i.putExtras(bundle);
startActivity(i);*/
ItemsDto idt = hand.getFirstUpc();
if (idt == null)
{
Log.e("BarcodeActivity:didScanBarcode", "UPC is NULL");
toast.cancel();
}
else
{
Intent intn_display = new Intent("com.ahold.scan.DISPLAYSCREEN");
Intent intn_warning = new Intent("com.ahold.scan.WARNINGSCREEN");
ImageLoader imgLoad = new ImageLoader(idt.getImageUrl(), context, idt)
*/
}
return null;
}
});
}
catch(Exception e)
{
//throws an error message to logcat if it catches one
Log.e("IntentStartError", e.toString());
}
}
There are two things you can try to do:
Close the toast before switching activities, pass an indication in your intent that the toast needs to be reshown, and show it in the new activity.
Pass the toast. Put it in a static variable somewhere, and in your new activity cancel it if it's not null. Keep in mind that it might be null, because Android can kill your process and start it again between activities.

why show always last value of arraylist in listview?

I have start a timer which call getMessage webservice which return comming message for that user arraylist size always show right number of messages but when show in list view of that message show only last message send give by web service I have use this code.
public void handleMessage(Message msg)
{
super.handleMessage(msg);
if(msg.arg1!=RECIEVEFAILURE)
{
objrReceiveMessageSiteList =(ArrayList<ReceiveMessageSiteList>)msg.obj;
System.out.println("objrReceiveMessageSiteList.get(0)"+objrReceiveMessageSiteList.get(0).getMessageStatus());
System.out.println("objrReceiveMessageSiteList.get(0)"+objrReceiveMessageSiteList.size());
if(objrReceiveMessageSiteList.size()!=0 && !objrReceiveMessageSiteList.get(0).getMessageStatus().equalsIgnoreCase("No New Message"))
{
for(int i=0;i<objrReceiveMessageSiteList.size();i++)
{
objkeyvaluepair.setMessage(objrReceiveMessageSiteList.get(i).getMessage());
objkeyvaluepair.setMessageType(objrReceiveMessageSiteList.get(i).getMessageType());
objkeyvaluepair.setTimeStamp(objrReceiveMessageSiteList.get(i).getTimeStamp());
objkeyvaluepair.setSenderFirstName(objrReceiveMessageSiteList.get(i).getSenderFirstName());
objkeyvaluepair.setSenderId(objrReceiveMessageSiteList.get(i).getSenderId());
objkeyvaluepair.setRecieverFirstName(objrReceiveMessageSiteList.get(i).getReceiverFirstName());
messagerecord.add(objkeyvaluepair);
System.out.println("MESSAGE SIZE"+messagerecord.size());
System.out.println("MESSAGE---------- findeee"+messagerecord.get(i).getMessage());
}
System.out.println("objrReceiveMessageSiteList.get(0)--------------"+objrReceiveMessageSiteList.get(0).getMessageStatus());
message.setText(""+messagerecord.size());
}
}
}
};
inside this for loop arraylist is showing right message in syste.out.println.but when sending in adapter set adapter take right size but show only last message in all list view.please help me
You are adding the same object (objkeyvaluepair) to the ArrayList each iteration through the nested for loops.
In the inner-most for loop, you should be creating a new objkeyvaluepair object and then add this new object to the ArrayList.
change this method to the following:
public void handleMessage(Message msg)
{
super.handleMessage(msg);
if(msg.arg1!=RECIEVEFAILURE)
{
objrReceiveMessageSiteList =(ArrayList<ReceiveMessageSiteList>)msg.obj;
System.out.println("objrReceiveMessageSiteList.get(0)"+objrReceiveMessageSiteList.get(0).getMessageStatus());
System.out.println("objrReceiveMessageSiteList.get(0)"+objrReceiveMessageSiteList.size());
if(objrReceiveMessageSiteList.size()!=0 && !objrReceiveMessageSiteList.get(0).getMessageStatus().equalsIgnoreCase("No New Message"))
{
for(int i=0;i<objrReceiveMessageSiteList.size();i++)
{
//Create Local object of the Objkeyvaluepair here, for example
//ObjectKeyValuePair objkeyvaluePair=new OjectKeyvaluePair();
objkeyvaluepair.setMessage(objrReceiveMessageSiteList.get(i).getMessage());
objkeyvaluepair.setMessageType(objrReceiveMessageSiteList.get(i).getMessageType());
objkeyvaluepair.setTimeStamp(objrReceiveMessageSiteList.get(i).getTimeStamp());
objkeyvaluepair.setSenderFirstName(objrReceiveMessageSiteList.get(i).getSenderFirstName());
objkeyvaluepair.setSenderId(objrReceiveMessageSiteList.get(i).getSenderId());
objkeyvaluepair.setRecieverFirstName(objrReceiveMessageSiteList.get(i).getReceiverFirstName());
messagerecord.add(objkeyvaluepair);
System.out.println("MESSAGE SIZE"+messagerecord.size());
System.out.println("MESSAGE---------- findeee"+messagerecord.get(i).getMessage());
}
System.out.println("objrReceiveMessageSiteList.get(0)--------------"+objrReceiveMessageSiteList.get(0).getMessageStatus());
message.setText(""+messagerecord.size());
}
}
}
};

Categories

Resources