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.
Related
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>
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();
}
}
}
I have a broadcast receiver for listening to incoming call event. It is defined programmatically not in the manifest. The purpose is to block all calls when that is chosen by the user. But after I unregister the broadcast receiver and close the service that registered it the receiver stays active and still blocks calls.
what I have tried:
1) I tried implementing this receiver inside another broadcast receiver class I already have in this app and works fine...which means that after unregistering it it stops listening to the other events. And while it stops listening to the other events it keeps listening to incoming call events. (which is just utterly weird)
2) I tried implementing the incoming calls receiver in a seperate broacast receiver class and register it in a seperate service. even after i kill this service it still stays alive.
The calls receiver dies only when the whole app closes.
3)I tried the same thing using an activity instead of a service.
OnDestory is called in the case of service. And the problem persists when using an activity as well.
How is this explained and how can I solve this problem???
this is my code for the seperate broacast receiver class and seperate service implementation:
package com.android.internal.telephony;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.widget.Toast;
public class CallBlockBroadcastReceiver extends BroadcastReceiver{
BroadcastReceiver CallBlocker;
TelephonyManager telephonyManager;
ITelephony telephonyService;
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
// TODO Auto-generated method stub
String number=intent.getExtras().getString("incoming_number");
Toast.makeText(context, number, Toast.LENGTH_SHORT).show();
telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
//Java Reflections
Class c = null;
try { c = Class.forName(telephonyManager.getClass().getName());}
catch (ClassNotFoundException e) { e.printStackTrace(); }
Method m = null;
try { m = c.getDeclaredMethod("getITelephony");}
catch (SecurityException e) { e.printStackTrace(); }
catch (NoSuchMethodException e) { e.printStackTrace(); }
m.setAccessible(true);
try { telephonyService = (ITelephony)m.invoke(telephonyManager);}
catch (IllegalArgumentException e) {e.printStackTrace();}
catch (IllegalAccessException e) {e.printStackTrace();}
catch (InvocationTargetException e) {e.printStackTrace();}
telephonyManager.listen(callBlockListener, PhoneStateListener.LISTEN_CALL_STATE);
}
PhoneStateListener callBlockListener = new PhoneStateListener(){
public void onCallStateChanged(int state, String incomingNumber){
if(state==TelephonyManager.CALL_STATE_RINGING){
try {
telephonyService.endCall();
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
}
ITelephony class:
package com.android.internal.telephony;
interface ITelephony {
boolean endCall();
void answerRingingCall();
void silenceRinger();
}
my service
import android.app.Service;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import com.android.internal.telephony.CallBlockBroadcastReceiver;
public class BroadcastService extends Service{
CallBlockBroadcastReceiver callBlockBroadcastReceiver = new CallBlockBroadcastReceiver();
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
getBaseContext().registerReceiver(callBlockBroadcastReceiver, new IntentFilter("android.intent.action.PHONE_STATE"));
return START_STICKY;
}
#Override
public void onDestroy() {
getBaseContext().unregisterReceiver(callBlockBroadcastReceiver);
// TODO Auto-generated method stub
super.onDestroy();
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
}
I would guess that onDestroy() is not getting called in your service. Are there any bindings left to the service? Are you sure you're calling stopService(intent) on the service?
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.
In my application i want to do bluetooth chat. I'm facing a problem in threading. In my application my android phone will work as server which has a blocking statement
socket=mServerSocket.accept();
for this purpose i've created a child thread so that it will run separately. But before finishing this child thread main thread goes down giving Force Close and if i use the .join() method it hangs up my UI.
What is the solution to run both threads parallel?
this is my code
main Activity
package com.my.bluechat_2_1;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class BlueChat extends Activity {
/** Called when the activity is first created. */
private BlueHandler btHandler=null;
private BluetoothAdapter btAdapter = null;
private Context context=this;
TextView chatWindow=null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
chatWindow=(TextView)findViewById(R.id.textView1);
doStart();
}
private void doStart(){
Button btnStart=(Button)findViewById(R.id.button1);
btnStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// Get local Bluetooth adapter
btAdapter = BluetoothAdapter.getDefaultAdapter();
// If the adapter is null, then Bluetooth is not supported
if(btAdapter == null)
{
Toast.makeText(context, "Device does not support Bluetooth", Toast.LENGTH_LONG).show();
}
if (!btAdapter.isEnabled()) {
Intent discoverableIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
}
chatWindow.append("Waiting for connection...\n");
btHandler=new BlueHandler(context,chatWindow,btAdapter);
Thread acceptThread=new Thread(btHandler);
acceptThread.start();
}
});
}
}
BlueHandler
package com.my.bluechat_2_1;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.widget.TextView;
import android.widget.Toast;
public class BlueHandler implements Runnable{
// Name for the SDP record when creating server socket
private static final String SMARTCAM_BT_SERVICE_NAME = "SmartCam";
// Unique UUID for this application
private static final UUID SMARTCAM_BT_SERVICE_UUID = UUID.fromString("95b82690-4c94-11e1-b86c-0800200c9a66");
private BluetoothAdapter btAdapter = null;
private BluetoothServerSocket btServerSocket = null;
private BluetoothSocket btSocket = null;
private InputStream btInputStream=null;
private Context contextObj=null;
private TextView textView;
public BlueHandler(Context contextObj,TextView textView,BluetoothAdapter btAdapter){
this.contextObj=contextObj;
this.btAdapter=btAdapter;
this.textView=textView;
try {
btServerSocket=this.btAdapter.listenUsingRfcommWithServiceRecord(SMARTCAM_BT_SERVICE_NAME, SMARTCAM_BT_SERVICE_UUID);
} catch (IOException e) {
// TODO Auto-generated catch block
Toast.makeText(this.contextObj, "Service not created", Toast.LENGTH_LONG);
}
}
#Override
public void run() {
// TODO Auto-generated method stub
textView.append("Inside child thread.\n");
textView.append(btServerSocket+"\n");
while (true) {
try {
btSocket = btServerSocket.accept();
} catch (IOException e) {
break;
}
// If a connection was accepted
if (btSocket != null) {
// Do work to manage the connection (in a separate thread)
try {
btServerSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
textView.append("Connected.\n");
try {
btInputStream=btSocket.getInputStream();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte[] buffer = new byte[1024]; // buffer store for the stream
String s;
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes=btInputStream.read(buffer);
s= new String(buffer);
// Send the obtained bytes to the UI Activity
textView.append("received ::" +s+"\n");
} catch (IOException e) {
break;
}
}
}
}
You're probably getting a crash because you're accessing a textView on the worker thread. You'll need to use TextView.post(Runnable) to make that not happen.
In reality you should be using a bindable Service to do this kind of work. You can post back to the UI via broadcast intents or callback methods, That way you don't have to worry about rotation bugs.
Are you performing a long operation in the constructor of your children thread? Each long operation must be done in the run() method.