I am new to learn to programme for Android. I was looking for a very long plug for the incoming call number. My search attempts were unsuccessful. I decided to create a plugin. I used as an example here are the sources:
https://github.com/petervojtek/cordova-plugin-signal-strength/blob/master/src/org/apache/cordova/plugin/SignalStrength.java
https://github.com/don/cordova-plugin-hello
Here's what I came up with:
package org.apache.cordova.plugin;
import android.content.Context;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Date;
import android.content.BroadcastReceiver;
import android.content.Intent;
public class SignalStrength extends CordovaPlugin {
CallStateListener ssListener;
String Number;
#Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
if (action.equals("go")) {
TelephonyManager tm = (TelephonyManager) cordova.getActivity().getSystemService(Context.TELEPHONY_SERVICE);
ssListener = new CallStateListener();
tm.listen(ssListener, PhoneStateListener.LISTEN_CALL_STATE);
callbackContext.success(name);
return true;
}
return false;
}
class CallStateListener extends PhoneStateListener {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
// called when someone is ringing to this phone
String Number= incomingNumber;
break;
}
}
}
}
Manifest:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
...
<receiver android:name=".CallReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
But unfortunately returns NULL
Help me to understand.
I'm using this plugin:
https://github.com/renanoliveira/cordova-phone-call-trap
usage is very simple:
if (window.PhoneCallTrap) {
PhoneCallTrap.onCall(function(state) {
console.log("CHANGE STATE: " + state);
switch (state) {
case "RINGING":
console.log("Phone is ringing");
break;
case "OFFHOOK":
console.log("Phone is off-hook");
break;
case "IDLE":
console.log("Phone is idle");
break;
}
});
}
Related
I have created two different Android applications. One contains a Service and the other one the Activity which binds the Service. This works well on all devices expected one. On the problematic device runs Android 6.0.1. On all other tested devices running Android 6 there are no problems. Same for devices with newer and older versions.
With packageManager.getPackageInfo("com.example.myexampleservice", 0) I checked that the service APK is installed.
My Activity class, which binds the Service (MainActivity.java, 1. project):
package com.example.myexampleactivity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
final static int MSG_SAY_HELLO = 1;
Messenger mService = null;
boolean mBound;
TextView textView;
Button button;
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
mService = new Messenger(service);
mBound = true;
button.setText("Send Message");
textView.setText("Everything is fine. You can press the button to send a message.");
}
#Override
public void onServiceDisconnected(ComponentName className) {
mService = null;
mBound = false;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
textView = findViewById(R.id.text_view);
button = findViewById(R.id.button);
textView.setText("Press the button to bind the service.");
button.setText("Bind service");
}
#Override
protected void onStop() {
super.onStop();
if (mBound) {
unbindService(mConnection);
mBound = false;
button.setText("Bind service");
}
}
public void onClickButton(View v) {
if (!mBound) {
Intent intent = new Intent("com.example.myexampleservice.SERVICE");
intent.setPackage("com.example.myexampleservice");
if (getApplicationContext().bindService(intent, mConnection, Context.BIND_AUTO_CREATE)) {
textView.setText("Everything is fine.");
} else {
// This happens only on one device. Why???
textView.setText("bindService(...) returns false. The following message is probably shown in the logcat:\n\n" +
"I BackgroundManagerService package not in whitelist com.example.myexampleservice\n" +
"I BackgroundManagerService not whitelist service Intent { act=com.example.myexampleservice.SERVICE pkg=com.example.myexampleservice }\n" +
"I BackgroundManagerService skipService Intent { act=com.example.myexampleservice.SERVICE pkg=com.example.myexampleservice } because of activity not started!");
}
} else {
Message msg = Message.obtain(null, MSG_SAY_HELLO, 0, 0);
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
}
My Service (MyExampleService.java, 2. project):
package com.example.myexampleservice;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.widget.Toast;
public class MyExampleService extends Service {
static final int MSG_SAY_HELLO = 1;
static class IncomingHandler extends Handler {
private Context applicationContext;
IncomingHandler(Context context) {
applicationContext = context.getApplicationContext();
}
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SAY_HELLO:
Toast.makeText(applicationContext, "hello!", Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
}
}
}
Messenger mMessenger;
#Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
mMessenger = new Messenger(new IncomingHandler(this));
return mMessenger.getBinder();
}
}
And the AndroidManifest of the Service application (AndroidManifest, 2. project):
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myexampleservice">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<service android:name=".MyExampleService">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="com.example.myexampleservice.SERVICE" />
</intent-filter>
</service>
</application>
</manifest>
Only on the one device that doesn't work the method bindService(...) returns false. For this device, the Logcat shows the followoing:
I BackgroundManagerService package not in whitelist com.example.myexampleservice
I BackgroundManagerService not whitelist service Intent { act=com.example.myexampleservice.SERVICE pkg=com.example.myexampleservice }
I BackgroundManagerService skipService Intent { act=com.example.myexampleservice.SERVICE pkg=com.example.myexampleservice } because of activity not started!
I am helpless, because the application on all other devices runs without problems. The Google search does not return any results for these log messages. Has anyone seen these log messages before and knows what to do here? Does anyone have any idea how to fix this problem?
I have built full voice recorder application.
I would like to start recording when a voice call starts on the phone, how can I detect the Calls state? tried some code and it didn't work for me.
I just need to know hot to start recording when a voice call starts (incoming and outgoing).
Here is an example of what you need.
Declare receiver in AndroidManifest
<receiver android:name=".IncomingCall">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
Give read phone state permission in AndroidManifest
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
Create a class IncomingCall with extends BroadcastReceiver class
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;
/**
* Created by matheszabi on Aug/20/2017 0020.
*/
public class IncomingCall extends BroadcastReceiver {
private Context context;
public void onReceive(Context context, Intent intent) {
this.context = context;
try {
// TELEPHONY MANAGER class object to register one listner
TelephonyManager tmgr = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
//Create Listner
MyPhoneStateListener PhoneListener = new MyPhoneStateListener();
// Register listener for LISTEN_CALL_STATE
tmgr.listen(PhoneListener, PhoneStateListener.LISTEN_CALL_STATE);
} catch (Exception e) {
Log.e("Phone Receive Error", " " + e);
}
}
private class MyPhoneStateListener extends PhoneStateListener {
public void onCallStateChanged(int state, String incomingNumber) {
Log.d("MyPhoneListener",state+" incoming no:"+incomingNumber);
if (state == 1) {
String msg = "New Phone Call Event. Incomming Number : "+incomingNumber;
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, msg, duration);
toast.show();
}
}
}
}
Above Android 6.0 you need to handle a bit different the permissions:
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private static final int MY_REQUEST_CODE = 1234;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onResume() {
super.onResume();
if (checkSelfPermission(Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.READ_PHONE_STATE},
MY_REQUEST_CODE);
}
}
public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == MY_REQUEST_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Now user should be able to use camera
Toast.makeText(this, "I have access", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "I DON'T have access", Toast.LENGTH_SHORT).show();
}
}
}
}
You must allow the permissions at the first time run:
Here is the screenshot of the working code:
I found how to do so:
package com.example.tsuryohananov.mycallrecorder;
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;
/**
* Created by tsuryohananov on 20/08/2017.
*/
public class MyPhoneReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
if (extras != null) {
String state = extras.getString(TelephonyManager.EXTRA_STATE);
Log.d("MY_DEBUG_TAG", state);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
String phoneNumber = extras.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
Log.d("MY_DEBUG_TAG", phoneNumber);
// here i need to save the number for the listview.
}
if ((state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK))){
String phoneNumber = extras.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
Toast.makeText(context,"Answered" + phoneNumber, Toast.LENGTH_SHORT).show();
MainActivity.recordStart();
}
if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)){
Toast.makeText(context,"Idle State", Toast.LENGTH_SHORT).show();
MainActivity.stopRecord();
}
}
}
}
I am originating a call from Android Studio. The code is as follows:
I want to get the state of the call at any point. The link: https://developer.android.com/reference/android/telecom/Call.html
shows the state of the call can be obtained by using the Class call.. SO if I use Call.getState() I should be able to get the current state. But I get the compilation error:
Error:(28, 20) error: Call() is not public in Call; cannot be accessed from outside package. There are several call states defined in the enum: Dialing, Ringing, Connected, DIsconnected, Holding, etc.
When I run the code, it does make the call as I can see the screen of emulator making the call.
The developer guide does not provide any examples of using these classes.
Thank you for your help.
package com.example.ramesh.makeacall;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.telecom.Call;
import android.telephony.*;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Call call;
call = new Call();
call();
}
private void call() {
try {
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:5555551212"));
System.out.println("====before startActivity====");
startActivity(callIntent);
} catch (ActivityNotFoundException e) {
Log.e("helloAndroid","Call failed",e);
}
}
}
Try to use like this(Haven't tried it though) -
Call.Callback callback = new Call.Callback() {
#Override
public void onStateChanged(Call call, int state) {
super.onStateChanged(call, state);
if(state == Call.STATE_RINGING){
//you code goes here
}
}
};
public class MyPhoneStateListener extends PhoneStateListener {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
handleRinging(incomingNumber);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
handleOffHook();
break;
case TelephonyManager.CALL_STATE_IDLE:
handleIdle();
break;
}
super.onCallStateChanged(state, incomingNumber);
}
}
and register statelistener :
telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.listen(myPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
I'm new to Android and I need to read the call state of the phone. I receive error when the app runs (stopped):
package com.example.droid1;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.widget.TextView;
import android.widget.Toast;
public class DroidActivity extends Activity {
private TextView text0;
private TelephonyManager telephoneM;
private PhoneStateListener listner;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_droid);
text0 = (TextView) findViewById(R.id.textout);
telephoneM = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
listner = new PhoneStateListener()
{
public void onCallStateChanged(int state, String incomingnumber) {
String stateS = "N/A";
switch(state) {
case TelephonyManager.CALL_STATE_IDLE:
stateS = "Oscioso";
Toast.makeText(DroidActivity.this, ""+stateS,Toast.LENGTH_SHORT).show();
break;
case TelephonyManager.CALL_STATE_RINGING:
stateS = "Sonando";
Toast.makeText(DroidActivity.this, ""+stateS,Toast.LENGTH_SHORT).show();
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
stateS = "Ocupado";
Toast.makeText(DroidActivity.this, ""+stateS,Toast.LENGTH_SHORT).show();
break;
}
text0.append (String.format("\nonCallStateChanged: %s",stateS));
}
};
telephoneM.listen(listner, PhoneStateListener.LISTEN_CALL_STATE);
}
}
I don't have any error messages in eclipse, the app installs without a problem on Virtual device but when it run I have the error message of "Unfortunatly Droid1 has stopped"
Any advice will be appreciated. Thx
check your manifest.
Did you put this permission
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
?
I would like to bring up a Toast and vibrate when call status is Idle.
I added this in the manifest file:
<receiver android:name="IncomingCallInterceptor">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE"/>
</intent-filter>
</receiver>
And this is IncomingCallInterceptor
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Vibrator;
import android.telephony.TelephonyManager;
import android.widget.Toast;
import android.app.Activity;
public class IncomingCallInterceptor extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
String msg = "Phone state changed to " + state;
if (TelephonyManager.EXTRA_STATE_RINGING.equals(state))
{
String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
msg += ". Incoming number is " + incomingNumber;
}
Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
if(msg == "IDLE")
{
ok() ;
}
}
public void ok()
{
Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(3000);
}
}
}
And I received this error:
Description Resource Path Location Type
The method getSystemService(String) is undefined for the type IncomingCallInterceptor IncomingCallInterceptor.java line 39 Java Problem
Make Sure You Have Added VIBRATE permission in manifest as:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="...">
<uses-permission android:name="android.permission.VIBRATE"/>
<application android:label="...">
...
</application>
</manifest>
change Your Code as:
public class IncomingCallInterceptor extends BroadcastReceiver {
private Context contextc;
#Override
public void onReceive(Context context, Intent intent)
{
this.contextc=context;
//YOUR CODE HERE
public void ok()
{
Vibrator v = (Vibrator)contextc.getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(3000);
}