I am new to android, I have created intent's like this -
<receiver android:name=".IncommigCallListener" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
<receiver android:name=".OutgoingCallReciever" >
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
Now i created a service like this -
<service
android:name=".CallLogger"
android:exported="false"/>
Class CallLogger
public class CallLogger extends IntentService {
public CallLogger(String name) {
super(name);
// TODO Auto-generated constructor stub
}
#Override
protected void onHandleIntent(Intent arg0) {
// TODO Auto-generated method stub
System.out.println("service started");
}
}
I don't want to have any activity in my application, i just want to start the service so that it can work in background and receive PHONE_STATE and NEW_OUTGOING_CALL intent.
When i start this application, it doesn't log anything on PHONE_STATE or NEW_OUTGOING_CALL intent.
How can start service in background without using any activity ?
Edit :
public class OutgoingCallReciever extends BroadcastReceiver {
#Override
public void onReceive(Context ctx, Intent intent) {
String number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
}
}
and
public class IncommigCallListener extends PhoneStateListener {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
String incommingCallNumber = incomingNumber;
System.out.println("incomming call : " + incomingNumber);
break;
}
}
}
Just start service in your BroadcastReceiver's onReceive method. As you are registering BroadcastReceiver in AndroidManifist, It will always listen for Broadcasts even if application is not running (OS will run it for you).
Example
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context, MyService.class);
context.startService(service);
}
}
EDIT
To start a service on Boot completed you can do something like this.
1) Add permission to your Manifist :
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
2) Register your Broadcast Receiver with BOOT COMPLETE action.
<receiver android:name="com.example.BootBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
3) In BootBroadcastReceiver.java:
public class BootBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent(context, MyService.class);
context.startService(serviceIntent );
}
}
You should be able to do something like this in your receiver.
public class OutgoingCallReciever extends BroadcastReceiver {
#Override
public void onReceive(Context ctx, Intent intent) {
String number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Intent service = new Intent(context, CallLogger.class);
context.startService(service);
}
}
You need to create an intent and call startService() on it to "launch" the service.
Also for what it's worth you should get out of the habbit of System.out.println use Log.d(tag,msg) to print debugging information to the logcat. You can switch the d to other letters if you want to print in different channels.
Why nothing gets printed is only due to the problem that System.out.println does not work in Android! Where do you think the background process will "print" this thing?
You need to change that to Log.d(tag, msg) and then check your logcat to see the output! Otherwise I guess your code might be running properly.
Related
I want to add a BroadCastReciver in a service. The BroadCastReceiver listens to phone calling. My problem is that the broadcast doesn't work in service (when I run the app it worked but when I go out of my app it didn't work).
MainActiviy.java:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(MainActivity.this,FirstService.class));
}
}
PhoneStateBrodcastRecevier.java:
public class PhoneStateBrodcastRecevier extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
try {
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(context.TELEPHONY_SERVICE);
MyPhoneStateListener myPhoneStateListener = new MyPhoneStateListener(context);
telephonyManager.listen(myPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
} catch (Exception e){}
}
}
FirstService.java:
public class FirstService extends Service {
BroadcastReceiver myreciReceiver;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
myreciReceiver=new PhoneStateBrodcastRecevier();
IntentFilter intentFilter=new IntentFilter();
intentFilter.addAction("android.intent.action.PHONE_STATE");
registerReceiver(myreciReceiver, intentFilter);
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.d("ddddddd", "start");
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("ddddddd", "finish");
}
}
And my manifest:
<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=".PhoneStateBrodcastRecevier">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE"/>
</intent-filter>
</receiver>
<service android:name=".FirstService"/>
</application>
When your target is to listen for phone state changes in the Service class itself. You can try to define it internally within the Service. This will decrease resource usage too as the system is not burdened with handling the lifecycle of another component. In your Service:
private final PhoneStateListener mPhoneListener = new PhoneStateListener() {
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
// Call receive state
if (state != TelephonyManager.CALL_STATE_IDLE) {
// Do something
}
}
};
Then you can register it to listen as (probably in onStartCommand()):
TelephonyManager mTelephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
mTelephonyManager.listen(mPhoneListener, PhoneStateListener.LISTEN_CALL_STATE);
And then unregister it from listening in onDestroy() (or whenever you are done):
mTelephonyManager.listen(mPhoneListener, PhoneStateListener.LISTEN_NONE);
Do something when the phone rings
Solution
This can be achieved by implementing a Broadcast Receiver and listening for a TelephonyManager.ACTION_PHONE_STATE_CHANGED action.
Discussion
If you want to do something when the phone rings you have to implement a broadcast receiver which listens for the TelephonyManager.ACTION_PHONE_STATE_CHANGED intent action. This is a broadcast intent action indicating that the call state (cellular) on the device has changed.
Create a class IncomingCallInterceptor which extends BroadcastReceiver.
Override the onReceive method to handle incoming broadcast messages.
The EXTRA_STATE intent extra in this case indicates the new call state.
If (and only if) the new state is RINGING, a second intent extra EXTRA_INCOMING_NUMBER provides the incoming phone number as a String.
We extract the number information from the EXTRA_INCOMING_NUMBER intent extra.
Note: Additionally you can act on a state change to OFFHOOK or IDLE when the user picks up the phone or ends/rejects the phone call respectively.
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.widget.Toast;
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;
// TODO This would be a good place to "Do something when the phone rings" <img src="http://androidlabs.org/wp-includes/images/smilies/icon_wink.gif" alt=";-)" class="wp-smiley">
}
Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
}
}
We have to register our IncomingCallInterceptor as a within the element in the AndroidManifest.xml file.
We register an 'intent-filter'…
and an action value which registers our receiver to listen for TelephonyManager.ACTION_PHONE_STATE_CHANGED broadcast messages.
Finally we have to register a so we are allowed to listen to phone state changes.
<receiver android:name="IncomingCallInterceptor">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE"/>
</intent-filter>
</receiver>
I have an application that I would like to have automatically start following boot completion. The following code seems overly complicated and I get erratic application starts when swiping to a neighbouring workspace.
What am I missing here? I have an activity class, a service class, as well as a broadcast receiver. Below is my code (in that order) followed by the manifest.
public class BlueDoor extends Activity implements OnClickListener{
Button btnExit;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.main);
btnExit = (Button) this.findViewById(R.id.ExitButton);
btnExit.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.ExitButton:
System.exit(0);
break;
}
}
}
service.class
public class BlueDoorStartService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
callIntent.setClass(this, BlueDoor.class);
startActivity(callIntent);
// do something when the service is created
}
}
broadcast receiver
public class StartBlueDoorAtBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
Intent serviceIntent = new Intent(context, BlueDoorStartService.class);
context.startService(serviceIntent);
}
}
}
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.bluedoor"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver
android:name=".StartBlueDoorAtBootReceiver"
android:enabled="true"
android:exported="false" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service android:name=".BlueDoorStartService" >
</service>
<activity
android:name=".BlueDoor"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
UPDATE Solution(s), 10/22/2015:
Changing the service to:
public class BlueDoorStartService extends Service {
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
}
and the receiver to:
public class StartBlueDoorAtBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Start Service On Boot Start Up
Intent serviceIntent = new Intent(context, BlueDoorStartService.class);
context.startService(serviceIntent);
//Start App On Boot Start Up
Intent App = new Intent(context, BlueDoor.class);
App.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(App);
}
}
resulted in a working configuration using a service w/no misbehaving. However deleting the service all together and modifying the receiver thus:
public class StartBlueDoorAtBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent App = new Intent(context, BlueDoor.class);
App.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(App);
}
}
also resulted in a functional as well as a more concise configuration that starts the application following boot completion.
Your BroadcastReceiver calls
context.startService(serviceIntent)
so the service will be created if it doesn't exist yet (which will be the case shortly after booting) and thus start the activity from its onCreate() method. So the app works, to a certain extent.
BUT when you call startService(), the system always calls the service's onStartCommand() method. You did not override that method, so the system uses the standard implementation from class android.app.Service.
As you can read on grepcode.com, the method will return a value like START_STICKY by default. This tells the system to keep the service alive until it is explicitly stopped.
In your case, I suppose the system reacted to the swiping by temporarily killing and then reanimating (= creating) the service, which in turn started your activity.
Some information on the service lifecycle can be found here.
What you can do:
Override onStartCommand() to start the activity from there instead of from onCreate(). Then use stopSelf(int) like described here
One last thing: when exiting from the activity, don't use System.exit(0) but call finish() instead, see this SO answer for "why".
I'm trying to create an external broadcast service which sends a number. A client (external application) trying to send a request to my service and the service sends back a number. I registered my service and broadcast resiever in AndroidManifest.xml:
<service android:exported="true" android:enabled="true" android:name=".MyService"/>
<receiver android:exported="true" android:enabled="true" android:name=".MyStartServiceReceiver">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
my broadcast class:
public class MyStartServiceReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent intent1 = new Intent(context, MyService.class);
context.startService(intent1);
}
}
in MyService class I'm trying to put extra data
public void onStart(Intent intent, int startId) {
Log.i(TAG, "service started");
intent.setClass(getApplicationContext(), MyService.class);
intent.setAction(Intent.ACTION_SEND);
intent.putExtra("result", 10);
sendBroadcast(intent);
}
and send it back, but I keep getting zero. To check my service I use adb shell:
adb shell am broadcast -a android.intent.action.SEND
Broadcasting: Intent { act=android.intent.action.SEND }
Broadcast completed: result=0
Does anybody know what's wrong in my service?
You can see here:
http://developer.android.com/reference/android/content/Intent.html
that ACTION_SEND is activity action, it cannot be used with receiver.
So you must switch from receiver to activity, you can make it a hidden activity using Theme.NoDisplay
[edit]
some more explanation: BroadcastReceiver with intent-filter for them?
Try something like this.
Method to send broadcast, used within the MyService
public static void sendSomeBroadcast(Context context, String topic) {
Intent actionIntent = new Intent();
// I would use Constants for these Action/Extra values
actionIntent.setAction(ConstantClass.SEND_SOME_BROADCAST);
actionIntent.putExtra(ConstantClas.BROADCAST_RESULT, 10);
LocalBroadcastManager.getInstance(context).sendBroadcast(actionIntent);
}
In action
public void onStart(Intent intent, int startId) {
sendSomeBroadcast();
}
BroadcastReceiver
public class MyStartServiceReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// do what you want with the intent, for example intent.getExtras()..
Intent intent1 = new Intent(context, MyService.class);
context.startService(intent1);
}
}
Binding the receiver and listening for specific Action
private void bindStartServiceReceiver() {
MyStartServiceReceiver startServiceReceiver = new MyStartServiceReceiver();
//This may need to be changed to fit your application
LocalBroadcastManager.getInstance(this).registerReceiver(subscribeTopicReceiver,
new IntentFilter(ConstantClass.SEND_SOME_BROADCAST));
}
I have a onBootCompleted broadcast receiver registered in the manifest.
It runs starts MyService. My service in the onCreate registers 3 more broadcast receivers dynamically.
The 3 new receivers filter on the following intent actions
LOCALE_CHANGED,
TIMEZONE_CHANGED and
CONNECTIVITY_CHANGED.
These works correctly when I run the application from Eclipse but, after I reboot the device and my service starts up none of receivers work.
I have a work around implementation but, I would like to know why this is happening?
Manifest:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<receiver android:name=".receiver.BootCompletedReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>
<service
android:name=".MyService"
android:enabled="true"
android:exported="false"
android:stopWithTask="false" >
</service>
Service:
public class MyService()
{
LocationTimeZoneChangedReceiver mLocationTimeZoneChangedReceiver = new LocationTimeZoneChangedReceiver()
NetworkChangedReceiver mNetworkChangedReceiver = new NetworkChangedReceiver()
public void onCreate()
{
registerReceiver(mLocationTimeZoneChangedReceiver, new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
registerReceiver(mLocationTimeZoneChangedReceiver, new IntentFilter(Intent.ACTION_TIMEZONE_CHANGED));
registerReceiver(mNetworkChangedReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
}
}
BootCompletedReceiver:
public class BootCompletedReceiver extends BroadcastReceiver
{
public void onReceive(Context context, Intent intent){}
}
MyApplication:
public class MyApplication extends Application
{
ServiceConnection mServiceConnection = new ServiceConnection() { anonymous class...}
public void onCreate()
{
bindService(new Intent(this, MyService.class), mServiceConnection,Context.BIND_AUTO_CREATE);
}
}
Edited:
Edited code for Plinio.Santos.
It's a big app with many moving parts so at best I can post small code snippets.
Following are the steps I am following for testing:
Push app via Eclipse,
test that network change receiver is working
leave wifi off
Now restart the device
wait for the process to start and turn on wifi.
I believe that the service is not started or bound due errors. Unfortunately I can not say it for sure without all binding/starting code.
Anyway, you can see bellow a code that worked fine after I rebooted (the app started, registered the receiver and is receiving the CONNECTIVITY_CHANGED broadcast.
AndroidManifest.xml:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<receiver android:name=".TestReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service
android:name=".TestService"
android:exported="true" />
Receiver class:
public class TestReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null && Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
Toast.makeText(context, "Intent.ACTION_BOOT_COMPLETED receiverd !", Toast.LENGTH_SHORT).show();
context.startService(new Intent(context, TestService.class));
}
}
}
Service class:
public class TestService extends Service {
private BroadcastReceiver mConnectivityChangedReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null && ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
Toast.makeText(context, "ConnectivityManager.CONNECTIVITY_ACTION receiverd !", Toast.LENGTH_SHORT).show();
}
}
};
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
registerReceiver(mConnectivityChangedReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
}
}
I want to open my application immediately when S Pen is detached , How can you do this, if the methods put under onSPenDetached is only called when my application is opened again?
Thanks,
Chandu
The following works on my Galaxy Tab A 9.7 with S-Pen (SM-P550) running Android 5.0.2.
Attaching and detaching the stylus creates Broadcast Intents of type com.samsung.pen.INSERT with a booleanExtra named penInsert of false if detached and true if put back into the device.
Thus a Broadcast Receiver can be created that filters this kind of events. The following code is for such a Broadcast Receiver which starts OneNote if the stylus is detached:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class SPenDetachIntentBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent penInsertIntent) {
if (!penInsertIntent.getBooleanExtra("penInsert", true)) {
try {
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage("com.microsoft.office.onenote");
context.startActivity(launchIntent);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
In the Manifest file you need to declare it as a receiver listening for com.samsung.pen.INSERT Broadcast Intents with an intent filter. The following entry in a project's AndroidManifest.xml declares SPenDetachBroadcastReceiver, generates an instance and makes it listening for com.samsung.pen.Insert Broadcast Intents:
<receiver
android:name=".SPenDetachIntentBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.samsung.pen.INSERT" />
</intent-filter>
</receiver>
The advantage over using registerSPenDetachmentListener on an SPenEventLibrary object to register a Service with an onSPenDetached method implemented is that you do not need any additional library files and you also do not need additional permissions.
You will need to create a BroadcastReceiver and a Service.
The service:
public class SPenService extends Service {
SPenEventLibrary mSPenEventLibrary = new SPenEventLibrary();
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
mSPenEventLibrary.registerSPenDetachmentListener(this, new SPenDetachmentListener() {
#Override
public void onSPenDetached(boolean bDetached) {
if (bDetached) {
Toast.makeText(SPenService.this, "S Pen Detached", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(SPenService.this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} else {
Toast.makeText(SPenService.this, "S Pen Inserted", Toast.LENGTH_SHORT).show();
}
}
});
}
#Override
public void onDestroy() {
super.onDestroy();
mSPenEventLibrary.unregisterSPenDetachmentListener(this);
}
}
The receiver:
public class SPenReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
context.startService(new Intent(context, SPenService.class));
}
}
}
The manifest (inside the <application> tag):
<receiver android:name=".SPenReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service android:name=".SPenService" >
</service>