Here is my service class
package com.example.com.listener;
import android.app.DownloadManager;
import android.app.IntentService;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.widget.Toast;
import com.android.volley.Request;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import com.google.android.gms.iid.InstanceID;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import com.example.com.R;
import com.example.com.listener.GCMRegistrationListener;
import com.example.com.util.Constants;
import com.example.com.web.RawRequest;
import com.example.com.web.WebRequest;
public class GCMRegistrationService extends IntentService{
private static final String TAG = "GCMRegistrationService";
private static final String[] TOPICS = {"global"};
public GCMRegistrationService() {
super(TAG);
}
#Override
protected void onHandleIntent(Intent intent) {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
try {
InstanceID instanceID = InstanceID.getInstance(this);
String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId), GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
sendRegistrationToServer(token,sharedPreferences.getString(Constants.EMAIL_SHARED_PREF,""));
Toast.makeText(this,"This is your token " + token,Toast.LENGTH_LONG).show();
Log.i("token", token);
// You should store a boolean that indicates whether the generated token has been
// sent to your server. If the boolean is false, send the token to your server,
// otherwise your server should have already received the token.
sharedPreferences.edit().putBoolean(Constants.GCM_TOKEN_TO_SERVER, true).apply();
// [END register_for_gcm]
} catch (Exception e) {
Log.d(TAG, "Failed to complete token refresh", e);
// If an exception happens while fetching the new token or updating our registration data
// on a third-party server, this ensures that we'll attempt the update at a later time.
sharedPreferences.edit().putBoolean(Constants.GCM_TOKEN_TO_SERVER, false).apply();
}
}
/**
* Persist registration to third-party servers.
*
* Modify this method to associate the user's GCM registration token with any server-side account
*
* #param token The new token.
*/
private void sendRegistrationToServer(String token,String email) {
WebRequest request= new RawRequest(this,Constants.SEND_GCM_TOKEN, Request.Method.POST);
Map<String,String> requestParams= new HashMap<>();
requestParams.put(Constants.GCM_TOKEN_LABEL,token);
requestParams.put(Constants.EMAIL_SHARED_PREF,email);
request.sendRequest(new GCMRegistrationListener(), requestParams, null);
}
}
Here is the code I used to start the service:
Intent gcmRegister= new Intent(context,GCMRegistrationService.class);
context.startService(gcmRegister);
Manifest file entry is:
Manifest package is com.example.com
and service entry is
<service android:name=".listener.GCMRegistrationService" android:exported="false" />
Unfortunately my service is not running. Please help.
GCM register() has been deprecated. Use InstanceID to perform general GCM registration management. as shown below , use google play lib to get it.
Log.i(TAG, "GCM Registration event is received");
String token;
try {
token = InstanceID.getInstance(context).getToken(context.getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
Log.i(TAG, "GCM Registration Token retrieved from google cloud: " + token);
//
} catch (IOException e) {
// exponential back off
Log.e(TAG, "IO error occurred, going to back off. backoffIndexGCM:" + backoffIndexGCM);
exponentialBackOff.postDelayed(exponentialBackOffGCMRegisterRun, 1000 * backoffIndexGCM);
backoffIndexGCM *= 2;
// should not wait more than 1000 sec in any circumstance.
backoffIndexGCM %= 1000;
}
Change your data according to your requirement ,Allow this service tag outside the closing activity tag in manifest file :
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.twitter"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="15" />
<uses-permission android:name="android.permission.INTERNET"/>
<application android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".TwitterTwoActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="tfe.rma.ciss.be.Server"/>
</application>
</manifest>
Adding superclass to onCreate super.onCreate() and change onStart by onStartCommand (plus its superclass super.onStartCommand().
package tfe.rma.ciss.be;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlrpc.android.MethodCall;
import org.xmlrpc.android.XMLRPCServer;
import android.app.IntentService;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
import java.io.IOException;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
public class Server extends IntentService {
public String myData="";
public String streamTitle = "",path="";
public void onCreate() {
super.onCreate();
Log.d("Server", ">>>onCreate()");
}
public Server() {
super("Server");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, startId, startId);
Log.i("LocalService", "Received start id " + startId + ": " + intent);
return START_STICKY;
}
#Override
protected void onHandleIntent(Intent intent) {
Log.d("Server", ">>>handlingIntent()");
try {
ServerSocket socket = new ServerSocket(8214);
XMLRPCServer server = new XMLRPCServer();
Log.d("Server", ">>>opening on port" + socket);
while (true) {
Socket client = socket.accept();
MethodCall call = server.readMethodCall(client);
String name = call.getMethodName();
if (name.equals("newImage")) {
ArrayList<Object> params = call.getParams();
// assume "add" method has two Integer params, so no checks done
myData = (String)( params.get(0));
//int i1 = (Integer) params.get(1);
server.respond(client, new Object[] {200});
/*intent = new Intent (this, ParseFunction.class);
startService (intent); */
Toast.makeText(this, myData, Toast.LENGTH_SHORT).show();
Log.d("ParseFunction", ">>>Started()");
Intent i = new Intent( this, B.class );
i.putExtra( "Azo", myData);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity( i );
} else {
server.respond(client, null);
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
}
}
Related
I'm building an Android Wear service which runs in the background and logs device data every three minutes. For this logging, I am using a Handler, which records the values and then has an interval of three minutes. This will be used to monitor user behaviour for one month, and as such it should not randomly stop.
I have also used android.intent.action.BOOT_COMPLETED in my manifest and this successfully runs the application whenever the watch is booted.
My issue is that the service can run correctly for 12 hours...and then just suddenly stop. The amount of time appears to be non-deterministic, as sometimes it will stop after 40 minutes. I suspect it's being killed by Android, but in this case I would like it to restart. I have included return START_STICKY in my service and this should minimise the chance of it being killed.
In some solutions, I have seen onDestroy() overridden and a refresh broadcast being sent to the service. While this appears to work, the onDestroy() function is being called every time the Handler completes one piece of work. This leads to the service restarting every three minutes, rather than when the application is actually killed by Android.
I have also looked at the intent actions to see whether my service could be called at regular intervals. However, aside from android.intent.action.BOOT_COMPLETED, all the useful ones cannot be registered in the Manifest file. Since the service will not be running, registerReceiver() would serve little purpose.
Does anybody know of a technique to either a) guarantee a service will not be killed by Android; or b) guarantee that a service will always be restarted after it has been killed. Any help would be greatly appreciated, as I've even started considering writing a Cron job on the device and setting it to execute my app every three minutes! I've also looked at the AlarmManager class, but I fear it is as likely to be killed if running for long periods.
Please find my code below: (AndroidManifest.xml)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.study">
<uses-feature android:name="android.hardware.type.watch" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#android:style/Theme.DeviceDefault">
<receiver android:name="com.example.study.MyServiceManager" android:enabled="true">
<intent-filter>
<action android:name="com.example.study.RestartAction" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<activity
android:name="com.example.study.MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="com.example.study.RecordService"
android:exported="false" />
</application>
</manifest>
RecordService.java
package com.example.study;
import android.Manifest;
import android.app.AlarmManager;
import android.app.IntentService;
import android.app.KeyguardManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import com.google.android.gms.location.LocationServices;
import android.os.Build;
import android.os.Handler;
import android.os.PowerManager;
import android.provider.Settings;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.text.TextUtils;
import com.google.android.gms.location.*;
import com.google.android.gms.tasks.OnSuccessListener;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;
public class RecordService extends IntentService {
private static Context context;
private final static int INTERVAL = 1000 * 5; // 1 minutes
Handler handler = new Handler();
Location myLocation;
private FusedLocationProviderClient mFusedLocationClient;
SensorManager sensorManager;
SensorManager gyroSensorManager;
SensorManager compassSensorManager;
SensorEventListener sensorEventListener;
float[] accValues;
float[] gyroValues;
float[] compassValues;
Runnable handlerTask = new Runnable() {
#Override
public void run() {
try {
recordData();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.postDelayed(handlerTask, INTERVAL);
}
};
public RecordService() {
super("RecordService");
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
handlerTask.run();
}
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
public void recordData() throws ExecutionException, InterruptedException {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(MainActivity.getAppContext());
boolean fineLocationGranted = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
boolean coarseLocationGranted = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
boolean isLocationEnabled = isLocationEnabled(this);
if(fineLocationGranted && coarseLocationGranted && isLocationEnabled) {
long startTime = System.currentTimeMillis();
long timeWaiting = 0L;
mFusedLocationClient.getLastLocation()
.addOnSuccessListener(MainActivity.getActivity(), new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
if (location != null) {
myLocation = location;
} else {
System.out.print("");
}
}
});
do {
timeWaiting = System.currentTimeMillis() - startTime;
} while (myLocation == null && timeWaiting < 200);
}
List<PackageInfo> packages = getPackageManager().getInstalledPackages(PackageManager.GET_PERMISSIONS);
KeyguardManager kg = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
boolean isLocked = kg.isDeviceSecure();
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
gyroSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
compassSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
sensorEventListener = new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
if(sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
accValues = sensorEvent.values;
} else if(sensorEvent.sensor.getType() == Sensor.TYPE_GYROSCOPE){
gyroValues = sensorEvent.values;
} else if(sensorEvent.sensor.getType() == Sensor.TYPE_ORIENTATION) {
compassValues = sensorEvent.values;
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {}
};
try {
sensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
gyroSensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE), SensorManager.SENSOR_DELAY_NORMAL);
compassSensorManager.registerListener(sensorEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), SensorManager.SENSOR_DELAY_NORMAL);
} catch(SecurityException e) {
e.printStackTrace();
}
long startTime2 = System.currentTimeMillis();
long timeWaiting2 = 0L;
do {
timeWaiting2 = System.currentTimeMillis() - startTime2;
} while((accValues == null || gyroValues == null || compassValues == null) && timeWaiting2 < 200);
StringBuilder builder = new StringBuilder();
builder.append("G" + (isLocationEnabled ? 1 : 0));
builder.append(" L" + (isLocked ? 1 : 0));
if(accValues != null && gyroValues != null && compassValues != null) {
builder.append(" ACX" + accValues[0]);
builder.append(" ACY" + accValues[1]);
builder.append(" ACZ" + accValues[2]);
builder.append(" GYX" + gyroValues[0]);
builder.append(" GYY" + gyroValues[1]);
builder.append(" GYZ" + gyroValues[2]);
builder.append(" CMX" + gyroValues[0]);
builder.append(" CMY" + gyroValues[1]);
builder.append(" CMZ" + gyroValues[2]);
}
if(myLocation != null) {
builder.append(" LT" + myLocation.getLatitude());
builder.append(" LN" + myLocation.getLongitude());
}
builder.append("\n");
for(PackageInfo info: packages) {
int lastDot = info.packageName.lastIndexOf('.');
builder.append(info.packageName + "\n");
if(info.requestedPermissions != null) {
for (String rqprm : info.requestedPermissions) {
int dot = rqprm.lastIndexOf('.');
builder.append(rqprm.substring(dot != -1 ? dot + 1 : 0) + " ");
}
builder.append("\n");
for (int permflag : info.requestedPermissionsFlags) {
builder.append("" + permflag + " ");
}
builder.append("\n");
}
}
SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd--HH-mm-ss");
String currentDateString = sdf.format(new Date());
File log = new File("/sdcard/Recordings/" + currentDateString);
try {
if (!log.exists()) {
log.createNewFile();
}
BufferedWriter writer = new BufferedWriter(new FileWriter(log, true));
writer.append(builder.toString());
writer.newLine();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static boolean isLocationEnabled(Context context) {
int locationMode = 0;
String locationProviders;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
try {
locationMode = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE);
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
return false;
}
return locationMode != Settings.Secure.LOCATION_MODE_OFF;
} else {
locationProviders = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
return !TextUtils.isEmpty(locationProviders);
}
}
MainActivity.java
package com.example.study;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity {
private TextView mTextView;
private static Context context;
private static MainActivity activity;
Intent serviceIntent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MainActivity.context = getApplicationContext();
activity = this;
serviceIntent = new Intent(this, RecordService.class);
startForegroundService(serviceIntent)
startService(serviceIntent);
}
public static Context getAppContext() {
return MainActivity.context;
}
public static MainActivity getActivity() {
return activity;
}
}
MyServiceManager.java
package com.example.study;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
public class MyServiceManager extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent myIntent = new Intent(context, MainActivity.class);
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myIntent);
}
}
}
I am trying to get the incoming call number from my cordova android plugin. Able to get the Phone State using TELEPHONYMANGER.PHONE_STATE_CHANGED. But unable to get the incoming call number. BroadcastReceiver's Intent provides the option to get the incoming call number. But BroadcastReceiver's onReceive function is not triggered. Please help.
package io.infonion.calldetail;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import android.support.v4.content.LocalBroadcastManager;
import org.apache.cordova.PluginResult;
import android.content.Context;
import android.widget.Toast;
import android.telephony.PhoneStateListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.telephony.TelephonyManager;
import android.content.BroadcastReceiver;
import android.os.Bundle;
import android.util.Log;
import org.json.JSONException;
import org.json.JSONArray;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class CallDetail extends CordovaPlugin {
CallStateListener listener;
IntentFilter intentFilter;
Context maincontext;
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
Toast.makeText(cordova.getActivity().getApplicationContext(), "first", Toast.LENGTH_LONG).show();
if (listener == null) {
listener = new CallStateListener();
listener.setCordovaContext(cordova.getActivity().getApplicationContext());
listener.setCallbackContext(callbackContext);
Toast.makeText(cordova.getActivity().getApplicationContext(), "fourth", Toast.LENGTH_LONG).show();
intentFilter = new IntentFilter() ;
intentFilter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
LocalBroadcastManager.getInstance(super.webView.getContext()).registerReceiver(listener,intentFilter);
//registerReceiver(listener, intentFilter);
Toast.makeText(cordova.getActivity().getApplicationContext(), "fifth", Toast.LENGTH_LONG).show();
}
return true;
}
}
class CallStateListener extends BroadcastReceiver {
private CallbackContext callbackContext;
private Context cordovaContext;
public void setCallbackContext(CallbackContext callbackContext) {
Toast.makeText(cordovaContext, "third", Toast.LENGTH_LONG).show();
this.callbackContext = callbackContext;
}
public void setCordovaContext(Context cordovaContext) {
Toast.makeText(cordovaContext, "second", Toast.LENGTH_LONG).show();
this.cordovaContext = cordovaContext;
}
#Override
public void onReceive(final Context context, Intent intent) {
String act=intent.getAction();
String number="";
Toast.makeText(cordovaContext, "Sixth", Toast.LENGTH_LONG).show();
if(intent.getAction().equals("TelephonyManager.ACTION_PHONE_STATE_CHANGED")){
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
Toast.makeText(cordovaContext, state, Toast.LENGTH_LONG).show();
if(state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
// Log.d(TAG, "Inside Extra state off hook");
number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Toast.makeText(cordovaContext, "EXTRA_STATE_OFFHOOK", Toast.LENGTH_LONG).show();
// Log.e(TAG, "outgoing number : " + number);
}
else if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)){
// Log.e(TAG, "Inside EXTRA_STATE_RINGING");
number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
Toast.makeText(cordovaContext, "RINGING", Toast.LENGTH_LONG).show();
// Log.e(TAG, "incoming number : " + number);
}
else if(state.equals(TelephonyManager.EXTRA_STATE_IDLE)){
Toast.makeText(cordovaContext, "EXTRA_STATE_IDLE", Toast.LENGTH_LONG).show();
// Log.d(TAG, "Inside EXTRA_STATE_IDLE");
}
PluginResult result = new PluginResult(PluginResult.Status.OK, number);
result.setKeepCallback(true);
callbackContext.sendPluginResult(result);
}
}
}
Maybe it's late to answer but may this help other people :
Creating instance "new CallStateListener()" for the receiver will not trigger the onReceive method.
Your receiver is not working, it should be declared at AndroidManifest.xml inside the tag application .
So you should first make static the class CallStateListener :
public static CallStateListener extends BrodcastReceiver {}
and add these lines on your plugin.xml file inside :
<config-file target="AndroidManifest.xml" parent="/manifest/application">
<receiver android:name="io.infonion.calldetail.CallDetail$CallStateListener"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
</config-file>
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 am working on app where i want to end outgoing call.
this is the main class
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
public class phonecalls extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
call();
}
private void call() {
try {
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:123456789"));
startActivity(callIntent);
} catch (ActivityNotFoundException activityException) {
Log.e("dialing-example", "Call failed", activityException);
}
}
}
and outgoingclass is this
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;
import com.android.internal.telephony.ITelephony;
import java.lang.reflect.Method;
public class OutgoingCallReceiver extends BroadcastReceiver {
private final String TAG = "CallControl";
Context context;
String incomingNumber;
ITelephony telephonyService;
#Override
public void onReceive(Context context, Intent intent) {
TelephonyManager tm = (TelephonyManager) context .getSystemService(Context.TELEPHONY_SERVICE);
try {
// Java reflection to gain access to TelephonyManager's
// ITelephony getter
Bundle bundle = intent.getExtras();
if(null == bundle)
return;
String phonenumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Log.i("OutgoingCallReceiver",phonenumber);
Log.i("OutgoingCallReceiver",bundle.toString());
String info = "Detect Calls sample application\nOutgoing number: " + phonenumber;
Toast.makeText(context, info, Toast.LENGTH_LONG).show();
Log.v(TAG, "Get getTeleService...");
Class c = Class.forName(tm.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
m.setAccessible(true);
telephonyService=(ITelephony) m.invoke(tm);
telephonyService.endCall();
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG,
"FATAL ERROR: could not connect to telephony subsystem");
Log.e(TAG, "Exception object: " + e);
}
}
}
But the call is not ended even though i am able to print no. when outgoing call starts which show broadcasting receiver is working right .
Any suggestion
Yes definately there is two way to do it either using airplane mode or internal telephony for this . I used internal telephony and code I developed is uploaded here https://github.com/deependersingla/end_calls.
If you need anything more tell me , will be happy to help.
I am testing call control example given on: http://prasanta-paul.blogspot.com/2010/09/call-control-in-android.html on emultaor.
Code is as below:
package com.example.callblock;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.RemoteException;
import android.telephony.TelephonyManager;
import android.widget.Toast;
import com.android.internal.telephony.ITelephony;
public class CallBlock extends BroadcastReceiver{
String[] blockedNumbers = {"5556"};
String incommingNumber;
Context context;
String incomingNumber;
ITelephony telephonyService;
public void onReceive(Context context, Intent intent) {
//Log.v(TAG, "Incoming Call BroadCast received...");
// Log.v(TAG, "Intent: ["+ intent.getAction() +"]");
Bundle b = intent.getExtras();
incommingNumber = b.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
Toast.makeText(context, "Phone no:"+incomingNumber, Toast.LENGTH_LONG).show();
// Additional Step
// Check whether this number matches with your defined Block List
// If yes, Reject the Call
if(incommingNumber.equals(blockedNumbers[0])){
try {
telephonyService.endCall();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
When i tried to run this example ie make call from one emulator(5556) to the second emulator(5554). It shows Phoneno:null.
I am unable to understand the reason for this.