Android - Service takes a long time to restart when forcibly killed - java

When I kill all the apps (including my app) running using a task killer, the service shows Restarting for a long time.
How do I improve on this ?
The best case scenario would be like, as soon as the app/service is killed, the service would spring up immediately or within the slightest delay possible.
WLANSrvice.java
public class WLANService extends Service {
String username, password, ssid, url;
private static final String CREDENTIALS = "Credentials";
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
SharedPreferences sharedPreferences = getSharedPreferences(CREDENTIALS, 0);
if(sharedPreferences.contains("username")) {
username = sharedPreferences.getString("username", "UNDEFINED");
}
if(sharedPreferences.contains("password")) {
password = sharedPreferences.getString("password", "UNDEFINED");
}
if(sharedPreferences.contains("ssid")) {
ssid = sharedPreferences.getString("ssid", "UNDEFINED");
}
if(sharedPreferences.contains("url")) {
url = sharedPreferences.getString("url", "UNDEFINED");
}
NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
boolean connected = info.isConnected();
if(connected) {
Toast.makeText(context, "WIFI CONNECTED!", Toast.LENGTH_LONG).show();
Log.i("Wi-Fi-State", "Wi-Fi is On!");
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
if(wifiInfo.getSSID().contains(ssid) == true) {
try {
String output = new Connection().execute().get().toString();
Log.i("LoginState", new Connection().execute().get().toString());
if(output.contains("Address")) {
Toast.makeText(WLANService.this, "Login Success!", Toast.LENGTH_SHORT).show();
Intent account_info_intent = new Intent(WLANService.this, AccountInfo.class);
account_info_intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(account_info_intent);
}else {
if(output.contains("n/a")) {
Toast.makeText(WLANService.this, "Login Failed!", Toast.LENGTH_SHORT).show();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
} else {
Toast.makeText(context, "WIFI DISCONNECTED!", Toast.LENGTH_SHORT).show();
//Log.i("Wi-Fi-State", "Wi-Fi is Off!");
}
}
};
public WLANService() {
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "Auto-Login Enabled!", Toast.LENGTH_SHORT).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// registering your receiver
registerReceiver(receiver, new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION));
return START_STICKY;
}
#Override
public void onDestroy() {
Toast.makeText(this, "Auto-Login Disabled!", Toast.LENGTH_SHORT).show();
unregisterReceiver(receiver);
super.onDestroy();
}
private class Connection extends AsyncTask {
#Override
protected Object doInBackground(Object[] objects) {
String formatted_url = url.replace("http://", "");
String true_url;
if(formatted_url.charAt((formatted_url.length()-1)) != '/') {
true_url = formatted_url.concat("/");
}else {
true_url = formatted_url;
}
Log.i("formatted_url", formatted_url);
Log.i("true_url", true_url);
return LoginHelper.doLogin(username, password, "http://".concat(true_url));
}
}
}

Related

Java android killed service

How I can kill this service:
private void startService(Class<?> service, ServiceConnection serviceConnection, Bundle extras) {
if (!UsbService.SERVICE_CONNECTED) {
Intent startService = new Intent(this, service);
if (extras != null && !extras.isEmpty()) {
Set<String> keys = extras.keySet();
for (String key : keys) {
String extra = extras.getString(key);
startService.putExtra(key, extra);
}
}
startService(startService);
}
Intent bindingIntent = new Intent(this, service);
bindService(bindingIntent, serviceConnection, Context.BIND_AUTO_CREATE);
}
I try do this :
Intent intent = new Intent(MainMenu.this, UsbService.class);
stopService(intent);
But the service works all the time.''
And this is my service :
public class UsbService extends Service {
public static final String ACTION_USB_READY = "pl.gps.connectivityservices.USB_READY";
public static final String ACTION_USB_ATTACHED = "android.hardware.usb.action.USB_DEVICE_ATTACHED";
public static final String ACTION_USB_DETACHED = "android.hardware.usb.action.USB_DEVICE_DETACHED";
public static final String ACTION_USB_NOT_SUPPORTED = "pl.gps.usbservice.USB_NOT_SUPPORTED";
public static final String ACTION_NO_USB = "pl..gps.usbservice.NO_USB";
public static final String ACTION_USB_PERMISSION_GRANTED = "pl.gps.usbservice.USB_PERMISSION_GRANTED";
public static final String ACTION_USB_PERMISSION_NOT_GRANTED = "pl.gps.usbservice.USB_PERMISSION_NOT_GRANTED";
public static final String ACTION_USB_DISCONNECTED = "pl.gps.usbservice.USB_DISCONNECTED";
public static final String ACTION_CDC_DRIVER_NOT_WORKING = "pl.gps.connectivityservices.ACTION_CDC_DRIVER_NOT_WORKING";
public static final String ACTION_USB_DEVICE_NOT_WORKING = "pl.gps.connectivityservices.ACTION_USB_DEVICE_NOT_WORKING";
public static final int MESSAGE_FROM_SERIAL_PORT = 1;
private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
private static final int BAUD_RATE = 9600; // BaudRate. Change this value if you need
public static boolean SERVICE_CONNECTED = false;
private IBinder binder = new UsbBinder();
private Context context;
private Handler mHandler;
private UsbManager usbManager;
private UsbDevice device;
private UsbDeviceConnection connection;
private UsbSerialDevice serialPort;
private boolean serialPortConnected;
/*
* Data received from serial port will be received here. Just populate onReceivedData with your code
* In this particular example. byte stream is converted to String and send to UI thread to
* be treated there.
*/
String date = "";
public static boolean check(String s) {
if (s.contains("$GNRMC")) {
return true;
}
return false;
}
private UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() {
#Override
public void onReceivedData(byte[] arg0) {
try {
Thread.sleep(700);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
String data = new String(arg0, "UTF-8");
if (mHandler != null) {
mHandler.obtainMessage(MESSAGE_FROM_SERIAL_PORT, data).sendToTarget();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
};
private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context arg0, Intent arg1) {
if (arg1.getAction().equals(ACTION_USB_PERMISSION)) {
boolean granted = arg1.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED);
if (granted) // User accepted our USB connection. Try to open the device as a serial port
{
Intent intent = new Intent(ACTION_USB_PERMISSION_GRANTED);
arg0.sendBroadcast(intent);
connection = usbManager.openDevice(device);
serialPortConnected = true;
new ConnectionThread().run();
} else // User not accepted our USB connection. Send an Intent to the Main Activity
{
Intent intent = new Intent(ACTION_USB_PERMISSION_NOT_GRANTED);
arg0.sendBroadcast(intent);
}
} else if (arg1.getAction().equals(ACTION_USB_ATTACHED)) {
if (!serialPortConnected)
findSerialPortDevice(); // A USB device has been attached. Try to open it as a Serial port
} else if (arg1.getAction().equals(ACTION_USB_DETACHED)) {
// Usb device was disconnected. send an intent to the Main Activity
Intent intent = new Intent(ACTION_USB_DISCONNECTED);
arg0.sendBroadcast(intent);
serialPortConnected = false;
serialPort.close();
}
}
};
/*
* onCreate will be executed when service is started. It configures an IntentFilter to listen for
* incoming Intents (USB ATTACHED, USB DETACHED...) and it tries to open a serial port.
*/
#Override
public void onCreate() {
this.context = this;
serialPortConnected = false;
UsbService.SERVICE_CONNECTED = true;
setFilter();
usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
findSerialPortDevice();
}
/* MUST READ about services
* http://developer.android.com/guide/components/services.html
* http://developer.android.com/guide/components/bound-services.html
*/
#Override
public IBinder onBind(Intent intent) {
return binder;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
UsbService.SERVICE_CONNECTED = false;
}
/*
* This function will be called from MainActivity to write data through Serial Port
*/
public void write(byte[] data) {
if (serialPort != null)
serialPort.write(data);
}
public void setHandler(Handler mHandler) {
this.mHandler = mHandler;
}
private void findSerialPortDevice() {
// This snippet will try to open the first encountered usb device connected, excluding usb root hubs
HashMap<String, UsbDevice> usbDevices = usbManager.getDeviceList();
HashMap<String, UsbDevice> usbDevices1 = new HashMap<String, UsbDevice>();
usbDevices1.clear();
if (!usbDevices.isEmpty()) {
boolean keep = true;
for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
device = entry.getValue();
int deviceVID = device.getVendorId();
int devicePID = device.getProductId();
if (deviceVID == 1659 && devicePID == 8963) {
// There is a device connected to our Android device. Try to open it as a Serial Port.
requestUserPermission();
keep = false;
if (!keep)
break;
}
}
if (!keep) {
// There is no USB devices connected (but usb host were listed). Send an intent to MainActivity.
Intent intent = new Intent(ACTION_NO_USB);
sendBroadcast(intent);
}
} else {
// There is no USB devices connected. Send an intent to MainActivity
Intent intent = new Intent(ACTION_NO_USB);
sendBroadcast(intent);
}
}
public void unReg(){
// if(usbReceiver != null)
// unregisterReceiver(usbReceiver);
}
private void setFilter() {
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_USB_PERMISSION);
filter.addAction(ACTION_USB_DETACHED);
filter.addAction(ACTION_USB_ATTACHED);
registerReceiver(usbReceiver, filter);
}
private void requestUserPermission() {
PendingIntent mPendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
usbManager.requestPermission(device, mPendingIntent);
}
public class UsbBinder extends Binder {
public UsbService getService() {
return UsbService.this;
}
}
private class ConnectionThread extends Thread {
#Override
public void run() {
serialPort = UsbSerialDevice.createUsbSerialDevice(device, connection);
if (serialPort != null) {
if (serialPort != null && serialPort.open()) {
serialPort.setBaudRate(BAUD_RATE);
serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
serialPort.setParity(UsbSerialInterface.PARITY_NONE);
serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
serialPort.read(mCallback);
Intent intent = new Intent(ACTION_USB_READY);
context.sendBroadcast(intent);
} else {
if (serialPort instanceof CDCSerialDevice) {
Intent intent = new Intent(ACTION_CDC_DRIVER_NOT_WORKING);
context.sendBroadcast(intent);
} else {
Intent intent = new Intent(ACTION_USB_DEVICE_NOT_WORKING);
context.sendBroadcast(intent);
}
}
} else {
Intent intent = new Intent(ACTION_USB_NOT_SUPPORTED);
context.sendBroadcast(intent);
}
}
}
}
But my intent service steal is working. I try did whis when I destroyed my activity in which I created this service but when this activity is destroyed in logs I see that all the time this intent service is steel working
Try this
use stopSelf();
Once requested to stop with stopSelf() the system destroys the service as soon as possible.
pass some action with intent
Intent intent = new Intent(MainMenu.this, UsbService.class);
intent.setAction(Constants.ACTION.STOPTFOREGROUND_ACTION);
stopService(intent);
in your Service onStartCommand()
if(intent.getAction()==Constants.ACTION.STOPTFOREGROUND_ACTION){
stopForeground(true);
stopSelf();
}
public class Constants {
public interface ACTION {
String STOPFOREGROUND_ACTION = "com.package.packageName.action.stopforeground";
}
}

How to send a value to a Bluetooth module from an app using an alarm trigger?

I am quite proficient with programming in general but new to android. I am trying to send a string to a Bluetooth module from the app with an alarm trigger. I am able to send this string with click event but when the same function is invoked with an alarm trigger the Bluetooth module receives the null string. I believe the problem occurs when the value is getting written when the alarm is triggered. Any ideas to solve the problem will be appreciated. Please let me know if the framing of the problem is not clear as I am still new I am not familiar with the jargons.
public static final String TAG = "MyAPP";
private static final int UART_PROFILE_CONNECTED = 20;
private static final int UART_PROFILE_DISCONNECTED = 21;
private int mState = UART_PROFILE_DISCONNECTED;
UartService mService = new UartService();
TimePicker timePicker;
public Button s1,s2,s3,s4,s5;
public Data1()
{
sample();
}
private void sample() {
Log.e(TAG, "Working");
String value = "5";
//send data to service
// value = message.getBytes("UTF-8");
Log.d(TAG, "ByteValue(Data5) = " + value);
UartService mService = new UartService();
mService.WritetoTimer(value);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(activity_main2);
service_init();
s1=findViewById(R.id.Data1);
s2=findViewById(R.id.Data2);
s3=findViewById(R.id.Data3);
s4=findViewById(R.id.Data4);
s5=findViewById(R.id.Data5);
s5.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String message = "5";
byte[] value;
try {
//send data to service
value = message.getBytes("UTF-8");
Log.d(TAG, "ByteValue(Data5) = " + value);
mService.writeRXCharacteristic(value);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
//UART service connected/disconnected
public ServiceConnection mServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder rawBinder) {
UartService mService = new UartService();
mService = ((UartService.LocalBinder) rawBinder).getService();
Log.d(TAG, "onServiceConnected mService= " + mService);
if (!mService.initialize()) {
Log.e(TAG, "Unable to initialize Bluetooth");
finish();
}
}
public void onServiceDisconnected(ComponentName classname) {
UartService mService = new UartService();
mService = null;
}
};
#SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
#Override
//Handler events that received from UART service
public void handleMessage(Message msg) {
}
};
public final BroadcastReceiver UARTStatusChangeReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
assert action != null;
if (action.equals(UartService.ACTION_GATT_CONNECTED)) {
runOnUiThread(new Runnable() {
public void run() {
Log.d(TAG, "UART_CONNECT_MSG");
mState = UART_PROFILE_CONNECTED;
}
});
}
if (action.equals(UartService.ACTION_GATT_DISCONNECTED)) {
runOnUiThread(new Runnable() {
public void run() {
Log.d(TAG, "UART_DISCONNECT_MSG");
mState = UART_PROFILE_DISCONNECTED;
mService.close();
}
});
}
//*********************//
if (action.equals(UartService.ACTION_GATT_SERVICES_DISCOVERED)) {
mService.enableTXNotification();
}
//*********************//
if (action.equals(UartService.ACTION_DATA_AVAILABLE)) {
final byte[] txValue = intent.getByteArrayExtra(UartService.EXTRA_DATA);
runOnUiThread(new Runnable() {
public void run() {
try {
String text = new String(txValue, "UTF-8");
} catch (Exception e) {
Log.e(TAG, e.toString());
}
}
});
}
//*********************//
if (action.equals(UartService.DEVICE_DOES_NOT_SUPPORT_UART)) {
showMessage("Device doesn't support UART. Disconnecting");
mService.disconnect();
}
}
};
public void service_init() {
Intent bindIntent = new Intent(this, UartService.class);
bindService(bindIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
LocalBroadcastManager.getInstance(this).registerReceiver(UARTStatusChangeReceiver, makeGattUpdateIntentFilter());
}
public static IntentFilter makeGattUpdateIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(UartService.ACTION_GATT_CONNECTED);
intentFilter.addAction(UartService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(UartService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(UartService.ACTION_DATA_AVAILABLE);
intentFilter.addAction(UartService.DEVICE_DOES_NOT_SUPPORT_UART);
return intentFilter;
}
#Override
public void onStart() {
service_init();
super.onStart();
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy()");
try {
LocalBroadcastManager.getInstance(this).unregisterReceiver(UARTStatusChangeReceiver);
} catch (Exception ignore) {
Log.e(TAG, ignore.toString());
}

Android onLocationChanged does not called

I am trying to implement a background GPS location service in android using Service and LocationListener. The service is started (-> the onCreate and onStartCommand methods are called), but the onLocationChanged method never called.
Here is the code of my Service:
public class GpsHandler extends Service implements LocationListener{
private static final String TAG = "GpsHandler";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 1000;
private static final float LOCATION_DISTANCE = 10f;
private final String LOCATION_BROADCAST_TAG = "android.LOCATION";
private final String LOCATION_EXTRA_TAG = "Location";
private Location mLastLocation = null;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate()
{
Toast.makeText(this, "Service Started, onCreate", Toast.LENGTH_LONG).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
Toast.makeText(this, "Service Started, onStartCommand", Toast.LENGTH_LONG).show();
if (mLocationManager == null)
{
mLocationManager = (LocationManager)getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
mLastLocation = new Location(LocationManager.GPS_PROVIDER);
try {
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE, this);
} catch (java.lang.SecurityException ex) {
Log.i(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "gps provider does not exist " + ex.getMessage());
}
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
if (mLocationManager != null)
{
try {
mLocationManager.removeUpdates(this);
} catch (Exception ex) {
Log.i(TAG, "fail to remove location listners, ignore", ex);
}
}
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
}
#Override
public void onProviderDisabled(String provider) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
Toast.makeText(getBaseContext(), "Gps is turned off!! ",
Toast.LENGTH_SHORT).show();
}
#Override
public void onLocationChanged(Location location)
{
Toast.makeText(this, "Location Changed", Toast.LENGTH_LONG).show();
if(isBetterLocation(location,mLastLocation))
{
mLastLocation.set(location);
Intent intent = new Intent(LOCATION_BROADCAST_TAG).putExtra(LOCATION_EXTRA_TAG, location);
sendBroadcast(intent);
}
}
#Override
public void onProviderEnabled(String provider){}
#Override
public void onStatusChanged(String provider, int status, Bundle extras){}
private boolean isBetterLocation(Location location, Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location
return true;
}
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > 1000*30;//30000ms = 30 sec
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use the new location
// because the user has likely moved
if (isSignificantlyNewer)
{
return true;
// If the new location is more than two minutes older, it must be worse
}
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and accuracy
if (isMoreAccurate) {
return true;
} else if (isNewer && !isLessAccurate) {
return true;
} else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
return true;
}
return false;
}
/** Checks whether two providers are the same */
private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
}
Finally I have found the solution. I have tried to debug it with an other emulator (Originally I have used Pixel C emulator) and now it works flawless. So it is just a Studio Bug, the code is working.I have also restructured the code a bit, removing some useless functions:
Working code:
public class GpsHandler extends Service implements LocationListener{
private static final String TAG = "GpsHandler";
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 0;
private static final float LOCATION_DISTANCE = 0f;
private final String LOCATION_BROADCAST_TAG = "android.LOCATION";
private final String LOCATION_EXTRA_TAG = "Location";
private Location mLastLocation = null;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate()
{
Toast.makeText(this, "Service Started, onCreate", Toast.LENGTH_LONG).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
Toast.makeText(this, "Service Started, onStartCommand", Toast.LENGTH_LONG).show();
if (mLocationManager == null)
{
mLocationManager = (LocationManager)getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
mLastLocation = new Location(LocationManager.GPS_PROVIDER);
try {
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE, this);
mLastLocation.set(mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER));
} catch (java.lang.SecurityException ex) {
Log.i(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "gps provider does not exist " + ex.getMessage());
}
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
if (mLocationManager != null)
{
try {
mLocationManager.removeUpdates(this);
} catch (Exception ex) {
Log.i(TAG, "fail to remove location listners, ignore", ex);
}
}
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
}
#Override
public void onProviderDisabled(String provider) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
Toast.makeText(getBaseContext(), "Gps is turned off!! ",
Toast.LENGTH_SHORT).show();
}
#Override
public void onLocationChanged(Location location)
{
Toast.makeText(this, "Location Changed", Toast.LENGTH_LONG).show();
if(location.getAccuracy()<4*mLastLocation.getAccuracy())
{
mLastLocation.set(location);
Intent intent = new Intent(LOCATION_BROADCAST_TAG).putExtra(LOCATION_EXTRA_TAG, location);
sendBroadcast(intent);
}
}
#Override
public void onProviderEnabled(String provider){}
#Override
public void onStatusChanged(String provider, int status, Bundle extras){}
}

Android Java get onStartCommand method

Hello I have this inside my MainActivity.java:
#Override
public void onBackPressed() {
Context context = getApplicationContext();
CharSequence text = "myText";
int duration = Toast.LENGTH_SHORT;
Toast.makeText(context, text, duration).show();
myDialog = new Dialog(this);
myDialog.setContentView(R.layout.dialog_signin);
myDialog.setCancelable(false);
password = (EditText) myDialog.findViewById(R.id.password);
myDialog.show();
Button lbtn = (Button) myDialog.findViewById(R.id.loginButton);
lbtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Context context = getApplicationContext();
CharSequence passwordCorrect = "Password correct";
CharSequence passwordIncorrect = "Password wrong";
int duration = Toast.LENGTH_SHORT;
if (password.getText().toString().equals("456")) {
Toast.makeText(context, passwordCorrect, duration).show();
// onstartCommand method here
} else {
Toast.makeText(context, passwordIncorrect, duration).show();
// onstartCommand method here
}
}
});
}
And this in my Kiosk.java:
#Override
public void onDestroy() {
Log.i(TAG, "Stopping service 'KioskService'");
running = false;
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Starting service 'KioskService'");
running = true;
ctx = this;
t = new Thread(new Runnable() {
#Override
public void run() {
do {
handleKioskMode();
try {
Thread.sleep(INTERVAL);
} catch (InterruptedException e) {
Log.i(TAG, "Thread interrupted: 'KioskService'");
}
} while (running);
stopSelf();
}
});
t.start();
return Service.START_NOT_STICKY;
}
I want to change the running value inside my onStartCommand which is current true, inside my MainActivity if password equals 456 to false.
How do I make that happen.
create new Intent(Context, Kiosk.class) and call intent.putExtra(String key, boolean value), then just start your service with Activity.starService(Intent) method

XMPP service connection dies

I'm developing an Android chat app in Java. Now I finally got my service to work but as soon as I fully kill the app the connection in my service dies.
I am using asmack as library for the XMPP connection. The goal is to receive messages even if the app is killed by the user (so it's not in the background).
It does work when I use a foreground service, but I don't want to use a foreground service because of high memory useage and because I don't want the foreground message in the notification center.
My service class
public class MessagingService extends Service {
private final String TAG = "MessagingService";
private final IBinder mBinder = new MessagingBinder();
public Context context;
public XMPPConnection Connection;
public static Handler mHandler = new Handler();
private final int ONGOING_NOTIFICATION_ID = 2344;
#Override
public void onCreate() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind");
return mBinder;
}
#Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind");
return true;
}
#Override
public void onRebind(Intent intent) {
super.onRebind(intent);
Log.d(TAG, "onRebind");
}
#Override
public void onDestroy() {
}
public class MessagingBinder extends Binder {
MessagingService getService() {
Log.d(TAG + " - MessagingBinder", "getService");
return MessagingService.this;
}
}
public Boolean isConnected() {
return (Connection != null);
}
public void Connect(final AuthorizeActivity authorize, final String username, final String password) {
Thread XMPPConnect = new Thread(new Runnable() {
public final String TAG = "XMPPConnect Thread";
#Override
public void run() {
AndroidConnectionConfiguration connConfig = new AndroidConnectionConfiguration(Configuration.HOST, Configuration.PORT, Configuration.SERVICE);
SmackConfiguration.setDefaultPingInterval(100);
connConfig.setReconnectionAllowed(true);
connConfig.setSASLAuthenticationEnabled(true);
connConfig.setRosterLoadedAtLogin(true);
Connection = new XMPPConnection(connConfig);
try {
Connection.connect();
Log.i(TAG, "Connected to " + Connection.getHost());
} catch (XMPPException ex) {
Log.e(TAG, "Failed to connect to " + Connection.getHost());
Log.e(TAG, ex.toString());
Connection = null;
}
if(authorize != null)
authorize.mServiceConnectCallback();
if(username != null && password != null)
Login(username, password, null);
}
});
XMPPConnect.start();
}
public void Login(final String username, final String password, final AuthorizeActivity authorize) {
Thread XMPPLogin = new Thread(new Runnable() {
public final String TAG = "XMPPConnect Thread";
#Override
public void run() {
try {
Connection.login(username, password);
Log.i(TAG, "Logged in as " + Connection.getUser());
Presence presence = new Presence(Presence.Type.available);
Connection.sendPacket(presence);
PacketFilter filter = new MessageTypeFilter(Message.Type.chat);
Connection.addPacketListener(new PacketListener() {
#Override
public void processPacket(Packet packet) {
final Message message = (Message) packet;
if (message.getBody() != null) {
final String fromName = StringUtils.parseName(message.getFrom());
Log.i(TAG, "Text Recieved " + message.getBody() + " from " + fromName );
mHandler.post(new Runnable() {
public void run() {
Receiver.recieveMessage(fromName, message.getBody());
if(!VisibilityHelper.IsVisible()) {
showNotification(fromName, message.getBody());
}
}
});
}
}
}, filter);
} catch (XMPPException ex) {
Log.e(TAG, "Failed to log in as " + "test");
Log.e(TAG, ex.toString());
Connection = null;
}
if(authorize != null)
authorize.mServiceLoginCallback();
}
});
XMPPLogin.start();
}
public void showNotification(String from, String message) {
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
CharSequence notiText = message;
long meow = System.currentTimeMillis();
Notification notification = new Notification(R.drawable.ic_launcher, notiText, meow);
Context context = getApplicationContext();
CharSequence contentTitle = from;
CharSequence contentText = message;
Intent notificationIntent = new Intent(context, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
notification.flags = Notification.DEFAULT_LIGHTS | Notification.FLAG_AUTO_CANCEL;
int SERVER_DATA_RECEIVED = 1;
notificationManager.notify(SERVER_DATA_RECEIVED, notification);
}
public void Logout() {
if(Connection.isConnected()) {
Log.i(TAG, "Logout");
Connection.disconnect();
}
}
public HashMap<String, String> getVCard(String user) {
Log.d(TAG, "getVCard");
//String email = user + "#" + Configuration.HOST;
String email = user;
VCard card = new VCard();
ProviderManager.getInstance().addIQProvider("vCard", "vcard-temp", new VCardProvider());
try {
card.load(MainActivity.mService.Connection, email);
String jabber_id = card.getJabberId();
String firstname = card.getFirstName();
String middlename = card.getMiddleName();
String lastname = card.getLastName();
HashMap<String, String> vcard = new HashMap<String, String>();
vcard.put("jabber_id", jabber_id);
vcard.put("firstname", firstname);
vcard.put("middlename", middlename);
vcard.put("lastname", lastname);
return vcard;
} catch (XMPPException e) {
e.printStackTrace();
}
return null;
}
public void retrieveContactsFromList() {
if(this.isConnected()) {
Roster roster = Connection.getRoster();
Collection<RosterEntry> entries = roster.getEntries();
for(RosterEntry entry : entries) {
Receiver.onRetrieveContactFromList(entry);
}
}
}
}
My activity to start the service
public class ConnectionBinder extends FragmentActivity {
private final String TAG = "ConnectionBinder";
public static MessagingService mService;
public boolean mBound = false;
public Database DB;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(!this.messagingServiceIsRunning())
{
startService(new Intent(this, MessagingService.class));
}
}
private boolean messagingServiceIsRunning() {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (MessagingService.class.getName().equals( service.service.getClassName())) {
return true;
}
}
return false;
}
#Override
protected void onResume() {
super.onResume();
doBindService();
}
#Override
protected void onPause() {
super.onPause();
doUnbindService();
}
private void doBindService() {
Intent intent = new Intent(this, MessagingService.class);
bindService(intent, mMessagingService, Context.BIND_AUTO_CREATE);
}
private void doUnbindService() {
if (mBound) {
unbindService(mMessagingService);
}
}
private void doXMPPLogin() {
HashMap<String, String> user = DB.getUser();
mService.Connect(null, user.get("username"), user.get("password"));
}
private ServiceConnection mMessagingService = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
Log.d(TAG, "mMessagingService.onServiceConnected()");
MessagingBinder binder = (MessagingBinder) service;
mService = binder.getService();
mBound = true;
if(!mService.isConnected()) {
doXMPPLogin();
}
mService.retrieveContactsFromList();
}
public void onServiceDisconnected(ComponentName arg0) {
Log.d(TAG, "mMessagingService.onServiceDisconnected()");
mBound = false;
}
};
}
Traditional XMPP implementations (and XMPP RFCs) does not define a way to maintain persistent user "sessions" when client disconnects - they all closing user session when underlying TCP/IP or HTTP connection is lost.
On the other hand, typical Android enviroment have "always-connected" Google Cloud Services, which can deliver messages for your application even if it is not connected. In fact, most chat and social networking applications are using GCM to inform user about new messages.
So, depend on your needs, you need to make some changes on the server side of your chat application:
Most XMPP server implementations are able to store messages which was received when user was "offline" and delivers it when user connects again. You can "hook" offline message receiving and inform user via Google Cloud Messaging about availability of new messages, user will receive it when open your application again and your XMPPConnection will established.
Use XMPP Stream Management extension - if you need to share same session across multiple user reconnections - and "resume" previous session when user open your app again. And you still should inform user about new events in his "session" via GCM.
Your server-side XMPP software should keep GCM registration ids for every user device, so when user device is registered in GCM - you need to inform your server about newly registered id - it can be achieved by sending custom <iq> packet to server with your GCM id.
Some commercial XMPP products already implement steps above and will sell you "Push-enabled XMPP service" which is in fact XMPP server with GCM backend, as I describe.

Categories