My Note :as I have already clarified in my initial post, I don't think it's a duplicate,
I already tried these method and it doesn't work for me,
The code below seems only work for 2.2, it requires MODIFY_PHONE_STATE which is not permitted after Android 2.2****
This is not duplicated questions since i have already looked many other post here and it doesn't work for me
I follow the solution from the link below:
block phone call
TelephonyManager tm = (TelephonyManager)
context.getSystemService(Context.TELEPHONY_SERVICE);
Class<?> c = Class.forName(tm.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
But the code give me exception when run on real device(which is Android 4.2)
java.lang.NoSuchMethodException: getITelephony
So, does it still possible use this solution on Android 4.2, if not,does there exist other solutions i can try?
Thanks a lot in advance
Create a file named ITelephony.aidl it should contain these data:
package com.android.internal.telephony;
interface ITelephony
{
boolean endCall();
void answerRingingCall();
void silenceRinger();
}
Create these folders under src
android > internal > telephony
Then Place the ITelephony.adl under telephony folder.
Copy this DeviceStateListener class and place it under any package on your project.
import android.content.Context;
import android.os.RemoteException;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import java.lang.reflect.Method;
public class DeviceStateListener extends PhoneStateListener {
private ITelephony telephonyService;
private Context context;
public DeviceStateListener(Context context) {
this.context = context;
initializeTelephonyService();
}
private void initializeTelephonyService() {
try {
TelephonyManager telephonyManager = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
Class clase = Class.forName(telephonyManager.getClass().getName());
try{
Method method = clase.getDeclaredMethod("getITelephony");
}catch (NoSuchMethodException e){
e.printStackTrace();
}
method.setAccessible(true);
telephonyService = (ITelephony) method.invoke(telephonyManager);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onCallStateChanged(int state, final String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
boolean isNumberIsBlocked=false;
// You can check here if incomingNumber string is under your blacklisted numbers
if (isNumberIsBlocked) {
try {
// This is the main code that block the incoming call.
telephonyService.endCall();
Thread t = new Thread(new Runnable() {
#Override
public void run() {
// You can run anything here lets say a notice to the user if a call is blocked
}
});
t.start();
} catch (RemoteException e) {
e.printStackTrace();
}
}
break;
}
}
}
Here is another important class "ServiceReceiver" place it also under any package of your project and resolve all possible imports.
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
public class ServiceReciever extends BroadcastReceiver
{
private static TelephonyManager telephony;
private static DeviceStateListener phoneListener;
private static boolean firstTime=true;
public ServiceReciever(Context context)
{
telephony=(TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
phoneListener=new DeviceStateListener(context);
}
#Override
public void onReceive(Context context, Intent intent)
{
if(firstTime)
{
telephony.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);
firstTime = false;
}
}
// You can use this in the future to stop the call blocker feature.
public void stopListening() {
telephony.listen(phoneListener, PhoneStateListener.LISTEN_NONE);
firstTime=true;
}
}
Copy this CallBlockerService class also and place it under any package of your project. It is an unkillable service that invokes the ServiceReceiver class.
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import com.katadigital.phone.callsmsblocker.callListener.ServiceReciever;
public class CallBlockerService extends Service {
public static final int notification_id = 111;
// ---------------------------------------
// Listening Services
// ---------------------------------------
private static ServiceReciever service;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
service = new ServiceReciever(getApplicationContext());
registerReceiver(service, new IntentFilter(
"android.intent.action.PHONE_STATE"));
System.out.println("Call blocker is running now");
}
#Override
public void onDestroy() {
service.stopListening();
unregisterReceiver(service);
service = null;
cancelStatusBarNotification();
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
public void cancelStatusBarNotification() {
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.cancel(notification_id);
}
}
Place this AfterBootReceiver class beside our CallBlockerService. Its job is to restart the blocker service when the phone starts from shutdown.
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class AfterBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
Intent serviceLauncher = new Intent(context, CallBlockerService.class);
context.startService(serviceLauncher);
}
}
Lastly place this on your AndroidManifest under tag.
<receiver android:name="com.callblocker.services.AfterBootReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<service android:name="com.callblocker.services.CallBlockerService" >
</service>
Replace "com.callblocker.services" with the folder location of the CallBlockerService and your AfterBootReceiver
I have tested this code until Android 4.4 KitKat. I hope you can follow the steps and it helps you with your problem.
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();
}
}
}
}
When i try to detect incoming calls with PhoneStateListener, it executes multiple times.
This is my code. onCallStateChanged method is called multiple times.
public class CallHelper {
public String number;
private Context ctx;
private TelephonyManager tm;
private CallStateListener callStateListener;
private OutgoingReceiver outgoingReceiver;
SharedPreferences trackMeData;
public CallHelper(Context ctx) {
this.ctx = ctx;
number ="";
callStateListener = new CallStateListener();
outgoingReceiver = new OutgoingReceiver();
trackMeData = ctx.getSharedPreferences("LockedSIM", 0);
}
private class CallStateListener extends PhoneStateListener {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
number = incomingNumber;
sendsmstoph(number);
System.out.println("Incomgin");
Toast.makeText(ctx, "Incoming: " + incomingNumber,Toast.LENGTH_LONG).show();
break;
}
}
}
Using BroadcastReceiver with functionality of PhoneStateListener
In above line: The problem is that every time when the onReceive() method is called a new TelphoneManager instance is created and registers as a listener to Phoone State .
Solution :
I made every variable of the CallReceiverBroadcast class static ! and it solved the problem !! to an extent but still the service is called twice every time it means that some how there is 2 instance of the class registered as a listener but i don't know why. Although i can work around it through some condition but it is causing unnecessary overhead and Anyone having a better solution will be highly Appreciated .
package com.example.netlogger.Receiver;
import java.util.Date;
import com.example.netlogger.util.LocalDatabase;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.telephony.TelephonyManager;
import android.util.Log;import android.widget.Toast;
public class CallActionsReceiver extends BroadcastReceiver {
static ThePhoneStateListener phoneStateListener;
#Override
public void onReceive(Context arg0, Intent arg1) {
TelephonyManager manager = (TelephonyManager) arg0
.getSystemService(arg0.TELEPHONY_SERVICE);
if (phoneStateListener == null) {
phoneStateListener = new ThePhoneStateListener(arg0);
manager.listen(phoneStateListener,
android.telephony.PhoneStateListener.LISTEN_CALL_STATE);
}
}
}
I'm trying to run startService() in my android app, but it is not working.
Here is the code from the call to start the service:
Intent mPositioningIntent = new Intent(this, MyGeoloqiPositioning.class);
stopService(mPositioningIntent);
startService(mPositioningIntent);
Here is the code from MyGeoloqiPositioning.java (note, this is taken with minor modifications from the source code of MapAttack)
package com.example.manhunttwopointoh;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.util.Pair;
import android.widget.Toast;
import com.example.manhunttwopointoh.MyFix;
import com.example.manhunttwopointoh.MyGeoloqiFixSocket;
import com.example.manhunttwopointoh.MyUDPClient;
public class MyGeoloqiPositioning extends Service implements LocationListener {
public static final String TAG = "GeoloqiPositioning";
private int batteryLevel = 0;
MyGeoloqiFixSocket fixSocket;
#Override
public void onCreate() {
android.os.Debug.waitForDebugger();
Toast.makeText(MyGeoloqiPositioning.this, "MyGeoloqiPositiong in onCreate()", Toast.LENGTH_LONG).show();
if (isConnected()) {
fixSocket = MyUDPClient.getApplicationClient(this);
} else {
// TODO: This is a crude check. Should probably be rolled into UDPClient class directly.
Log.w(TAG, "Network unavailable! Stopping positioning service.");
stopSelf();
}
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onStart(Intent intent, int startid) {
Toast.makeText(MyGeoloqiPositioning.this, "MyGeoloqiPositiong in onStart()", Toast.LENGTH_LONG).show();
registerReceiver(batteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
for (String provider : ((LocationManager) getSystemService(LOCATION_SERVICE)).getAllProviders()) {
if (!provider.equals("passive")) {
MyADB.log("Registering for updates with " + provider);
((LocationManager) getSystemService(LOCATION_SERVICE)).requestLocationUpdates(provider, 0, 0, this);
}
}
}
public void onStop() {
unregisterReceiver(batteryReceiver);
((LocationManager) getSystemService(LOCATION_SERVICE)).removeUpdates(this);
}
#Override
public void onDestroy() {
unregisterReceiver(batteryReceiver);
((LocationManager) getSystemService(LOCATION_SERVICE)).removeUpdates(this);
}
#Override
public int onStartCommand(Intent intent, int flags, int startid) {
Toast.makeText(MyGeoloqiPositioning.this, "MyGeoloqiPositiong in onStartCommand()", Toast.LENGTH_LONG).show();
onStart(intent, startid);
return Service.START_REDELIVER_INTENT;
}
#Override
public void onLocationChanged(Location location) {
Toast.makeText(MyGeoloqiPositioning.this, "MyGeoloqiPositiong in onLocationChanged()", Toast.LENGTH_LONG).show();
#SuppressWarnings("unchecked")
MyFix lqLocation = new MyFix(location, new Pair<String, String>("battery", "" + batteryLevel));
if (isConnected()) {
fixSocket.pushFix(lqLocation);
} else {
// TODO: This is a crude check. Should probably be rolled into UDPClient class directly.
Log.w(TAG, "Network unavailable, failed to push location fix!");
}
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
BroadcastReceiver batteryReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
batteryLevel = intent.getIntExtra("level", 0);
}
};
/** Determine if the network is connected and available. */
private boolean isConnected() {
ConnectivityManager manager = (ConnectivityManager) getApplicationContext()
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = manager.getActiveNetworkInfo();
return (activeNetwork != null && activeNetwork.isConnected());
}
}
I tried inserting a breakpoint in MyGeoloqiPositioning, but nothing ever comes of it. I also put various Toast() calls, but still no dice. My GeoloqiPositioning.java is never called. What am I doing wrong?
EDIT:
Here is the new code from the manifest file:
<service
android:name="com.manhunttwopointoh.MyGeoloqiPositioning"
android:enabled="true"
android:exported="false"
android:process=":lqRemote" >
<intent-filter>
<action android:name="com.manhunttwopointoh.MyGeoloqiPositioning" />
</intent-filter>
</service>
I tried adding the intent-filter tags, but still nothing. I also have nothing registering on the logs. Here is the code (commented out stopService()):
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_geoloqi);
Intent mPositioningIntent = new Intent(this, MyGeoloqiPositioning.class);
//stopService(mPositioningIntent);
startService(mPositioningIntent);
Toast.makeText(PreyGeoloqi.this, "testing mPositioningIntent: " + mPositioningIntent.toString(), Toast.LENGTH_LONG).show();
}
I still get nothing. Do I need to explicitly call methods in MyPreyGeoloqi.java? I am fairly confused...
Try adding an intent filter your service definition in the AndroidManifest:
<!-- snippet from Android Manifest file -->
<service android:name="com.manhunttwopointoh.MyGeoloqiPositioning" android:enabled="true" android:process=":lqRemote" >
<intent-filter>
<action android:name="com.manhunttwopointoh.MyGeoloqiPositioning" />
</intent-filter>
</service>
This allows your service to receive the intent sent from your Activity.
I have an Activity class, in which I have a static flag, let's say
public static volatile flag = false;
Then in the class, I start a thread, which checks the flag and do different things.
I also have a broadcastreceiver, which sets the flag to true or false.
I though volatile will force the flag to the most recent value. But I can see my broadcastreceiver sets the static flag to true, but my thread is still getting it as false.
Am I missing something basic here? Any help would be appreciated!
Simplified Code (Updated) - So the flag is supposed to change to true after one minute. But it never did. But message from broadcast receiver shows it has been change to true
TestappActivity.java:
package com.test;
import java.util.Calendar;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
public class TestappActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent intent0 = new Intent(this, TestService.class);
this.startService(intent0);
Intent intent = new Intent(this, TestReceiver.class);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
PendingIntent sender = PendingIntent.getBroadcast(this,
1, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
Calendar slot = Calendar.getInstance();
int min = slot.get(Calendar.MINUTE);
slot.set(Calendar.MINUTE, min+1);
am.set(AlarmManager.RTC_WAKEUP, slot.getTimeInMillis(), sender);
}
}
TestService.java:
package com.test;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class TestService extends Service {
private static final String TAG = "TestService";
public static volatile boolean flag = false;
private MyTopThread mTopThread;
public TestService() {
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
}
#Override
public void onDestroy() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
protect();
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
/**
* Run protection
*
*/
private void protect() {
mTopThread = new MyTopThread();
mTopThread.start();
}
private class MyTopThread extends Thread {
#Override
public void run() {
while (true) {
try {
Thread.sleep(150);
Log.d(TAG, "Flag is " + TestService.flag);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
TestReceiver.java:
package com.test;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class TestReceiver extends BroadcastReceiver {
final static private String TAG = "TestReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "onReceive is triggered ...");
TestService.flag = true;
Log.d(TAG, "flag is changed to " + TestService.flag);
}
}
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".TestappActivity"
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=".TestService" />
<receiver
android:name=".TestReceiver"
android:process=":remote" >
</receiver>
</application>
</manifest>
I think the problem is that you are running the receiver in its own process. From the docs for the android:process attribute of <receiver>:
If the name assigned to this attribute begins with a colon (':'), a new process, private to the application, is created when it's needed and the broadcast receiver runs in that process.
I think the receiver is modifying a process-local version of TestService.flag, not the one being used by TestService. Try removing the android:process attribute from the <receiver> tag in your manifest.
From this link
http://www.javamex.com/tutorials/synchronization_volatile.shtml
Essentially, volatile is used to indicate that a variable's value will
be modified by different threads.
I really hope your service thread is not this one (I don't see any other one):
private class MyTopThread extends Thread {
#Override
public void run() {
while (true) {
try {
Thread.sleep(150);
Log.d(TAG, "Flag is " + TestService.flag);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Because you have while(true) here, not while(!flag) as it should be.