The problem in my work is if I give the android.intent.action.PHONE_STATE intent from the shell it works but does not get the phone number. But the main problem is that when I call my phone it does not get any effect. What is the problem when I call my phone with another phone when the app is closed, why not receive this call?
Here is AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="homework.contactor">
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".ServiceReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
</application>
</manifest>
Here is the Receiver Code:
package homework.contactor;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
class MyPhoneStateListener extends PhoneStateListener {
public static Boolean phoneRinging = false;
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
Log.d("DEBUG", "IDLE");
phoneRinging = false;
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.d("DEBUG", "OFFHOOK");
phoneRinging = false;
break;
case TelephonyManager.CALL_STATE_RINGING:
Log.d("DEBUG", "RINGING");
phoneRinging = true;
break;
}
}
}
public class ServiceReceiver extends BroadcastReceiver {
TelephonyManager telephony;
public void onReceive(Context context, Intent intent) {
MyPhoneStateListener phoneListener = new MyPhoneStateListener();
telephony = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);
}
public void onDestroy() {
telephony.listen(null, PhoneStateListener.LISTEN_NONE);
}
}
Check this code, it is working for me
public class ServiceReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, Intent intent) {
TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
Toast.makeText(MainActivity.this, "" + incomingNumber, Toast.LENGTH_SHORT).show();
}
}, PhoneStateListener.LISTEN_CALL_STATE);
}
}
Related
I Could not figure out what is wrong with below code. I also checked about registering receiver twice. But that's also not the case. or may be I am missing something.
Could any please help. I really need it. :(
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.IBinder;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;
/**
*
* #author Bharat
*
*/
public class CallNotifierService extends Service
{
private static final String ACTION_IN = "android.intent.action.PHONE_STATE";
private static final String ACTION_OUT = "android.intent.action.NEW_OUTGOING_CALL";
private CallBr br_call;
#Override
public IBinder onBind(Intent arg0)
{
return null;
}
#Override
public void onDestroy()
{
Log.d("service", "destroy");
this.unregisterReceiver(this.br_call);
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
final IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_OUT);
filter.addAction(ACTION_IN);
this.br_call = new CallBr();
this.registerReceiver(this.br_call, filter);
return START_NOT_STICKY;
}
public class CallBr extends BroadcastReceiver
{
Bundle bundle;
String state;
String inCall, outCall;
public boolean wasRinging = false;
public boolean answered = false;
public boolean outgoing = false;
#Override
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(ACTION_IN))
{
if ((bundle = intent.getExtras()) != null)
{
state = bundle.getString(TelephonyManager.EXTRA_STATE);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING))
{
inCall = bundle.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
wasRinging = true;
Toast.makeText(context, "Incoming Call : " + inCall, Toast.LENGTH_LONG).show();
}
else if (state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK))
{
if (wasRinging == true)
{
answered = true;
Toast.makeText(context, "Answered", Toast.LENGTH_LONG).show();
}
}
else if (state.equals(TelephonyManager.EXTRA_STATE_IDLE))
{
wasRinging = false;
Toast.makeText(context, "Disconnected", Toast.LENGTH_LONG).show();
}
}
}
else if (intent.getAction().equals(ACTION_OUT))
{
if ((bundle = intent.getExtras()) != null)
{
outCall = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Toast.makeText(context, "Outgoing Call : " + outCall, Toast.LENGTH_LONG).show();
outgoing = true;
}
}
}
}
}
Below is the activity I am calling it from
public class MyActivity extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.roaming);
Intent intent = new Intent(this, CallNotifierService.class);
startService(intent);
}
.
.
.
}
Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ind.cosmos.main"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-sdk
android:minSdkVersion="22"
android:targetSdkVersion="22" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<!-- android:theme="#style/AppTheme"> -->
<activity
android:name="ind.cosmos.main.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="ind.cosmos.callRecord.CallNotifierService" />
</application>
As Bharat said it's better so handle it in code. Below is a trick to do so, found here, thanks to Michael Marvick who has given detail description as well.
public class PhoneStateBroadcastReceiver extends BroadcastReceiver {
public static final String TAG = "PHONE STATE";
private static String mLastState;
#Override
public void onReceive(Context context, Intent intent) {
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if (!state.equals(mLastState)) {
mLastState = state;
Log.e(TAG, state);
}
}
}
Actually .. there is nothing wrong with the code. its System who triggers this. some time its 2 times.. other times it touches 4 times.
So the best we can do it handle it in the code itself.
I have the same behavior, and there is no issue in your code. android.intent.action.PHONE_STATE can be received few times, but Intent's bundle is always different, for example:
D/App(2001): Bundle{ state => OFFHOOK; subscription => 1; }Bundle
D/App(2001): Bundle{ incoming_number => 555555555; state => OFFHOOK; subscription => 9223372036854775807; }Bundle
My Requirment
I am trying to build an application which shows a Toast whenever user makes a outgoing call from the phone. For this I am using a BroadcastReceiver to tap the call action and a service (to run Receiver always). once I start this activity, it starts showing toast when a outgoing call get initiated ...everything works well.
Issues
Sometimes I dont get any Toast Action EVEN for Outgoing call as well, is that mean service stops after some time ?
After phone reboot Toast Action for Outgoing call stops. Untill you start the servce again manually.
The code I have written is ok ? OR can it be improved ?
Below is the complete code -
MainActivity.class
public class MainActivity extends Activity
{
CallNotifierService m_service;
boolean isBound = false;
private ServiceConnection m_serviceConnection = new ServiceConnection()
{
#Override
public void onServiceConnected(ComponentName className, IBinder service)
{
m_service = ((CallNotifierService.MyBinder)service).getService();
Toast.makeText(MainActivity.this, "Service Connected", Toast.LENGTH_LONG).show();
isBound = true;
Intent intent = new Intent(MainActivity.this, CallNotifierService.class);
startService(intent);
}
#Override
public void onServiceDisconnected(ComponentName className)
{
m_service = null;
isBound = false;
}
};
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, CallNotifierService.class);
bindService(intent, m_serviceConnection, Context.BIND_AUTO_CREATE);
}
.
.
.
}
CallNotifierService.class
public class CallNotifierService extends Service
{
private final IBinder myBinder = new MyBinder();
private static final String ACTION_OUTGOING_CALL = "android.intent.action.NEW_OUTGOING_CALL";
private static final String ACTION_ANSWER = "android.intent.action.ANSWER";
private static final String ACTION_CALL = "android.intent.action.CALL";
private CallBr br_call;
#Override
public IBinder onBind(Intent arg0)
{
return myBinder;
}
#Override
public void onDestroy()
{
Log.d("service", "destroy");
this.unregisterReceiver(this.br_call);
Toast.makeText(CallNotifierService.this, "Receiver Un-Registered", Toast.LENGTH_LONG).show();
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
final IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_ANSWER);
filter.addAction(ACTION_CALL);
filter.addAction(ACTION_OUTGOING_CALL);
this.br_call = new CallBr();
this.registerReceiver(this.br_call, filter);
Toast.makeText(CallNotifierService.this, "onStartCommand Called", Toast.LENGTH_LONG).show();
return START_STICKY;
}
public class MyBinder extends Binder
{
CallNotifierService getService()
{
return CallNotifierService.this;
}
}
public class CallBr extends BroadcastReceiver
{
public CallBr() {}
#Override
public void onReceive(Context context, Intent intent)
{
Toast.makeText(context, "Action:"+intent.getAction(), Toast.LENGTH_LONG).show();
}
}
}
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.alwaysrunningprocesswithcallanswertap"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-sdk
android:minSdkVersion="22"
android:targetSdkVersion="22" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".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.alwaysrunningprocesswithcallanswertap.CallNotifierService" />
</application>
</manifest>
Could anyone please help for the issue OR pointout something better ?
#Bharat Once device switch off automatically service will stop, So when ever your device reboot that time you need to start service again then only you will get Toast Action, refer this example code :
BootCompleteReceiver.java
package com.example.newbootservice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class BootCompleteReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context, AutostartService.class);
context.startService(service);
}
}
AutostartService .java
package com.example.newbootservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
public class AutostartService extends Service {
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
return Service.START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service Destroy", Toast.LENGTH_LONG).show();
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
MainActivity.java
package com.example.newbootservice;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startService(new Intent(getBaseContext(), AutostartService.class));
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
Manifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.newbootservice"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<service android:name=".AutostartService"/>
<receiver android:name=".BootCompleteReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
I wrote a simple class that extends BroadcastReceiver to handle an incoming call and get the caller's number. Now I want to display that number in a popup window or something similar. I've tried to display an alert dialog or open an activity but my app crashed. Then I read that it's not a good idea to start dialog from a BroadcastReceiver class. I need you to advice me how to correctly display the caller's number on the screen when there's an incoming call. This is my Broadcast Receiver class:
package com.example.nrsearch;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
public class CallReceiver extends BroadcastReceiver {
public CallReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
Log.i("CallReceiverBroadcast", "onReceive() is called. ");
TelephonyManager teleMgr = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
PhoneStateListener psl = new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
Log.i("CallReceiverBroadcast", "onCallStateChanged() is called. ");
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
Log.i("CallReceiverBroadcast", "Incoming call caught. Caller's number is " + incomingNumber + ".");
}
}
};
teleMgr.listen(psl, PhoneStateListener.LISTEN_CALL_STATE);
teleMgr.listen(psl, PhoneStateListener.LISTEN_NONE);
}
}
I created a IncomingCallService service that extends from BroadcastReceiver to handle an incoming call and get the caller's number. Now I displayed that Incoming caller number in a popup window like TrueCaller. Its working fine me. Hope it should helpful for you. Please try and let me know. Thanks
CallReceiver.java
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
public class CallReceiver extends BroadcastReceiver {
static String IncomingNumber;
#Override
public void onReceive(final Context context, Intent intent) {
TelephonyManager teleMgr = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
PhoneStateListener psl = new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
IncomingNumber = incomingNumber;
Log.i("CallReceiverBroadcast", "Incoming call caught. Caller's number is " + incomingNumber + ".");
Intent i = new Intent(context, IncomingCallService.class);
context.startService(i);
case TelephonyManager.CALL_STATE_IDLE:
Log.i("CallReceiverBroadcast", "CALL_STATE_IDLE");
IncomingCallService.clearView(context);
// Call Disconnected
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.i("CallReceiverBroadcast", "CALL_STATE_OFFHOOK");
IncomingCallService.clearView(context);
// Call Answer Mode
break;
}
}
};
teleMgr.listen(psl, PhoneStateListener.LISTEN_CALL_STATE);
teleMgr.listen(psl, PhoneStateListener.LISTEN_NONE);
}
}
IncomingCallService.java:
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
public class IncomingCallService extends Service {
static View view = null;
static WindowManager wm;
static LayoutInflater inflater;
static WindowManager.LayoutParams params;
private static TextView txtIncomingnumber;
static boolean processingAction = false;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onCreate();
params = new WindowManager.LayoutParams(WindowManager.LayoutParams.MATCH_PARENT, 350,
WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT);
params.gravity = Gravity.LEFT | Gravity.TOP;
params.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
wm = (WindowManager) getSystemService(WINDOW_SERVICE);
inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.activity_main,null);
wm.addView(view, params);
txtIncomingnumber = (TextView)view.findViewById(R.id.txtIncomingnumber);
txtIncomingnumber.setText("You have Incoming Call from " + CallReceiver.IncomingNumber);
return START_STICKY;
}
public static void clearView(Context context) {
wm = (WindowManager) context.getSystemService(WINDOW_SERVICE);
if(view != null) {
if(view.isEnabled()){
wm.removeView(view);
view = null;
}
}
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentLeft="true"
android:background="#0090FF"
android:padding="10dp"
android:keepScreenOn="true" >
<TextView
android:id="#+id/txtIncomingnumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="30dp"
android:text="Incoming Call Number"
android:textColor="#fff" />
</RelativeLayout>
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.stackoverflow"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" ></uses-permission>
<uses-permission android:name="android.permission.VIBRATE"></uses-permission>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver android:name=".CallReceiver" >
<intent-filter android:priority="99999">
<action android:name="android.intent.action.PHONE_STATE"/>
</intent-filter>
</receiver>
<activity
android:name="com.stackoverflow.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=".IncomingCallService">
</service>
</application>
</manifest>
If you want to show a dialog from inside your onReceive of the BroadcastReceiver, you have to start a transparent activity with an alert dialog and NEVER called setContentView(). The activity will have an transparent view and only the alert dialog will show..
Your Broadcast Receiver onReceive
#Override
public void onReceive(Context context, Intent intent) {
Log.i("CallReceiverBroadcast", "onReceive() is called. ");
TelephonyManager teleMgr =(TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
PhoneStateListener psl = new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
Log.i("CallReceiverBroadcast", "onCallStateChanged() is called. ");
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
Log.i("CallReceiverBroadcast", "Incoming call caught. Caller's number is " +incomingNumber + ".");
//start activity which has dialog
Intent i=new Intent(context,DialogActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
};
teleMgr.listen(psl, PhoneStateListener.LISTEN_CALL_STATE);
teleMgr.listen(psl, PhoneStateListener.LISTEN_NONE);
}
And your DiaLogActivity
public class DialogActivity extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//dont call setcontent view
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Are you sure you want to exit?").setCancelable(
false).setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
}).setNegativeButton("No",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
}
I'm trying to create a small app that listens for my Bluetooth media receiver's on press commands and launches a Tasker task when it is pressed. The service is started and stopped using an intent I send from tasker.
Everything runs perfectly until I restart my device (or lose power) whilst my service's receiver is still registered. Once my device reboots, the receiver remains registered and my app crashes if I try to unregister it using my STOP intent. How do I unregister my receiver if my phone is about to switch off?
Target API is 16 (4.1):
MainActivity (A dummy activity for security):
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
finish();
}
}
RemoteControlReceiver
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class RemoteControlReceiver extends BroadcastReceiver {
public RemoteControlReceiver () {
super();
}
#Override
public void onReceive(Context context, Intent intent) {
intent.setClass(context, RemoteControlService.class);
context.startService(intent);
}
}
RemoteControlService
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.media.AudioManager;
import android.os.Handler;
import android.os.IBinder;
import android.view.KeyEvent;
import com.example.simplemediabuttonlistener.TaskerIntent;
public class RemoteControlService extends Service {
public RemoteControlService() {
}
private Handler handler;
//sets up the audio manager and names the receiver component (registered later)
AudioManager manager;
ComponentName mReciever = new ComponentName(RemoteControlReceiver.class.getPackage().getName(), RemoteControlReceiver.class.getName());
#Override
public void onCreate(){
super.onCreate();
}
#Override
public void onDestroy(){
super.onDestroy();
manager.unregisterMediaButtonEventReceiver(mReciever);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
handler = new Handler();
String intentAction = intent.getAction();
//if we are using our custom start intent
if (intentAction == "com.example.simplemediabuttonlistener.START"){
//we have launched from tasker...
//so register our receiver
manager = (AudioManager) getSystemService(AUDIO_SERVICE);
manager.registerMediaButtonEventReceiver(mReciever);
}
//if we are using our custom stop intent
if (intentAction == "com.example.simplemediabuttonlistener.STOP"){
//we have stopped from tasker...
//so stop service
stopSelf();
}
//if a media button is pressed
if (Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) {
KeyEvent event = (KeyEvent) intent
.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (event == null) {
return START_STICKY;
}
int keycode = event.getKeyCode();
int action = event.getAction();
//check which button it is and run the appropriate task
if (keycode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE
|| keycode == KeyEvent.KEYCODE_MEDIA_PLAY
|| keycode == KeyEvent.KEYCODE_MEDIA_PAUSE
|| keycode == KeyEvent.KEYCODE_HEADSETHOOK) {
if (action == KeyEvent.ACTION_DOWN) {
handler.post(new Runnable() {
public void run() {
if ( TaskerIntent.testStatus( getApplicationContext() ).equals( TaskerIntent.Status.OK ) ) {
TaskerIntent i = new TaskerIntent( "BTPLAY" );
getApplicationContext().sendBroadcast( i );
}
}
});
}
}
if (keycode == KeyEvent.KEYCODE_MEDIA_NEXT) {
if (action == KeyEvent.ACTION_DOWN) {
// Start your app here!
handler.post(new Runnable() {
public void run() {
if ( TaskerIntent.testStatus( getApplicationContext() ).equals( TaskerIntent.Status.OK ) ) {
TaskerIntent i = new TaskerIntent( "BTNEXT" );
getApplicationContext().sendBroadcast( i );
}
}
});
}
}
}
return START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
// We dont bind to an activity, so this is unused
return null;
}
}
AndroidManifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.simplemediabuttonlistener"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="18" />
<permission android:name = "net.dinglisch.android.tasker.PERMISSION_RUN_TASKS" />
<permission android:name = "android.permission.BLUETOOTH" />
<uses-permission android:name = "android.permission.BLUETOOTH" />
<uses-permission android:name = "net.dinglisch.android.tasker.PERMISSION_RUN_TASKS" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver android:name=".RemoteControlReceiver" >
<intent-filter android:priority="1000000000" >
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
<activity
android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".RemoteControlService">
<intent-filter>
<action android:name= "com.example.simplemediabuttonlistener.START">
<category android:name = "android.intent.category.DEFAULT" />
</action>
<action android:name= "com.example.simplemediabuttonlistener.STOP">
<category android:name = "android.intent.category.DEFAULT" />
</action>
</intent-filter>
</service>
</application>
</manifest>
If I'm not mistaken I think you need to switch
#Override
public void onDestroy(){
super.onDestroy();
manager.unregisterMediaButtonEventReceiver(mReciever);
}
to
#Override
public void onDestroy(){
manager.unregisterMediaButtonEventReceiver(mReciever);
super.onDestroy();
}
so it unregisters the receiver prior to it being destoryed.
I'm trying to set up PhoneStateListener but I get a PhoneCallListener cannot be resolved to a type.
public class ButtonView extends FrameLayout {
PhoneCallListener phoneListener = new PhoneCallListener();
TelephonyManager telephonyManager = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.listen(phoneListener,PhoneStateListener.LISTEN_CALL_STATE);
}
In another Example, I found its written like this and it's working
public class MainActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
// add PhoneStateListener
PhoneCallListener phoneListener = new PhoneCallListener();
TelephonyManager telephonyManager = (TelephonyManager) this
.getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.listen(phoneListener,PhoneStateListener.LISTEN_CALL_STATE);
}
What should I change in my code to make it working?
You have to create a receiver to catch phone calls.
To do this, add this in your in manifest.xml:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<receiver android:name=".ServiceReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
and create these classes:
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.webkit.WebView;
public class MyPhoneStateListener extends PhoneStateListener {
public static Boolean phoneRinging = false;
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
Log.d("DEBUG", "IDLE");
phoneRinging = false;
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.d("DEBUG", "OFFHOOK");
phoneRinging = false;
break;
case TelephonyManager.CALL_STATE_RINGING:
Log.d("DEBUG", "RINGING");
phoneRinging = true;
break;
}
}
}
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
public class ServiceReceiver extends BroadcastReceiver {
TelephonyManager telephony;
public void onReceive(Context context, Intent intent) {
MyPhoneStateListener phoneListener = new MyPhoneStateListener();
telephony = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);
}
public void onDestroy() {
telephony.listen(null, PhoneStateListener.LISTEN_NONE);
}
}