I have an already built application and I want to add a feature that has to be started when a call ends.
How can I achieve that?
I thought that declaring in my manifest something like this
<activity android:name="Filter">
<intent-filter>
<category android:name="android.intent.SOMETHING" />
</intent-filter>
</activity>
could be enough, but what kind of Intent I have to put on the filter?
Looking in the documentation I found only the intents that detects when a call is started.
Is what I'm looking for possible?
I have done this using a broadcast receiver. Works! code looks like this -
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.gopi"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<application android:icon="#drawable/icon" android:label="#string/app_name">
<receiver android:name=".IncomingCallTracker">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
</application>
</manifest>
The IncomingCallTracker code snippet looks like -
public class IncomingCallTracker extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
Set<String> keys = bundle.keySet();
for (String key : keys) {
Log.i("MYAPP##", key + "="+ bundle.getString(key));
}
}
}
You can look for the key 'state' in the bundle. When its value is 'IDLE' it means call has ended and you can perform whatever action you want to based on this.
You can use the PhoneStateLisenter to listen out for changes in the call state.
So you listen for the LISTEN_CALL_STATE change.
With the onCallStateChanged method.
So when the state changes from OFFHOOK to IDLE start your application
Related
I've implemented a BroadcastReceiver according to https://developer.android.com/guide/components/broadcasts but it does not seem to work.
The receiver part of my Manifest.xml looks like this (I use android.permission.ACCESS_NETWORK_STATE and android.permission.ACCESS_WIFI_STATE):
...
<receiver android:name=".BackgroundTask">
<intent-filter>
<action android:name="android.net.wifi.WIFI_STATE_CHANGED"/>
<action android:name="android.net.wifi.STATE_CHANGE" />
</intent-filter>
</receiver>
...
and it's declared within my application.
My BroadcastReceiver class looks like this:
public class BackgroundTask extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("Connection changed!");
Toast.makeText(context, "Network state changed", Toast.LENGTH_LONG).show();
}
}
Neither the toast is displayed nor I receive the println-ed output on my logcat.
I also read the note which recommends me to use scheduled jobs instead of receivers, but I could not find an example how to use this for listening to network changes.
The reason I want to use this is because I want my (background)-app only to run while my phone is connected to my WiFi - if you have any different suggestions on how to implement this, I'm also very thankful.
Btw. I'm using Android 8.0.0.
Cheers,
Nikolar
Update:
Somehow it still does not work. Am I forgetting anything?
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="mypackagename">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<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">
<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=".BootReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
<receiver android:name=".BackgroundPoller">
</receiver>
</application>
</manifest>
Just for clearence I renamed my BackgroundTask-Class to BootReceiver:
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("INFO", "BootReceiver started");
Intent newIntent = new Intent(context, BackgroundPoller.class);
context.sendBroadcast(newIntent);
Log.d("INFO", "BackgroundPoller activated");
}
}
When I successfully send my broadcast
adb.exe shell am broadcast -a android.intent.action.ACTION_BOOT_COMPLETED
I still don't get a log output.
To get around Oreo's broadcast receiver restrictions, you have to register your receivers using Context.registerReceiver(). You could do this by subclassing Application and registering receivers in onCreate(). The only downside to doing this is your app would have to be launched to have Application.onCreate() get called. To get around this, you could register an ACTION_BOOT_COMPLETED receiver in your manifest as this action is exempt from the restriction. Your ACTION_BOOT_COMPLETED receiver doesn't have to do anything, but it will force your app to start running on boot and therefore Application.onCreate() will get called. Then the only challenge is keeping your app running because the system will kill it if the user doesn't go into it. There's a couple options to solve this. You could write a foreground service whose only purpose is to keep the app alive. Or perhaps use AlarmManager to schedule some intent that will wake your app back up, which will register your receivers again.
I am trying to develop a ToDo application which helps user make notes as soon as call ends. In general life we are told many things to be done on phone. For example : buy grocery on way back to office.
I am facing difficulty in starting this application. I am using BroadcastReceiver How should I implement onReceive() method?
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.your"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<application android:icon="#drawable/icon" android:label="#string/app_name">
<receiver android:name=".CallTracker">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
</application>
BroadcasrReceiver
public class CallTracker extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
}
}
Look for the 'state' in the bundle. When the state changes from OFFHOOK to IDLE start your application.
From activity you can use this example
I have a broadcast receiver for incoming call.I want to launch a new activity when an incoming call comes.I am aware of the changes that are made from android 3.0,that the broadcast receiver will not work unless user manually starts an application
For that purpose I launch a dummy activity with just a toast message in it.Still the broadcast receiver is not working.
Here is my code
My broadcastreceiver
public class IncomingCallResult extends BroadcastReceiver
{
String TAG="IncomingCallResult";
#Override
public void onReceive(Context arg0, Intent I1)
{
Log.i(TAG,"inside on receive........");
Bundle bundle=I1.getExtras();
String state=bundle.getString(TelephonyManager.EXTRA_STATE);
if(state.equals(TelephonyManager.EXTRA_STATE_RINGING))
{
Intent flash_intent=new Intent(arg0,LedFlasher.class);
flash_intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
arg0.startActivity(flash_intent);
}
}
}
manifest file
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.blinker"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.FLASHLIGHT"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver
android:name=".IncomingCallResult"
android:enabled="true">
<intent-filter
android:priority="214783648"
android:name="android.intent.action.PHONE_STATE">
</intent-filter>
</receiver>
<activity
android:name=".LedFlasher"
android:label="#string/title_activity_incoming_call_result" >
</activity>
<activity
android:name=".Dummy">
<intent-filter >
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
What is wrong with the code?
Please help
As you have already known that the broadcast receiver will not work unless user manually starts an application For that purpose, you should not be surprised that your broadcast receiver will not work until user Manually open your application once. That is to say, you have to make a launcher activity which user is able to click and open it manually.
And what's more, it is better to Open and stay in your application for like 20s since I remember that the change of application configuration will take 10 or 20s to be saved.
I want to write a service in Android which starts based on USB_DEVICE_ATTACHED intent. So, basically my service should start when a specific USB Device(FT232C - VID:PID 0403:6010) is connected and stop when that USB device is detached. Is it possible to do that or should I always have an Activity which starts this service in case it is not already started? The intent of the service in the end is to update the location on the LocationProvider with a TEST_PROVIDER based on what location is provided from this USB device.
I already tried creating a service with this configuration in AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.testlocservice"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="12" android:targetSdkVersion="15" />
<uses-feature android:name="android.hardware.usb.host"/>
<supports-screens android:resizeable="true" android:smallScreens="true" android:anyDensity="true" android:largeScreens="true" android:xlargeScreens="true" android:normalScreens="true"/>
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<application android:label="#string/app_name"
android:icon="#drawable/ic_launcher"
android:theme="#style/AppTheme">
<service android:name="com.testlocservice.LocationService" android:process=":LocService" android:enabled="true" android:exported="true">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="#xml/device_filter" />
</service>
</application>
</manifest>
The xml/device_filter.xml contains this
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-device vendor-id="0403" product-id="6010"/>
</resources>
My LocationService class has overridden onStartCommand() which handles the USB_DEVICE_ATTACHED intent
From my experience a <service> cannot receive the USB intents. I overcame this by creating a hidden activity to receive the intent and re-broadcast it. Of course this activity could also handle starting/stopping your service.
I have already put up some working code here:
https://stackoverflow.com/a/15151075/588476
You will just have to change it so it starts and stops your service automatically.
I believe the main problem is the number base for the vendor and product id's. The format in the device filter xml should be decimal, so vendor-id="1025" and product-id="24592".
Aside from that, it absolutely should be USB_DEVICE_ATTACHED, rather than UMS_CONNECTED (the latter is not USB host mode at all).
I don't have the authoritative answer as to whether a service could receive a broadcast intent, or whether you have to use an activity for that, but it seems like Wayne Uroda has good experience with this question.
Yes, it is very well possible, sorry to say that you are using wrong intent-filter in your reveiver tag in AndroidManifest.xml. Let me guide you
AndroidManifest.xml
.
.
.
<receiver android:name=".DetactUSB">
<intent-filter>
<action android:name="android.intent.action.UMS_CONNECTED" />
<action android:name="android.intent.action.UMS_DISCONNECTED" />
</intent-filter>
</receiver>
BroadcastReceiver file
public class DetactUSB extends BroadcastReceiver
{
private static final String TAG = "DetactUSB";
#Override
public void onReceive(Context context, Intent intent)
{
// TODO Auto-generated method stub
if (intent.getAction().equalsIgnoreCase( "android.intent.action.UMS_CONNECTED"))
{
// Fire your Intent to start Activity
Log.i(TAG,"USB connected..");
}
if (intent.getAction().equalsIgnoreCase( "android.intent.action.UMS_DISCONNECTED"))
{
}
}
}
I am attempting to write some JUnit tests for my android application. The application is a service.
I have tried several things to get the ServiceTestCase to launch the service but it fails to.
HOWEVER, when i debug the ServiceTestCase it WILL launch the service. I belive this is because the ServiceTestCase is calling setup and not giving enough time for the service to launch before it kills it...
I am not completely sure, this is the first time i have ever used junit testing for android. VERY new to this. Any suggestions on what i can do to fix this problem?
I was thinking of creating some timer loop or something, but that seems REALLY dirty. Would like a much cleaner aproach.
Android Manifest for the service.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="dataservice.server"
<uses-sdk android:minSdkVersion="10" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<application android:icon="#drawable/icon" android:label="#string/app_name">
<service android:name="dataservice.server.DataServer" android:process=":remote" android:exported="true" android:enabled="true">
<intent-filter>
<action android:name="dataservice.DataService.BIND.1" />
</intent-filter>
<intent-filter>
<action android:name= ".DataServer" />
</intent-filter>
</service>
<receiver android:name="dataservice.server.Receiver">
<intent-filter>
<action android:name="android.intent.action.USER_PRESENT"></action>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
</application>
</manifest>
The ServiceTestCase i am attempting.
public class Publish extends ServiceTestCase<DataServer> {
private final static String TAG = "Publish Unit Test";
private Context mSystemContext;
public Publish() {
super(DataServer.class);
}
public Publish(Class<DataServer> serviceClass) {
super(serviceClass);
}
#Override
protected void setUp() throws Exception {
// TODO Auto-generated method stub
super.setUp();
// this is where i am attempting to start the service.
// i have attempted other methods, but none of those worked either.
startService(new Intent(this.getContext(), DataServer.class));
}
public void testPublish() {
}
}
I was referencing one of the dependant projects incorrectly. Once this was fixed, it resolved the issue. So, check and make sure you are referencing your projects correctly if you are having the same issue.