I am trying to get the call block numbers in android N, i want to know the given is block number or not (ex:- 5554 emulator number)
Contacts, sms, phone state permissions has been given to allow to access the block numbers and i followed the "Android Developer" site https://developer.android.com/reference/android/provider/BlockedNumberContract.html
But i am unable to get the block numbers, i am using latest android studio 2.2.2 and checked the functionality in android N emulator i don't have device.
Here is my code.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// Button onclick method to show the logs
public void displayBlockCursorCount(View view) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
String number = "5552";
if (BlockedNumberContract.canCurrentUserBlockNumbers(MainActivity.this)) {
if (BlockedNumberContract.isBlocked(MainActivity.this, number)) {
Log.e(TAG, "given number is blocked >>>>>> " + number);
}
}
}
}
}
I am getting the
java.lang.SecurityException: Caller must be system, default dialer or default SMS app.
Please post the comment if down comment and thanks for advance.
To access blocked contacts,Your app should be default calling app or Messaging app else it throws security exception.
Add additional check
private boolean isAppAsDefaultDialer() {
TelecomManager telecom = mContext.getSystemService(TelecomManager.class);
if (getApplicationContext().getPackageName().equals(telecom.getDefaultDialerPackage())) {
return true;
}
return false;
}
or check sources https://android.googlesource.com/platform/packages/providers/BlockedNumberProvider/+/android-7.0.0_r1/src/com/android/providers/blockednumber/BlockedNumberProvider.java
And make you app as defaul dialer
<intent-filter>
<action android:name="android.intent.action.DIAL"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="tel"/>
</intent-filter>
Related
I am using the Android Class CallScreeningService onScreenCall(Call.Details calldetails) to get all incoming calls and everything works fine! From now I have an error, that on Android 10 devices the function calldetails.getExras() and calldetails.getIntentExtras() always returns NULL, instead of a Bundle, where I can read some further information. On Android 9 devices and older everything works fine.
Someone has a similar issue? Here is the Source Code and some Declarations:
public class IncomingCallService extends CallScreeningService {
#Override
public void onScreenCall(Call.Details callDetails) {
if (callDetails.getExtras() != null) {
Log.d(LOG_TAG, "Everything works on Android 9 or older");
}else{
Log.d(LOG_TAG, "Its Null on Android 10!");
}
if (callDetails.getIntentExtras() != null) {
Log.d(LOG_TAG, "Everything works on Android 9 or older");
}else{
Log.d(LOG_TAG, "Its Null on Android 10!");
}
}
And Manifest.xml:
<service android:name=".call_handler.IncomingCallService"
android:permission="android.permission.BIND_SCREENING_SERVICE">
<intent-filter>
<action android:name="android.telecom.CallScreeningService"/>
</intent-filter>
</service>
According to Android docs:
Note: The Call.Details instance provided to a call screening service
will only have the following properties set. The rest of
the Call.Details properties will be set to their default value
or null.
Call.Details#getCallDirection()
Call.Details#getConnectTimeMillis()
Call.Details#getCreationTimeMillis()
Call.Details#getHandle()
Call.Details#getHandlePresentation()
Only calls where
the Call.Details#getHandle() Uri#getScheme() is PhoneAccount#SCHEME_TEL are
passed for call screening. Further, only calls which are not in the
user's contacts are passed for screening. For outgoing calls, no
post-dial digits are passed.
So what you are seeing it's just the expected behavior for Android 10.
On Androind 29+ you need user permission :
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
RoleManager roleManager = (RoleManager) getSystemService(ROLE_SERVICE);
Intent intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_CALL_SCREENING);
startActivityForResult(intent, 1);
}
I've implemented iOS and Android SDK, now I'm testing my app configuration in test environment. While with iOS everything seems working fine, I've noticed that with Android, the install event is correctly attributed to my quick link, any other events I'm sending (even thos I can correctly see them in the liveview) are not attributed to the quick link used to open the app.
Here my dependencies:
com.android.tools.build:gradle:3.1.1
com.google.gms:google-services:4.2.0
io.fabric.tools:gradle:1.31.0
com.android.support:appcompat-v7:28.0.0
Here the main lines of code:
#Override
protected void handleOnStart() {
super.handleOnStart();
Branch.enableDebugMode();
// Branch object initialization
Branch.getAutoInstance(this.getActivity().getApplication());
branchInstance = Branch.getInstance();
branchInstance.disableTracking(trackingDisabled);
branchInstance.initSession(new Branch.BranchReferralInitListener() {
#Override
public void onInitFinished(JSONObject referringParams, BranchError error) {
if (error != null) {
log("onInitFinished - " + error.getMessage());
} else {
log("onInitFinished invoked with " + referringParams.toString());
testEvent();
// Retrieve deeplink keys from 'referringParams' and evaluate the values to determine where to route the user
// Check '+clicked_branch_link' before deciding whether to use your Branch routing logic
}
}
}, getActivity().getIntent().getData(), getActivity());
}
#Override
public void onNewIntent(Intent intent) {
this.setIntent(intent);
}
private void testEvent() {
BranchEvent event = new BranchEvent(BRANCH_STANDARD_EVENT.VIEW_ITEM);
event.logEvent(this.getActivity());
}
And my AndroidManifest.xml looks like this:
<application android:launchMode="singleTask" .....>
<meta-data android:name="io.branch.sdk.BranchKey" android:value="#string/branchio_key_live" />
<meta-data android:name="io.branch.sdk.BranchKey.test" android:value="#string/branchio_key_test" />
<meta-data android:name="io.branch.sdk.TestMode" android:value="#bool/branchio_test_mode" />
<receiver android:enabled="#bool/branchio_track_referral_active" android:name="io.branch.referral.InstallListener" android:exported="true">
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER" />
</intent-filter>
</receiver>
</application>
It looks like your code is slightly different than what we recommend in our Android Docs, so I would recommend you conform your code as closely as possible to our code snippets as possible. For example, we recommend initializing in the onStart() method whereas you are doing yours in handleOnStart(). Here are the Android docs: https://docs.branch.io/apps/android/
If you do this and are still having difficulties, please send an email to support#branch.io and provide your App ID which is found in your Account Settings on your dashboard so we can investigate this further.
I want to use USSD dialog which comes after dialing any USSD code say *123# which asks user to enter option number to perform specific task(s) depending upon sim card vendors. I need to interact with that dialog to provide input in the text box given into it programmatically.
However, I am able to read the USSD response that comes in Alert Dialog after dialing any USSD code, using AccessibilityService and I'm showing the response in a Toast as shown in the code below. I haven't found any solution to interact with USSD dialog yet.
public class UssdService extends AccessibilityService{
public static String TAG = "USSD";
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
Log.d(TAG, "onAccessibilityEvent");
String text = event.getText().toString();
if (event.getClassName().equals("android.app.AlertDialog")) {
Log.d(TAG, text);
Toast.makeText(this, text, Toast.LENGTH_LONG).show();
}
}
#Override
public void onInterrupt() {
}
#Override
protected void onServiceConnected() {
super.onServiceConnected();
Log.d(TAG, "onServiceConnected");
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.flags = AccessibilityServiceInfo.DEFAULT;
info.packageNames = new String[]{"com.android.phone"};
info.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
setServiceInfo(info);
}
}
Here is the service declaration in Manifest:
<service android:name=".UssdService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data android:name="android.accessibilityservice"
android:resource="#xml/config_service" />
</service>
For interacting with USSD dialog, I used below code.
I used the below code for click event:
List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText("Send");
for (AccessibilityNodeInfo node : list) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
I used the below code for setText in EditText. This is setText where the current focus is.
AccessibilityNodeInfo nodeInput = nodeInfo.findFocus(AccessibilityNodeInfo.FOCUS_INPUT);
Bundle bundle = new Bundle();
bundle.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,pMPIN);
nodeInput.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT,bundle);
nodeInput.refresh();
My company Hover has developed an Android SDK which uses accessibility services to run multi-step USSD sessions and have it appear to happen inside your app. The underlying method is similar to what is outlined in the accepted answer, but there is more of an abstraction layer, support for lots of devices that behave differently, and it hides the session from the user.
You create configurations for USSD services, trigger the session to run from your app and pass in any runtime variables you need. When the response is returned your app is notified and you can parse it as you need. It works on Android 4.3 and above.
The SDK is free to integrate and use until you hit large scale. Please see our docs to get started.
(Disclosure: I am the CTO of Hover)
I am making an application to call multiple numbers.
In that app
When I call to 1 person and if the call is answered by the user then
the loop should be stopped.
But If the call is rejected then the call should be on next number and
loop should be couninue.
My problem is I cant detect whether the call is rejected or answered. when I had search on net some people says it is not possible to detect the call is answered or rejected.
Is it really not possible to detect the call in android If it is possible then how can I do that?
I think you can check outgoing call time of last call in PhoneStateListener class' onCallStateChanged method. Fetch the data if state is idle that is TelephonyManager.CALL_STATE_IDLE.
Something like this:
Cursor mCallCursor = context.getContentResolver().query(android.provider.CallLog.Calls.CONTENT_URI,null,null,null,null);
int duration = mCallCursor.getColumnIndex( CallLog.Calls.DURATION);
while(mCallCursor.moveToFirst())
{
Toast.makeText(context, mCallCursor.getString(duration), Toast.LENGTH_LONG).show();
}
You can find more about that here. I haven't tested the above code. But something like that should work.
You can check if time's 00:00, then call next number of loop. Else you can stop calling.
Hope this helps you.
below is a code of detecting outgoing call by accessibility events -
Add a class which extends AccessibilityService in your projects -
public class CallDetection extends AccessibilityService {
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
acquireLock(this);
Log.d("myaccess","after lock");
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
Log.d("myaccess","in window changed");
AccessibilityNodeInfo info = event.getSource();
if (info != null && info.getText() != null) {
String duration = info.getText().toString();
String zeroSeconds = String.format("%02d:%02d", new Object[]{Integer.valueOf(0), Integer.valueOf(0)});
String firstSecond = String.format("%02d:%02d", new Object[]{Integer.valueOf(0), Integer.valueOf(1)});
Log.d("myaccess","after calculation - "+ zeroSeconds + " --- "+ firstSecond + " --- " + duration);
if (zeroSeconds.equals(duration) || firstSecond.equals(duration)) {
Toast.makeText(getApplicationContext(),"Call answered",Toast.LENGTH_SHORT).show();
// Your Code goes here
}
info.recycle();
}
}
}
#Override
protected void onServiceConnected() {
super.onServiceConnected();
Toast.makeText(this,"Service connected",Toast.LENGTH_SHORT).show();
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.eventTypes = AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
info.notificationTimeout = 0;
info.packageNames = null;
setServiceInfo(info);
}
#Override
public void onInterrupt() {
}
}
But to get the function event.getSource() working you have to specify some of your service configuration through xml, so create a xml folder in your project and add a xml file called serviceconfig.xml (you can give any name you want.
The content of serviceconfig is below -
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="#string/callDetection"
android:accessibilityEventTypes="typeWindowContentChanged"
android:notificationTimeout="100"
android:canRetrieveWindowContent="true"
/>
You can find more about serviceconfig in Here
Now add your service in you Manifest file like this -
<service android:name=".CallDetection"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:label="#string/callDetection">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="#xml/serviceconfig" />
</service>
And youre done, just run the app and go to Accessibility settings in your phone, you will find an option named as detection (or whatever name you have given as your service description), switch that on to give accesibility permissions for you app.
Now you will see a toast when call is answered.
you can Code any code you want in there, also you can call a callback function in your activity
Most important - Dont call your call window(android dialer window) untill the call is answered, otherwise this will not work.
Note - As android doesn't provide any solution to detect if the call is answered or not, this is the best alternative i have made, hope it works for you.
With Glass you can launch an app via the 'OK, Glass' menu and it seems to pick the nearest match unless a command is miles off, and you can obviously see the list of commands.
Is there anyway from within the app, or from the voice prompt (after the initial app trigger) to have a similar list given and return the nearest match.
Random (non-real world) example, an app that shows you a colour, "OK Glass, show the colour red"
'show the colour' could be your voice trigger and seems to be matched by glass on a 'nearest neighbor' method, however 'red' is just read in as free text and could be easily misheard as 'dread' or 'head', or even 'read' as there is no way of differentiating 'read' from 'red'.
Is there a way to pass a list of pre-approved option (red, green, blue, orange*, etc.) to this stage, or to another voice prompt within the app so the user can see the list and get more accurate results when there is a finite set of expected responses (like the main ok glass screen)?
*ok well nothing rhymes with orange, we're probably safe there
The Google GDK doesn't support this feature yet. However, the necessary features are already available in some libraries and you can use them as long as the GDK doesn't support this natively.
What you have to do:
Pull the GlassVoice.apk from your Glass: adb pull /system/app/GlassVoice.apk
Use dex2jar to convert this apk into a jar file.
Add the jar file to your build path
Now you can use this library like this:
public class VoiceActivity extends Activity {
private VoiceInputHelper mVoiceInputHelper;
private VoiceConfig mVoiceConfig;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.voice_activity);
String[] items = {"red", "green", "blue", "orange"};
mVoiceConfig = new VoiceConfig("MyVoiceConfig", items);
mVoiceInputHelper = new VoiceInputHelper(this, new MyVoiceListener(mVoiceConfig),
VoiceInputHelper.newUserActivityObserver(this));
}
#Override
protected void onResume() {
super.onResume();
mVoiceInputHelper.addVoiceServiceListener();
}
#Override
protected void onPause() {
super.onPause();
mVoiceInputHelper.removeVoiceServiceListener();
}
public class MyVoiceListener implements VoiceListener {
protected final VoiceConfig voiceConfig;
public MyVoiceListener(VoiceConfig voiceConfig) {
this.voiceConfig = voiceConfig;
}
#Override
public void onVoiceServiceConnected() {
mVoiceInputHelper.setVoiceConfig(mVoiceConfig, false);
}
#Override
public void onVoiceServiceDisconnected() {
}
#Override
public VoiceConfig onVoiceCommand(VoiceCommand vc) {
String recognizedStr = vc.getLiteral();
Log.i("VoiceActivity", "Recognized text: "+recognizedStr);
return voiceConfig;
}
#Override
public FormattingLogger getLogger() {
return FormattingLoggers.getContextLogger();
}
#Override
public boolean isRunning() {
return true;
}
#Override
public boolean onResampledAudioData(byte[] arg0, int arg1, int arg2) {
return false;
}
#Override
public boolean onVoiceAmplitudeChanged(double arg0) {
return false;
}
#Override
public void onVoiceConfigChanged(VoiceConfig arg0, boolean arg1) {
}
}
}
You can take advantage of the disambiguation step that occurs when multiple Activities or Services support the same Voice Trigger: simply have multiple Activities or Services in your application support "show me the color" as the voice trigger and label them with the color options.
Your manifest would look something like:
<application
android:allowBackup="true"
android:label="#string/app_name"
android:icon="#drawable/icon_50"
>
<activity
android:name="com.mycompany.RedActivity"
android:label="#string/red"
android:icon="#drawable/icon_red"
>
<intent-filter>
<action android:name="com.google.android.glass.action.VOICE_TRIGGER"/>
</intent-filter>
<meta-data
android:name="com.google.android.glass.VoiceTrigger"
android:resource="#xml/activity_start"
/>
</activity>
<activity
android:name="com.mycompany.BlueActivity"
android:label="#string/blue"
android:icon="#drawable/icon_blue"
>
<intent-filter>
<action android:name="com.google.android.glass.action.VOICE_TRIGGER"/>
</intent-filter>
<meta-data
android:name="com.google.android.glass.VoiceTrigger"
android:resource="#xml/activity_start"
/>
</activity>
<!-- ... -->
</application>
Those Activities or Services would only be used as a "trampoline" to launch the main logic of your app with the color selection.
If you haven't already, you should take a look at contextual voice menus that were added just a few weeks ago to the GDK. I had your exact same problem just the day before it was released, looking at it the next day and finding this helped me a lot! :)