I tried lot of links at so but I am not good enough to find the right code.I managed to block calls using this code.
public class BlockCallReceiver extends BroadcastReceiver{
Context context;
#Override
public void onReceive(Context context, Intent intent) {
Bundle myBundle = intent.getExtras();
if (myBundle != null)
{
System.out.println("--------Not null-----");
try
{
if (intent.getAction().equals("android.intent.action.PHONE_STATE"))
{
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
System.out.println("--------in state-----");
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING))
{
// Incoming call
String incomingNumber =intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
System.out.println("--------------my number---------"+incomingNumber);
// this is main section of the code,. could also be use for particular number.
// Get the boring old TelephonyManager.
TelephonyManager telephonyManager =(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
// Get the getITelephony() method
Class<?> classTelephony = Class.forName(telephonyManager.getClass().getName());
Method methodGetITelephony = classTelephony.getDeclaredMethod("getITelephony");
// Ignore that the method is supposed to be private
methodGetITelephony.setAccessible(true);
// Invoke getITelephony() to get the ITelephony interface
Object telephonyInterface = methodGetITelephony.invoke(telephonyManager);
// Get the endCall method from ITelephony
Class<?> telephonyInterfaceClass = Class.forName(telephonyInterface.getClass().getName());
Method methodEndCall = telephonyInterfaceClass.getDeclaredMethod("endCall");
// Invoke endCall()
methodEndCall.invoke(telephonyInterface);
}
}
}
catch (Exception ex)
{
// Many things can go wrong with reflection calls
ex.printStackTrace();
}
}
}
}
and in my Manifest
<receiver android:name=".utils.BlockCallReceiver" >
<intent-filter android:priority="100" >
<action android:name="android.intent.action.PHONE_STATE" >
</action>
</intent-filter>
</receiver>
It worked. But even the app is no in foreground/or not even in the active apps calls are blocked.
I tried to un register this BlockCallReceiver class in my Launcher Activity because I want to allow calls when the app is not open.
So in onPause I tried some codes given in answers but It did not work since my bad knowledge.
Here is an example that I tried but I'm stuck
ComponentName receiver = new ComponentName(MainActivity.this, BlockCallReceiver.class);
PackageManager pm = MainActivity.this.getPackageManager();
pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
Please if someone can guide me to re allow calls when the app turns off I am really grateful.
Edit One :
If I use below
public void onPause() {
super.onPause();
MainActivity.this.unregisterReceiver(mybroadcast);
}
It throws me an error java.lang.IllegalArgumentException: Receiver not registered! Yes I have not registered it in my Activity only on that thing at the manifest. I know something is wrong but cannot understand it.
Edit Two : #Imen Nmn answer is helpful. I will try to register dynamically rather than the Manifest. But I have a doubt there should be someway with un registering B.receiver given in the Manifest ?
To Stop a broadcastReceiver , you should call : yourContext.unregisterReceiver(yourBroadcastReceiver);
if you notice this example , in onResume there is this.registerReceiver(the_receiver, filter); and in onPause , there is
this.unregisterReceiver(the_receiver);
Here an example :
public class Android Example extends Activity {
private BroadcastReceiver the_receiver = new BroadcastReceiver(){
#Override
public void onReceive(Context c, Intent i) {
}
};
// Set When broadcast event will fire.
private IntentFilter filter = new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
#Override
protected void onResume() {
// Register reciever if activity is in front
this.registerReceiver(the_receiver, filter);
super.onResume();
}
#Override
protected void onPause() {
// Unregister reciever if activity is not in front
this.unregisterReceiver(the_receiver);
super.onPause();
}
}
Related
I've written an android app which checks the network status by using a BroadcastReceiver inherited class:
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
Log.d("mylog", "NetworkChangeReceiver Hit");
}
}
which is registered in the manifest file like this:
<receiver
android:name="foo.NetworkChangeReceiver"
android:label="NetworkChangeReceiver" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
</intent-filter>
</receiver>
I needed to handle the internet connection whenever it connects or disconnects. Actually, it works perfectly in normal situations.
But the problem is that when the application is closed manually (by minimizing the app and then closing it by swiping out the app icon in the Recents button menu), it still receives the network status changes. This sometimes causes some exceptions.
Even I have included all the code in receiver function in try/catch block, but still sometimes a toast message containing an error message is shown. This sometimes happen even after some days after the closure of the app.
Please note that the code in the receiver function is more complicated than the code that is shown here and has some access to internal classes and variables.
Your app will still receive events, even if it isn't running. Before you do anything in onReceive(), you can check if the activity is running by:
Option 1: Use a static variable in your activity to check it's state for access from the receiver :
public class YourActivity extends Activity {
public static boolean isRunning = false;
#Overrride
public void onCreate(Bundle savedInstanceState){
isRunning = true;
....
}
//We need receiver to work when app is minimized
/*
#Override
public void onStart() {
super.onStart();
isRunning = true;
}
#Override
public void onStop() {
super.onStop();
isRunning = false;
}
*/
}
And in the receiver:
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
Log.d("mylog", "NetworkChangeReceiver Hit");
if(!YourActivity.isRunning)
return;
}
}
Option 2 : Using the ActivityManager
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
if (isAppForground(context))
return;
}
public boolean isAppForground(Context mContext) {
ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> tasks = am.getRunningTasks(1);
if (!tasks.isEmpty()) {
ComponentName topActivity = tasks.get(0).topActivity;
if (!topActivity.getPackageName().equals(mContext.getPackageName())) {
return false;
}
}
return true;
}
}
You'll need the permission:
<uses-permission android:name="android.permission.GET_TASKS" />
If you define receivers in your manifest, the app will receive events, even if it is not started.
http://developer.android.com/guide/topics/manifest/receiver-element.html
Broadcast receivers enable applications to receive intents that are broadcast by the system or by other applications, even when other components of the application are not running.
To fix this, just don't define the Receiver in the manifest, but do it programatically in onStart and unregister it again in onStop. The problem with this solution is, that you won't get messages if your app is in the background.
private BroadcastReceiver receiver;
#Overrride
public void onStart(){
super.onStart();
IntentFilter filter = new IntentFilter();
filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
filter.addAction("android.net.wifi.WIFI_STATE_CHANGED");
receiver = new NetworkChangeReceiver();
registerReceiver(receiver, filter);
}
#Override
protected void onStop() {
super.onStop();
//don't forget to unregister the receiver again
unregisterReceiver(receiver);
}
EDIT: onCreate and onDestroy won't work, as onDestroy will not be called in every instance the app is closed (e.g. if it is closed with the task manager)
Solution Found:
I found a perfect solution to my problem. Thanks to the correct answer in Android service crashes after app is swiped out of the recent apps list, I found out that when an app is closed via Recents list, the whole process will be created again and all the static variables will be freshed to their default values, and the onCreate and all other methods will not be called.
So the solution is something like:
public static boolean appStarted = false;
protected void onCreate(Bundle savedInstanceState) {
appStarted = true;
...
}
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
if (!MyActivity.appStarted)
return;
...
}
}
The key is to just keep track of when the app starts, and not when the app is closed (because the closing event of app is not dependable and in some situations doesn't work properly)
I managed to get my headset buttons get recognized by my app when pressed, but one of the buttons needs to call a method that's in MyCustomActivity. The problem is onReceive's 1st parameter is a Context that cannot be cast to Activity and so I am forced to implement my BroadcastReceiver as an inner class inside MyCustomActivity.
So far so good but how do I register this inner MediaButtonEventReceiver in the manifest?
For the independent class, this was simple:
<receiver android:name=".RemoteControlReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
What is the trick/syntax to do the same for MyCustomActivity's mReceiver?
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context ctx, Intent intent) {
// ...
}
}
You don't, if it's meant to be part of the Activity, you register it dynamically:
BroadcastReceiver receiver;
#Override
protected void onCreate (Bundle b)
{
super.onCreate (b);
IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);
filter.setPriority(10000);
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context ctx, Intent intent) {
// ...
}
};
registerReceiver (receiver, filter);
}
Then don't forget to unregister in onPause() (to avoid leaking).
#Override
protected void onPause()
{
try{
unregisterReceiver (receiver);
}
catch (IllegalStateException e)
{
e.printStackTrace();
}
super.onPause();
}
This dynamic registration does mean however, that if your Activity isn't in the foreground, the button won't work. You can try unregistering in onDestroy() instead, but the surest way to avoid leaking is onPause().
Alternatively, to make the button respond no matter what, consider making a Service, and having that register your receiver.
So far so good but how do I register this inner MediaButtonEventReceiver in the manifest?
You can't. You can register it dynamically by calling registerReceiver() on the activity, though.
I'm using C2DM, my BroadcastReceivers propagate the C2DM events to a local service. the service complete the registration by sending the id to my webserver pus it's responsible for letting the device know about new messages, however if the application (one of the activities) is up we want to send an intent to that activity with the new data so it can be updated, if not than the NotificationManager is used to notify the user.
The issue is, how to know the activity is running ? the Application object is not an option since the Service is part of the application it's obviously going to be present. unregister in the onDesroy of each application is also not an option since it may occur in orientation change...
Any standard way to get it done ?
Solution 1:
You can use ActivityManager for Checking if Activity is Running or not:
public boolean isActivityRunning() {
ActivityManager activityManager = (ActivityManager)Monitor.this.getSystemService (Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> activitys = activityManager.getRunningTasks(Integer.MAX_VALUE);
isActivityFound = false;
for (int i = 0; i < activitys.size(); i++) {
if (activitys.get(i).topActivity.toString().equalsIgnoreCase("ComponentInfo{com.example.testapp/com.example.testapp.Your_Activity_Name}")) {
isActivityFound = true;
}
}
return isActivityFound;
}
need to add the permission to your manifest..
<uses-permission android:name="android.permission.GET_TASKS"/>
Solution 2:
Your can use an static variable in your activity for which you want to check it's running or not and store it some where for access from your service or broadcast receiver as:
static boolean CurrentlyRunning= false;
public void onStart() {
CurrentlyRunning= true; //Store status of Activity somewhere like in shared //preference
}
public void onStop() {
CurrentlyRunning= false;//Store status of Activity somewhere like in shared //preference
}
I hope this was helpful!
The next approach would work well if you want to handle incoming Google Cloud message (C2DM) by your activity (if any is running) or issue a notification if no activities are running.
Register one BroadcastReceiver in the manifest file. This receiver will handle C2D messages whenever application not running. Register another BroadcastReceiver programmatically in your activity. This receiver will handle C2D messages whenever activity is running.
AndoroidManifest.xml
<receiver
android:name=".StaticReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.mypackage" />
</intent-filter>
</receiver>
MyReceiver.java
public class StaticReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Trigger a Notification
}
}
MyActivity.java
public class MyActivity extends ActionBarActivity {
#Override
protected void onResume() {
super.onResume();
final IntentFilter filter = new
IntentFilter("com.google.android.c2dm.intent.RECEIVE");
filter.addCategory("com.mypackage");
filter.setPriority(1);
registerReceiver(dynamicReceiver, filter,
"com.google.android.c2dm.permission.SEND", null);
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(dynamicReceiver);
}
private final BroadcastReceiver dynamicReceiver
= new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent) {
// TODO Handle C2DM
// blocks passing broadcast to StaticReceiver instance
abortBroadcast();
}
};
}
Note! To catch broadcasts first, the priority of dynamicReceiver IntentFilter must be higher than priority of StaticReceiver instance IntentFilter (default priority is '0').
PS. It looks like broadcasts issued by Google Cloud Messaging Service are ordered broadcasts. Original idea author: CommonsWare
Copied from here.
you can use a static variable within the activity.
class MyActivity extends Activity {
static boolean active = false;
public void onStart() {
active = true;
}
public void onStop() {
active = false;
}
}
Easiest way to check that whether an Activity is running or not is:
Context context = MyActivity.this;
if (! ((Activity) context).isFinishing()) {
// Activity is running
} else {
// Activity has been finished
}
Note: If activity is not running you should not perform any UI related operation.
I've used the following code to disconnect a call programatically but It's not working.
private void callDisconnect(){
try{
TelephonyManager manager = (TelephonyManager)this.getSystemService(this.TELEPHONY_SERVICE);
Class c = Class.forName(manager.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
m.setAccessible(true);
ITelephony telephony = (ITelephony)m.invoke(manager);
telephony.endcall();
} catch(Exception e){
Log.d("",e.getMessage());
}
}
Can anybody help me with this?? Do I need to change the code or something...??
For disconnecting a call programmatically you must add ITelephony.AIDL file in your project. If you have added it, then your package name must be com/android/internal/telephony/ITelephony.AIDL: for more information see Blocking Incoming call. Download the AIDL file from here.
To disconnect a call use endCall(); method of ITelephony
Simply use this broadcastreceiver. I tested it in one of my application and it works perfectly.
public class MyBroadcastReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, final Intent intent)
{
if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL))
{
String phoneNumber = intent.getExtras().getString(Intent.EXTRA_PHONE_NUMBER);
if (phoneNumber.equals("123456"))
{
if (getResultData() != null)
{
setResultData(null);
}
}
}
}
}
It is not possible anymore in newer versions of android. The user decides when to end the call if it has already started. You can however block calls from happening.
You can block the outgoing call using the setResultData(null) function in the onReceive method of the Broadcast receiver.
public class BlockOutgoing extends BroadcastReceiver
{
String number;
#Override
public void onReceive(Context context, Intent intent)
{
Log.d("12280", "asdasNumber is-->> " + number);
number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
setResultData(null);
Toast.makeText(context, "Outgoing Call Blocked" , 5000).show();
}
}
<receiver
android:name=".BlockOutgoing"
android:label="#string/app_name" >
<intent-filter android:priority="1">
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
You cannot end a call like that in android 2.3+... using your code... I think only user can end his call...and for earlier versions You can see this link and This one
I have an application which should watching incoming SMS (scan SMS text and show toast messages based on content) , even after my application is closed. The desired functionality is app watching all incoming SMS until app will not moved from device, and now it works like this. But I think, if I will need soon, to "switch of" this "watching eye", how I could to do this?
public class SmsReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
//---get the SMS message passed in---
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
if (bundle != null)
{
//do some action
}
}
BroadcastReceiver's code is a separate unit SMSReceiver.java. From main Activity I do not call this receiver, do not register and do not unregister. It's just working independently. Amazing.
So.. how I can ti stop this receiver??
The most common way to register/unregister BroadcastReceivers is to use the onResume() and onPause() methods of your Activity.
Firstly remove the <intent-filter> from your manifest, i.e., delete this section......
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECIEVED"></action>
</intent-filter>
Then add something like this to your Activity....
public class MyActivity extends Activity {
private final String ACTION_SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
private SMSReceiver smsReceiver = null;
private Boolean isReceiverRegistered = false;
#Override
protected void onResume() {
if (!isReceiverRegistered) {
registerReceiver(smsReceiver, new IntentFilter(ACTION_SMS_RECEIVED));
isReceiverRegistered = true;
}
}
#Override
protected void onPause() {
if (isReceiverRegistered) {
unregisterReceiver(smsReceiver);
isReceiverRegistered = false;
}
}
}
You'll have to take the BroadcastReceiver out of your Manifest to control it such as using it in a Service or Activity. When its in the Manifest its always on.