I use a service that automatically sends me push notifications and I want to automatically press the confirm option of these notifications. I'm able to capture the notification using the code below:
import android.app.Notification;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import android.support.v4.content.LocalBroadcastManager;
import java.io.ByteArrayOutputStream;
public class NotificationHandler extends NotificationListenerService {
Context context;
#Override
public void onCreate() {
Log.e("STATE","HERE AGAIN");
super.onCreate();
context = getApplicationContext();
}
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
String pack = sbn.getPackageName();
String ticker = "";
if (sbn.getNotification().tickerText != null) {
ticker = sbn.getNotification().tickerText.toString();
}
Bundle extras = sbn.getNotification().extras;
// try {
// //sbn.getNotification().contentIntent.send();
// } catch (PendingIntent.CanceledException e) {
// e.printStackTrace();
// }
String title = extras.getString("android.title");
String text = extras.getCharSequence("android.text").toString();
int id1 = extras.getInt(Notification.EXTRA_SMALL_ICON);
Bitmap id = sbn.getNotification().largeIcon;
Log.i("NEW", "----------");
Log.i("Package", pack);
Log.i("Ticker", ticker);
Log.i("Title", title);
Log.i("Text", text);
sbn.getNotification().contentIntent.sen
for (String key : bundle.keySet()) {
Log.i("Intent", key);
}
Log.i("NEW", "----------");
Intent msgrcv = new Intent("Msg");
msgrcv.putExtra("package", pack);
msgrcv.putExtra("ticker", ticker);
msgrcv.putExtra("title", title);
msgrcv.putExtra("text", text);
if (id != null) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
id.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
msgrcv.putExtra("icon", byteArray);
}
LocalBroadcastManager.getInstance(context).sendBroadcast(msgrcv);
}
#Override
public void onNotificationRemoved(StatusBarNotification sbn) {
Log.i("Msg", "Notification Removed");
}
}
I'm having trouble figuring out how to capture the custom option for confirming the notification and then clicking it. The confirm/deny buttons look similar to the buttons on this notification. Any ideas how I can capture this?
You can get the list of actions (if it exists) from the notification by using the following code
Notification n = sbn.getNotification();
for(Action action : n.actions){
String title = action.title.toString;
...
}
You can create a button with the action-title and then write the code onClick() to execute the action corresponding to the notifications.
To be more precise - you can call
action.actionIntent.send(); // or another variation of send()
from your onClick() on the button to execute the action corresponding to the pendingIntent supplied by the app that sent the notification.
Related
I've developed a version of the native SIP Demo app provided by Google https://android.googlesource.com/platform/development/+/master/samples/SipDemo/
My Simple app registers with the SIP server and when a call invite is received on that SIP account a notification and Toast is displayed with the caller ID. I've not designed the app to run as a service or anything. After launching the activity the app registers with the SIP server and then I simple hit the home button and let the app run in the background, waiting for an incoming call.
The app functions correctly it's just that within ~ 12 - 24 hrs the app seems to have been stopped by the Android OS. I'm not sure if it's related to the native SIP stack or Android's resource manager shutting down the app but I've tried setting everything I can on the handset itself to prevent the app from being stopped like removing any battery saving settings etc.
Are there any tips to keep the app running in the background using the native SIP API?
My is code below:
CallerIDActivity.java -
package example.callerid;
//This app has been developed with a target API of 22 so as to avoid having to
//implement runtime permissions on the test handset with a higher API level.
import android.Manifest;
import android.app.Activity;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.sip.SipException;
import android.net.sip.SipManager;
import android.net.sip.SipProfile;
import android.net.sip.SipRegistrationListener;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Random;
public class CallerIDactivity extends Activity {
public SipManager manager = null;
public SipProfile me = null;
public IncomingCallReceiver callReceiver;
public CallerIDactivity (){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) createNotificationChannel();
}//end constructor
//define NotificationChannel method for use in the contructor above
//IncomingCallReciever will then use this channel to send notification of CID
public void createNotificationChannel(){
//Create the Notification but only on API 26+ as the
//notification class is new and not in the support lib
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
CharSequence name = "CHANNEL_NAME";
String description = "CID_NOTIFY";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel("CHANNEL_ID", name, importance);
channel.setDescription(description);
//Register the channel with the system: you can't change the importance
//or other notification behaviour after this
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if(notificationManager !=null) {
notificationManager.createNotificationChannel(channel);
}
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.callerid);
// Set up the intent filter. This will be used to trigger an
// IncomingCallReceiver when someone calls the SIP address used by this
// application.
IntentFilter filter = new IntentFilter();
filter.addAction("android.CallerID.INCOMING_CALL");
callReceiver = new IncomingCallReceiver();
this.registerReceiver(callReceiver, filter);
}//end onCreate
#Override
public void onStart() {
super.onStart();
// When we get back from the preference setting Activity, assume
// settings have changed, and re-login with new auth info.
initializeManager();
}
#Override
public void onDestroy() {
super.onDestroy();
closeLocalProfile();
if (callReceiver != null) {
this.unregisterReceiver(callReceiver);
Log.d("CallerID", "UnRegisteringReceiverOnDestroy ");
Toast toast = Toast.makeText(getApplicationContext(), "UnRegisteringReceiverOnDestroy", Toast.LENGTH_LONG);
toast.show();
}
}//end onDestroy
public void RegisterBtn(View callerid){
initializeManager();
Log.d("CallerIDactivity","RegisterBtn Press");
Toast toast = Toast.makeText(getApplicationContext(),"Registering", Toast.LENGTH_SHORT);
toast.show();
}
public void initializeManager() {
if(manager == null) {
manager = SipManager.newInstance(this);
}
initializeLocalProfile();
}
public void initializeLocalProfile() {
if (manager == null) {
return;
}
if (me != null) {
closeLocalProfile();
}
try {
SipProfile.Builder builder = new SipProfile.Builder("sipaccount", "my.sip.server");
builder.setPassword("pass");
me = builder.build();
Intent i = new Intent();
i.setAction("android.CallerID.INCOMING_CALL");
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, Intent.FILL_IN_DATA);
manager.open(me,pi,null);
// This listener must be added AFTER manager.open is called,
// Otherwise the methods aren't guaranteed to fire.
manager.setRegistrationListener(me.getUriString(), new SipRegistrationListener() {
public void onRegistering(String localProfileUri) {
updateStatus("Registering with SIP Server...");
}
public void onRegistrationDone(String localProfileUri, long expiryTime) {
updateStatus("Ready");
}
public void onRegistrationFailed(String localProfileUri, int errorCode,
String errorMessage) {
updateStatus("Registration failed. Please check settings.");
}
});
}catch (ParseException pe) {
updateStatus("Connection Error.");
} catch (SipException se) {
updateStatus("Connection error.");
}
}
/**
* Closes out your local profile, freeing associated objects into memory
* and unregistering your device from the server.
*/
public void closeLocalProfile() {
if (manager == null) {
Log.d("closeLocalProfile", "manager == null");
return;
}
try {
if (me != null) {
manager.close(me.getUriString());
Toast toast = Toast.makeText(getApplicationContext(), "ClosingProfileURI"+" "+me.getUriString(), Toast.LENGTH_SHORT);
toast.show();
}
} catch (Exception ee) {
Toast toast = Toast.makeText(getApplicationContext(), ee.getMessage(), Toast.LENGTH_SHORT);
toast.show();
Log.d("onDestroy", "Failed to close local profile.", ee);
}
}
/**
* Updates the status box at the top of the UI with a messege of your choice.
* #param status The String to display in the status box.
*/
public void updateStatus(final String status) {
this.runOnUiThread(new Runnable() {
public void run() {
Toast toast = Toast.makeText(getApplicationContext(), status, Toast.LENGTH_SHORT);
toast.show();
}});
/* Be a good citizen. Make sure UI changes fire on the UI thread.
this.runOnUiThread(new Runnable() {
public void run() {
Log.i("allenssip",status);
TextView labelView = (TextView) findViewById(R.id.sipLabel);
labelView.setText(status);
}
});
*/
}//end updateStatus
}//end Class
IncomingCallReceiver.java -
package example.callerid;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.sip.*;
import android.os.Build;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.util.Log;
import android.widget.Toast;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Random;
/**
* Listens for incoming SIP calls, intercepts and hands them off to CallerIDactivity.
*/
public class IncomingCallReceiver extends BroadcastReceiver {
public Calendar calendar;
public SimpleDateFormat dateFormat;
public String date;
public SipManager mSipManager;
public SipSession mSipSesion;
public SipProfile peerProfile;
static private int notifyNum = 1;
/**
* Processes the incoming call, answers it, and hands it over to the
* CallerIDactivity.
* #param context The context under which the receiver is running.
* #param intent The intent being received.
*/
#Override
public void onReceive(Context context, Intent intent) {
mSipManager = SipManager.newInstance(context);
try {
mSipSesion = mSipManager.getSessionFor(intent);
} catch (SipException e) {
e.printStackTrace();
}
peerProfile = mSipSesion.getPeerProfile();
calendar = Calendar.getInstance();
dateFormat = new SimpleDateFormat("dd/MM/yyyy");
date = dateFormat.format(calendar.getTime());
Log.d("CallerID", "OnReceive");
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context, "CHANNEL_ID")
.setSmallIcon(R.mipmap.ic_launcher_round)
.setContentTitle("CallerID" + " " + date)
.setContentText(peerProfile.getDisplayName())
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
if(notifyNum <= 9) {
notificationManager.notify(notifyNum++, mBuilder.build());
}else {notificationManager.notify(notifyNum, mBuilder.build());
notifyNum = 1;
}
int count = 0;
while (count <= 10) {
Toast toast = Toast.makeText(context, peerProfile.getDisplayName(), Toast.LENGTH_SHORT);
toast.show();
count++;
}//end while
}//end onReceive
}//end Class
I think I'm in a bit of a catch 22 situation. I'm making an app that verifies the user's phone number by sending a text message to the number the user entered and then checking - that way it's definitely the user's phone number. This activity should only appear once, at the beginning - for the user to verify, and from then on activity 2 should be loaded.
I am trying to do this with :
// when the form loads, check to see if phoneNo is in there
SharedPreferences sharedPreferences = getSharedPreferences("MyData", Context.MODE_PRIVATE);
String phoneNoCheck = sharedPreferences.getString("phonenumber","");
if (phoneNoCheck != null) {
// if it is in there, start the new Activity
Intent myIntent = new Intent(MainActivity.this, PopulistoContactList.class);
MainActivity.this.startActivity(myIntent);
}
But it doesn't seem to be working properly. For a start, I'm not even sure it should be null. When I turn off my phone and on again, it starts back at activity 1, asking for verification.
And I can't test it. I need to run the app on my device as I can't send an SMS from the emulator, and I'm unable to get to the files where sharedPreferences exist on my device, so I can't even see if it's being written correctly.
Any advice on how I might be able to see the MyData.xml on my phone and proceed with testing my app, or tell my how I may be able to improve my code ? I downloaded the Astro app but still couldn't find it.
Here's my code :
package com.example.chris.tutorialspoint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.app.Activity;
import android.provider.Telephony;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.example.tutorialspoint.R;
public class MainActivity extends Activity {
Button sendBtn;
EditText txtphoneNo;
String phoneNo;
String origNumber;
private BroadcastReceiver receiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sendBtn = (Button) findViewById(R.id.btnSendSMS);
txtphoneNo = (EditText) findViewById(R.id.editText);
// when the form loads, check to see if phoneNo is in there
SharedPreferences sharedPreferences = getSharedPreferences("MyData", Context.MODE_PRIVATE);
String phoneNoCheck = sharedPreferences.getString("phonenumber","");
if (phoneNoCheck != null) {
// if it is in there, start the new Activity
Intent myIntent = new Intent(MainActivity.this, PopulistoContactList.class);
MainActivity.this.startActivity(myIntent);
}
//if it is not in there, proceed with phone number verification
else {
sendBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
sendSMSMessage();
}
});
IntentFilter filter = new IntentFilter();
// the thing we're looking out for is received SMSs
filter.addAction("android.provider.Telephony.SMS_RECEIVED");
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent)
{
Bundle extras = intent.getExtras();
if (extras == null)
return;
Object[] pdus = (Object[]) extras.get("pdus");
SmsMessage msg = SmsMessage.createFromPdu((byte[]) pdus[0]);
origNumber = msg.getOriginatingAddress();
Toast.makeText(getApplicationContext(), "Originating number" + origNumber, Toast.LENGTH_LONG).show();
Toast.makeText(getApplicationContext(), "Sent to number" + phoneNo, Toast.LENGTH_LONG).show();
}
};
registerReceiver(receiver, filter);
}
}
protected void sendSMSMessage() {
phoneNo = txtphoneNo.getText().toString();
//this is the SMS received
String message = "Verification test code. Please ignore this message. Thank you.";
try {
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(phoneNo, null, message, null, null);
Toast.makeText(getApplicationContext(), "SMS sent.", Toast.LENGTH_LONG).show();
//if originating phone number is the same as the sent to number, save
//and go to the next activity
if (origNumber.equals(phoneNo)) {
//save the phone number
SharedPreferences sharedPreferences = getSharedPreferences("MyData", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("phonenumber", phoneNo);
editor.commit();
Intent myIntent = new Intent(MainActivity.this, PopulistoContactList.class);
MainActivity.this.startActivity(myIntent);
}
}
catch (Exception e) {
Toast.makeText(getApplicationContext(), "SMS failed, please try again.", Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
#Override
protected void onDestroy() {
if (receiver != null) {
unregisterReceiver(receiver);
receiver = null;
}
super.onDestroy();
}
What do you expect to happen here:
String phoneNoCheck = sharedPreferences.getString("phonenumber","");
if (phoneNoCheck != null) {
...
}
The method that you are calling, getString(String, String), uses the second parameter as the default value, that is, if no property is found, it will default to, as you have defined, an empty string, "".
You then try and compare this to null, which will never be equal.
Try changing it up to something like this:
String phoneNoCheck = sharedPreferences.getString("phonenumber", null);
// check if null or empty
if ( null == phoneNoCheck || phoneNoCheck.equals("") ) {
// unregistered
}
This question has been asked before but I could not find a working solution to it.
I'm trying to read notifications using NotificationListener Service. Here is the code
import android.app.Notification;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import android.support.v4.content.LocalBroadcastManager;
import java.io.ByteArrayOutputStream;
public class NotificationService extends NotificationListenerService {
Context context;
#Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
String pack = sbn.getPackageName();
String ticker ="";
if(sbn.getNotification().tickerText !=null) {
ticker = sbn.getNotification().tickerText.toString();
}
Bundle extras = sbn.getNotification().extras;
String title = extras.getString("android.title");
String text = extras.getCharSequence("android.text").toString();
int id1 = extras.getInt(Notification.EXTRA_SMALL_ICON);
Bitmap id = sbn.getNotification().largeIcon;
Log.i("Package",pack);
Log.i("Ticker",ticker);
Log.i("Title",title);
Log.i("Text",text);
Intent msgrcv = new Intent("Msg");
msgrcv.putExtra("package", pack);
msgrcv.putExtra("ticker", ticker);
msgrcv.putExtra("title", title);
msgrcv.putExtra("text", text);
if(id != null) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
id.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
msgrcv.putExtra("icon",byteArray);
}
LocalBroadcastManager.getInstance(context).sendBroadcast(msgrcv);
}
#Override
public void onNotificationRemoved(StatusBarNotification sbn) {
Log.i("Msg","Notification Removed");
}
}
This works well but, when notifications get stacked, it does not capture the full notifications.
John:Hi
John:2 new messages
I have tried using the following but that too does not work.
sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString();
The following method tries to get the extra text lines, if there are none it tries to fall back to the extra big text if it’s available.
CharSequence[] lines =
extras.getCharSequenceArray(Notification.EXTRA_TEXT_LINES);
if(lines != null && lines.length > 0) {
StringBuilder sb = new StringBuilder();
for (CharSequence msg : lines)
if (!TextUtils.isEmpty(msg)) {
sb.append(msg.toString());
sb.append('\n');
}
return sb.toString().trim();
}
CharSequence chars =
extras.getCharSequence(Notification.EXTRA_BIG_TEXT);
if(!TextUtils.isEmpty(chars))
return chars.toString();
So i'm using asmack library to listen for incoming xmpp packets. I've got the service implemented. It's started, bound, a method is run and then it's unbound. The service creates a PacketListener to get incoming messages, and displays a notification when a new message comes in. This all works while the app is the active activity, but doesn't work when it's fully closed (swiped away in the window list) and it's just the service running, the PacketListener doesn't fire. It fires as soon as the app is reopened though, firing off all notifications. I'm looking to get those notifications fired as they come in, instead of the service being suspended, if you will. The code for the service is here:
package com.jayseeofficial.xmpp.service;
import java.io.File;
import java.util.ArrayList;
import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Presence.Type;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.util.Log;
import android.widget.Toast;
import com.jayseeofficial.xmpp.MainActivity;
import com.jayseeofficial.xmpp.Program;
import com.jayseeofficial.xmpp.R;
import com.jayseeofficial.xmpp.objects.Contact;
import com.jayseeofficial.xmpp.preferences.Preferences;
public class XMPPService extends Service {
private Connection conn = null;
private boolean loggedIn = false;
private final XMPPBinder binder = new XMPPBinder();
private Handler handler;
#Override
public IBinder onBind(Intent arg0) {
handler = new Handler(getMainLooper());
return binder;
}
public class XMPPBinder extends Binder {
public XMPPService getService() {
return XMPPService.this;
}
}
public void logIn() {
new LogInTask().execute();
}
public boolean isLoggedIn() {
return loggedIn;
}
private ConnectionConfiguration getConnectionConfiguration() {
ConnectionConfiguration config = new ConnectionConfiguration(
Preferences.Account.getServer(), Preferences.Account.getServerPort());
config.setSASLAuthenticationEnabled(true);
config.setCompressionEnabled(true);
config.setSecurityMode(SecurityMode.enabled);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
config.setTruststoreType("AndroidCAStore");
config.setKeystoreType("AndroidCAStore");
config.setTruststorePassword(null);
config.setTruststorePath(null);
} else {
config.setTruststoreType("BKS");
String path = System.getProperty("javax.net.ssl.trustStore");
if (path == null) {
path = System.getProperty("java.home") + File.separator + "etc" + File.separator
+ "security" + File.separator + "cacerts.bks";
}
config.setTruststorePath(path);
}
return config;
}
private void showNotification() {
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setContentTitle("XMPP+").setContentText("running")
.setSmallIcon(R.drawable.speech_bubble);
Intent i = new Intent(this, MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(i);
// Assign the intent
mBuilder.setContentIntent(stackBuilder.getPendingIntent(9127,
PendingIntent.FLAG_UPDATE_CURRENT));
NotificationManager mgr = (NotificationManager) this
.getSystemService(Context.NOTIFICATION_SERVICE);
Notification n = mBuilder.build();
n.flags |= Notification.FLAG_ONGOING_EVENT;
mgr.notify(1,n);
}
private void hideNotification() {
// TODO Implement hideNotification in XMPPService
}
private class LogInTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
try {
showNotification();
// Set up and log in
conn = new XMPPConnection(getConnectionConfiguration());
conn.connect();
conn.login(Preferences.Account.getUsername(), Preferences.Account.getPassword());
// Set up to receive messages
PacketFilter filter = new PacketTypeFilter(Message.class);
conn.addPacketListener(new XMPPMessagePacketListener(), filter);
conn.sendPacket(new Presence(Type.available));
final ArrayList<Contact> allContacts = new ArrayList<Contact>();
// Populate contact list
for (RosterEntry re : conn.getRoster().getEntries()) {
Log.d("Roster entry: ", re.getUser() + ": " + re.getName());
Contact c = new Contact();
if (re.getName() == null) {
c.setName(re.getUser());
} else {
c.setName(re.getName());
}
c.setAddress(re.getUser());
allContacts.add(c);
}
handler.post(new Runnable() {
#Override
public void run() {
Program.contacts.addAll(allContacts);
}
});
loggedIn = true;
} catch (XMPPException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void ignored) {
if (loggedIn) {
Toast.makeText(XMPPService.this, "Logged in successfully", Toast.LENGTH_LONG)
.show();
} else {
Toast.makeText(XMPPService.this, "Failed to log in", Toast.LENGTH_LONG).show();
}
}
}
private class XMPPMessagePacketListener implements PacketListener {
#Override
public void processPacket(Packet packet) {
Message m = (Message) packet;
if (m.getBody() != null) {
com.jayseeofficial.xmpp.objects.Message message = new com.jayseeofficial.xmpp.objects.Message();
message.setRecipient(Preferences.Account.getUsername() + "#"
+ Preferences.Account.getServer());
String fullSender = m.getFrom();
String address = fullSender.substring(0, fullSender.indexOf('/'));
message.setSender(address);
message.setContents(m.getBody());
Program.showMessageNotification(message, 9127);
}
}
}
}
and the code for the starting/binding the service is here:
public static void init() {
if (!initialized) {
// Call other portions of init code first
SmackAndroid.init(context);
Preferences.init();
// Set up our variables
contacts = GlazedLists.threadSafeList(new BasicEventList<Contact>());
// Start up the xmpp connection
Intent ixmpp = new Intent(context, XMPPService.class);
context.startService(ixmpp);
context.bindService(ixmpp, xmppConnection, Context.BIND_AUTO_CREATE);
initialized = true;
}
}
So as I said, i want to receive notifications from the service running in the background when the foreground activity is closed. Is there any way of doing this? Maybe have it in it's own process? Something else?
EDIT: the ongoing notification sticks around and works when clicked, in case you're wondering
use startforeground method
http://developer.android.com/reference/android/app/Service.html#startForeground%28int,%20android.app.Notification%29
in onCreate of service
public void onCreate() {
startForeground (int id, Notification notification)
}
I'm trying to write an android app for may Nexus S that is able to write a simple Text Record on a NFC-Tag. My problem is the connection-establishment to the NFC-Tag.
I've implemented two activities called "TagWriter" & "TagWriterStartPage".
Here ist the "TagWriter"-activity:
package nfc.example.writer;
import java.util.Locale;
import com.google.common.base.Charsets;
import com.google.common.primitives.Bytes;
import android.app.Activity;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.nfc.tech.NdefFormatable;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class TagWriter extends Activity
{
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.tagwriter);
Intent intent = this.getIntent();
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
writeTag(tag);
}
private void writeTag(Tag t)
{
Ndef tag = Ndef.get(t);
Locale locale = Locale.US;
final byte[] langBytes = locale.getLanguage().getBytes(Charsets.US_ASCII);
String text = "Tag, you're it!";
final byte[] textBytes = text.getBytes(Charsets.UTF_8);
final int utfBit = 0;
final char status = (char) (utfBit + langBytes.length);
final byte[] data = Bytes.concat(new byte[] {(byte) status}, langBytes, textBytes);
NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], data);
try
{
NdefRecord[] records = {record};
NdefMessage message = new NdefMessage(records);
tag.connect();
boolean connected = tag.isConnected();
boolean writeable = tag.isWritable();
if( connected && writeable)
{
tag.writeNdefMessage(message);
}
tag.close();
}
catch (Exception e)
{
//do error handling
}
}
}
The activity "TagWriter" is called when I put my device on the NFC-tag. Everytime the method "tag.connect()" is called, there occures an exception.
Can anyone help me to solve the problem???
Thanks,
Dennis
this might work better:
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
Ndef ndef = Ndef.get(tag);
if (ndef != null) {
ndef.connect();
ndef.writeNdefMessage(message);
} else {
NdefFormatable format = NdefFormatable.get(tag);
if (format != null) {
format.connect();
format.format(message);
}
}
need other checks in there for real use (capacity, writable etc) - but that is bare bones..