Automatic reply to SMS is not working. Android studio - java

I am trying to send automatic reply when receiving sms using BroadcastReceiver to listen to sms and SmsManager to send reply but the auto reply is not working.
Note: If I call smsManager.sendTextMessage(phoneNo, null, msg, null, null); from onCreate, it indeed sends a message but the problem is when I am trying to call it from messageReceived.
I have also tried to use registerReceiver instead bindListener but the same happened.
When running on emulator all Toasts are showing (but I can't really check that a message is sent on emulator).
When running on device connected via USB cable, "sending the message" Toast is not showing.
I will really appreciate your help.
Thank you
public class MainActivity extends AppCompatActivity implements SmsListener, View.OnClickListener{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED){
requestSMSPermission();
}
else{
SmsReceiver.bindListener(this);
Toast.makeText(this, "listening", Toast.LENGTH_SHORT).show();
}
}
#Override
public void messageReceived(String messageText, String sender) {
Toast.makeText(getBaseContext(), "sending the message", Toast.LENGTH_SHORT).show();
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(sender, null, messageText, null, null);
}
private void requestSMSPermission(){
if(ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.SEND_SMS)){
new AlertDialog.Builder(this)
.setTitle("Permission needed").setMessage("This permission is needed in order to send automatic reply")
.setPositiveButton("ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.SEND_SMS},READ_SMS_PERMISSION_CODE);
}
})
.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
}).create().show();
}
else{
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.SEND_SMS},READ_SMS_PERMISSION_CODE);
}
}
}
Receiver class:
public class SmsReceiver extends BroadcastReceiver {
private static SmsListener mListener;
#Override
public void onReceive(Context context, Intent intent) {
Bundle data = intent.getExtras();
Object[] pdus = (Object[]) data.get("pdus");
String sender = null;
for(int i=0; i<pdus.length; i++){
SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdus[i]);
sender = smsMessage.getOriginatingAddress();
String messageBody = smsMessage.getMessageBody();
mListener.messageReceived(messageBody,sender);
}
}
public static void bindListener(SmsListener listener) {
mListener = listener;
}
}
Listener interface:
public interface SmsListener {
public void messageReceived(String messageText, String sender);
}
Manifest:
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<receiver android:name=".SmsReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>

Ok, I figured out the problem;
This issue happens on api > 26 (maybe even 25).
On api 24 this code above worked just fine and an automatic reply was sent.
The problem is that I requested permission for SEND_SMS (in Manifest I have READ,RECEIVE,SEND) and apparently on api 26 it doesn't really give permission for RECEIVE_SMS so In my code onReceive was never called.
Solution: I have changed the permission above to RECEIVE_SMS and added to onCreate this:
if(ActivityCompat.checkSelfPermission(this,Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.SEND_SMS},111);
}
To conclude: If you want two (or more) permissions from the same family (e.g READ_SMS/SEND_SMS), you need to request for all needed permissions even thought eventually you will see a dialog only once allowing all permissions together.
In API <= 24 it is enough to request only for one permission from the same family (e.g READ_SMS) and you receive the rest

Related

AIDL Client does not bind to remote service

I am trying to run a simple multiplication with a remote service. I have AIDL server file declaring and defining methods. In AIDL, i have copied the same AIDL file as server under the server's package name.
I have given the action for the intent filter of server's service.
Still my AIDL client code is not connecting to the service.
AIDLServer:
Manifest
<service
android:name=".CalService"
android:enabled="true"
android:exported="true"
android:process=":remote">
<intent-filter>
<action android:name="mutliply"/>
</intent-filter>
</service>
ICalService.aidl
interface ICalService {
String getMessage(String name);
int getResult(int val1, int val2);
}
CalService.java
public class CalService extends Service {
public CalService() {
}
private final ICalService.Stub binder = new ICalService.Stub() {
#Override
public String getMessage(String name) throws RemoteException {
return "Hello " + name + ". The result is: ";
}
#Override
public int getResult(int val1, int val2) throws RemoteException {
return val1 * val2;
}
};
#Nullable
#Override
public IBinder onBind(Intent intent) {
return binder;
}
}
AIDLCLient:
MainActivity.java
#Override
protected void onStart() {
super.onStart();
editName = (EditText) findViewById(R.id.editName);
editVal1 = (EditText) findViewById(R.id.editVal1);
editVal2 = (EditText) findViewById(R.id.editVal2);
resultView = (TextView) findViewById(R.id.resultView);
if(calService == null) {
Log.v("CALSERVICE", "cal service null");
Intent it = new Intent("multiply");
it.setPackage("com.example.aidlserver");
if(getBaseContext().getApplicationContext().bindService(
it, connection, Context.BIND_AUTO_CREATE
) == true){
Log.v("Bind", "Bind service Succeeded");
} else {
Log.v("Bind", "Bind service failed");
}
} else {
Log.v("Cal", "Cal Service not null");
}
}
#Override
protected void onDestroy() {
super.onDestroy();
unbindService(connection);
}
public void mutiply(View v) {
switch (v.getId()) {
case R.id.btnCal:
int num1 = Integer.parseInt(editVal1.getText().toString());
int num2 = Integer.parseInt(editVal2.getText().toString());
try {
int result = calService.getResult(num1, num2);
String msg = calService.getMessage(editName.getText().toString());
resultView.setText(msg + result);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
}
}
private ServiceConnection connection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("onServiceConnected", "Connected");
calService = ICalService.Stub.asInterface(service);
Toast.makeText(getApplicationContext(), "Service Connected",
Toast.LENGTH_SHORT).show();
}
#Override
public void onServiceDisconnected(ComponentName name) {
Log.d("onServiceDisconnected", "Disconnected");
calService = null;
Toast.makeText(getApplicationContext(), "Service Disconnected",
Toast.LENGTH_SHORT).show();
}
};
The code shows its an implicit intent used while bindService call.
Intent it = new Intent("multiply");
it.setPackage("com.example.aidlserver");
If you are above API level 21, you must update your code with an explicit intent. Please update your code with setClassName() API to make the bind service call with an explicit intent.
Intent it = new Intent("multiply");
it.setClassName("com.example.aidlserver","com.example.aidlserver.CalService");
if(getBaseContext().getApplicationContext().bindService(it, connection, Context.BIND_AUTO_CREATE) == true){
Log.v("Bind", "Bind service Succeeded");
} else {
Log.v("Bind", "Bind service failed");
}
Please note the following:
Caution: To ensure that your app is secure, always use an explicit
intent when starting a Service and don't declare intent filters for
your services. Using an implicit intent to start a service is a
security hazard because you cannot be certain of the service that
responds to the intent, and the user cannot see which service starts.
Beginning with Android 5.0 (API level 21), the system throws an
exception if you call bindService() with an implicit intent.
Ref: https://developer.android.com/guide/components/services
Also check this too,
"To receive implicit intents, you must include the CATEGORY_DEFAULT category in the intent filter"
<category android:name="android.intent.category.DEFAULT"/>
https://developer.android.com/guide/components/intents-filters#Receiving
All you need is to add in client app Manifest, where you want tu bind 3rd party app Service. With the same package name you set in the Intent:
val intent = Intent("example_action")
intent.`package` = "your package name"
bindService(intent, connection, Context.BIND_AUTO_CREATE)
Manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.github.asvid.services.client">
<queries>
<package android:name="io.github.asvid.services.server" />
</queries>
...
</manifest>
Alternatively you can stay with compileSdk 29 but I don’t recommend that :)

onActivityResult Not Being Called For UnityPlayerActivity

I don't have a lot of experience creating Java (.aar) plugins for Unity3d, but I am attempting to setup google authentication with firebase from such a plugin. To give an example of my problem, I begin by opening a unity android application, then I run the c# code below, and get a popup on my display to sign-in with google. I then choose the correct google account, then the google intent/activity disappears, then I receive no indication that "onActivityResult" has been called. No errors occur and I am unable to to do anything with the google account information that I chose.
In the image below, I click submit -> it opens the google sign-in activity in the next picture -> then it returns back to the submit screen (closing the google sign-in activity).
I think my issue is in this line:
activity.startActivityForResult(signInIntent, RC_SIGN_IN);
The "activity" in this case is a UnityPlayerActivity sent from the c# unity code below. I think this is making it so my code is looking for an "onActivityResult" method in the C# unity code rather than the java code. Any help would be greatly appreciated. Let me know if you need any other info or screenshots. Please call me out if I am being a moron.
Here is my code for calling the Google Signin Plugin From C# & Unity3d:
AndroidJNIHelper.debug = true;
using (AndroidJavaClass activityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) {
activity_context = activityClass.GetStatic<AndroidJavaObject>("currentActivity");
}
using (AndroidJavaClass pluginClass = new AndroidJavaClass("com.package.class")) {
if (pluginClass != null) {
GoogleSignInActivity = pluginClass.CallStatic<AndroidJavaObject>("instance");
GoogleSignInActivity.Call("SetContext", activity_context);
GoogleSignInActivity.Call("StartGoogleLogin", activity_context);
activity_context.Call("runOnUiThread", new AndroidJavaRunnable(() => {
GoogleSignInActivity.Call("ShowMessage", "You signed in as " + display_name);
}));
}
}
Here is the code for creating the Google SignIn Activity:
public void StartGoogleLogin(UnityPlayerActivity activity) {
gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken("some url")
.requestEmail()
.build();
mGoogleSignInClient = GoogleSignIn.getClient(activity, gso);
Intent signInIntent = mGoogleSignInClient.getSignInIntent();
activity.startActivityForResult(signInIntent, RC_SIGN_IN);
Log.d(TAG, "Activity Started; Waiting For Result");
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d(TAG, "Result Received!");
if (requestCode == RC_SIGN_IN) {
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
try {
// Google Sign In was successful
GoogleSignInAccount account = task.getResult(ApiException.class);
someMethod(account);
} catch (ApiException e) {
// Google Sign In failed, update UI appropriately
Log.d(TAG, "Google sign in failed", e);
}
setResult(RESULT_OK);
}
}
Thank you for your time.
Well, I solved my own problem of getting Google Authentication to work between the Android .aar plugin and Unity c#. Been working tirelessly and found some kickbutt resources.
First and foremost, I referenced the code written by a guy named cwgtech HERE.
I also went through all of his videos.
Instead of using UnitySendMessage, I was able to use a callback method similar to what CWGTech does to send a googleIdToken back to Unity and sign-in with Google into Firebase. I was also correct in thinking that my mistake was with the statement below:
activity.startActivityForResult(signInIntent, RC_SIGN_IN);
Instead of doing this, I followed CWGTech's advice and removed "activity." portion. I ran the startActivityForResult in a ResultCallback class that extends Activity. If you are still confused, dm me or comment on this post. Thanks!
Here is some of the code I used to send a callback string to Unity via a Java Proxy in written in C#. Information about writing a Java proxy can be found in the cwgtech information above. Writing the java proxy is extremely important if you want to get information to flow from Android activities to Unity C#. CWGTech explains the intricacies of java proxies way better than I could do justice.
public static final String LOGTAG = GoogleSignInActivity.TAG + "_OnResult";
public static GoogleSignInActivity.ShareStringCallback shareStringCallback;
private static final int RC_SIGN_IN = 9001;
private GoogleSignInClient mGoogleSignInClient;
private GoogleSignInOptions gso;
private CallbackManager mCallbackManager;
public void myFinish(String myresult) {
if (shareStringCallback != null) {
shareStringCallback.onLoginComplete(myresult);
}
shareStringCallback = null;
finish();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(LOGTAG, "onCreateBundle");
Intent intent = getIntent();
setContentView(R.layout.login_activity);
findViewById(R.id.buttonFacebookLogin).setOnClickListener(this);
findViewById(R.id.signInButton).setOnClickListener(this);
findViewById(R.id.buttonAnonymousSignIn).setOnClickListener(this);
}
/* GOOGLE SIGN-IN CODE */
public Intent StartGoogleLogin() {
/*
Google Sign In Client Init Code Goes Here
*/
Intent signInIntent = mGoogleSignInClient.getSignInIntent();
return signInIntent;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//Detects some type of result from an activity, in this case Google
String id_result = "Send This To Unity";
myFinish(id_result);
}
Here is a bit more code from a different java class file. The 'Login' method is called from Unity c#.
/* INTERFACES FOR CALLBACK FUNCTIONAILITY */
public interface ShareStringCallback {
public void onLoginComplete(String result);
}
public void Login(final ShareStringCallback callback)
{
mainActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
try {
Log.i(TAG,"Starting Authentication");
try {
try {
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setClass(mainActivity,OnResultCallback.class);
OnResultCallback.shareStringCallback = callback;
mainActivity.startActivity(shareIntent);
}
catch (Exception e)
{
e.printStackTrace();
Log.i(TAG,"error sharing intent: " + e);
}
}
catch (Exception e)
{
e.printStackTrace();
Log.i(TAG,"Error getting Uri: " + e);
}
}
catch (Exception e)
{
e.printStackTrace();
Log.i(TAG,"Error writing file: " + e);
}
}
});
}
When you start a activity from UnityPlayerActivity, the onActivityResult will be called when finished, but will have its default return value. What you can do is create a new Activity in Android, and extends UnityPlayerActivity.
In Android, create a new Activity
import com.unity3d.player.UnityPlayer;
public class OverrideUnityPlayerActivity extends UnityPlayerActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public Activity getCurrentActivity(){
return mUnityPlayer.currentActivity;
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 0) {
switch (resultCode) {
case Activity.RESULT_OK:
//do something
break;
case Activity.RESULT_CANCELED:
//do something
break;
}
}
}
}
You need to set this override activity as launch endpoint in AndroidManifest.XML
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.unity3d.player"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="false"
tools:replace="android:allowBackup">
<activity
android:name="com.example.unitylibrary.manager.OverrideUnityPlayerActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="app_name" android:value="app_value"/>
</activity>
</application>
</manifest>
3.Then in Unity, you can get this activity and context, also get the onActivityResult
AndroidJavaObject overridePlayerActivity;
AndroidJavaObject overrideActivity;
public void init(){
overridePlayerActivity = new AndroidJavaObject("com.example.unitylibrary.manager.OverrideUnityPlayerActivity");
overrideActivity= overridePlayerActivity.Call<AndroidJavaObject>("getCurrentActivity");
}
public void startAct(){
anonymousFunction.Call("StartActForRes", overrideActivity);
}
Hope this will solve your problem.

Identify sms number ID in Oreo

My actual code blocks calls perfectly but now I want to identify an incoming SMS number ID and do stuff, like mark as read or whatever ( like Medium and this one ).
I've read a couple articles and threads but it's not even getting the intent, note again that this code works perfectly blocking calls so I'll paste the SMS related information
Manifest.xml
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<service android:name=".CallReceiverService" />
Service with Broadcast receiver
#Override
public void onCreate() {
super.onCreate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);
Notification notification = new Notification.Builder(this, SERVICE_CHANNEL_ID)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentText(this.getResources().getString(R.string.stg_ServiceRunning))
.setContentIntent(pendingIntent)
.setCategory(Notification.CATEGORY_CALL)
.build();
startForeground(44332255, notification);
}
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.intent.action.PHONE_STATE"); // related to call feature, ignore
intentFilter.addAction("android.provider.Telephony.SMS_RECEIVED");
intentFilter.addAction("Telephony.Sms.Intents.SMS_RECEIVED_ACTION");
intentFilter.setPriority(1000);
registerReceiver(callCheckReceiver, intentFilter);
}
private BroadcastReceiver callCheckReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
try {
if (intent.getAction().equals(Telephony.Sms.Intents.SMS_RECEIVED_ACTION)) {
Log.d("Call", "SMS received");
String smsSender = "";
if (intent.getAction().equals(Telephony.Sms.Intents.SMS_RECEIVED_ACTION)) {
Log.d("Call", "SMS received");
String smsSender = "";
for (SmsMessage smsMessage : Telephony.Sms.Intents.getMessagesFromIntent(intent)) {
smsSender = smsMessage.getDisplayOriginatingAddress();
}
if (!isValidPhoneNumber(smsSender)) {
Log.d("Call", "Invalid SMS detected: From " + smsSender);
}
}
if (!isValidPhoneNumber(smsSender)) {
Log.d("Call", "Invalid SMS detected: From " + smsSender);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
public static boolean isValidPhoneNumber(String phoneNumber) {
return android.util.Patterns.PHONE.matcher(phoneNumber).matches();
}
Basically I'm asking the permission in MainActivity, setting them in Manifest and passing the FilterIntent in the Service that IS properly called in Oreo or lower versions of Android. Target API >=19
I don't want to build an app to manage SMS, I just want to intercept the number ID and do things. Can someone advise?
What you need is SMS Retriever API
If you want to detect the SMS, you can simply use
SmsRetrieverClient client = SmsRetriever.getClient(this /* context */);
Task<Void> task = client.startSmsRetriever();
task.addOnSuccessListener(new OnSuccessListener<Void>()
{
#Override
public void onSuccess(Void aVoid)
{
// Successfully started retriever, expect broadcast intent
// ...
}
});
task.addOnFailureListener(new OnFailureListener()
{
#Override
public void onFailure(#NonNull Exception e)
{
// Failed to start retriever, inspect Exception for more details
// ...
}
});
In AndroidManifest.xml simply add receiver
<receiver
android:name=".custom.SMSBroadcastReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED" />
</intent-filter>
</receiver>
Within receiver you can do whatever you want with detected message
public class SMSBroadcastReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
if (SmsRetriever.SMS_RETRIEVED_ACTION.equals(intent.getAction()))
{
Bundle extras = intent.getExtras();
Status status = (Status) extras.get(SmsRetriever.EXTRA_STATUS);
switch (status.getStatusCode())
{
case CommonStatusCodes.SUCCESS:
// Get SMS message contents
String message = (String) extras.get(SmsRetriever.EXTRA_SMS_MESSAGE);
// Extract one-time code from the message and complete verification
// by sending the code back to your server for SMS authenticity.
break;
case CommonStatusCodes.TIMEOUT:
// Waiting for SMS timed out (5 minutes)
// Handle the error ...
break;
}
}
}
}
It should be noted that SMSRetrieverClient default timeout is 5 minutes.
For creating detectable SMS please follow SMS Creator for Google

Android Java callback null inside broadcastReceiver

I'm trying to get notification when Android receives a text message, so I wrote a new class for that like this:
public class MyBroadcastReceiver extends BroadcastReceiver {
public MyBroadcastCallback callback;
public MyBroadcastReceiver() {}
public MyBroadcastReceiver(MyBroadcastCallback callback) {
this.callback=callback;
Log.d("myTag", "MyBroadcastReceiver CONSTRUCTOR.... "+this.callback);
this.callback.OnReceiveSMS("phone TEST","message TEST");
}
#Override
public void onReceive(Context context, Intent intent) {
Bundle intentExtras = intent.getExtras();
if (intentExtras != null) {
Object[] sms = (Object[]) intentExtras.get("pdus");
for (int i = 0; i < sms.length; ++i) {
SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) sms[i]);
String phone = smsMessage.getOriginatingAddress();
String message = smsMessage.getMessageBody().toString();
this.callback.OnReceiveSMS(phone,message);
}
}
}
public interface MyBroadcastCallback {
void OnReceiveSMS(String phone,String message);
}
}
Then in my main activity I instantiate the class like this:
public class MainActivity extends AppCompatActivity implements MyBroadcastReceiver.MyBroadcastCallback {
MyBroadcastReceiver broadcastReceiver=null;
#Override
protected void onCreate(Bundle savedInstanceState) {
....
super.onCreate(savedInstanceState);
broadcastReceiver=new MyBroadcastReceiver(this);
....
}
#Override
public void OnReceiveSMS(String phone, String message) {
Log.d("myTag", "NEW SMS MESSAGE PHONE="+phone + " message="+message);
}
}
The Android manifest looks like this:
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
When a text is received, OnReceive is called in the MyBroadCastReceiver class, that works great.
But when I try to call my own callback function inside OnReceive() to notify the main activity of the text message like this:
this.callback.OnReceiveSMS(phone, message);
It crashes with exception that this.callback is null.
I know it's not null in the beginning because in the constructor I pass in the main activity which implements that interface.
To debug I also printed out this.callback in the constructor and even called that function in there to make sure its not null, and all that works, but somehow it BECOMES null when a text comes in and Android OS calls OnReceive.
Does anybody knows why it's null? How to fix?

how to stop displaying apps in active application window in android

I made an app as a service which runs in background. This app is basically a battery alarm. It works fine but the only problem is that when this service is running it also displays this app in the active application task manager. So when I exit this app it stops that service as well. So what I want is to only stop this service when the user unchecks the box in the app settings. If it is checked then it should not be stopped even if it is closed in active application task manager.
How can I stop showing my app in task manager?
I think I should provide code over here This is my service class
public class BatteryService extends Service {
Notify notification = new Notify();
BatteryAlarm alarm = new BatteryAlarm();
private MediaPlayer mMediaPlayer;
boolean flag = false;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
//method to start service
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
notification.initNotification(this, false);
this.registerReceiver(this.mBatInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
return START_STICKY;
}
//Broadcast receiver to get battery info
private BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context c, Intent i) {
//notification.initNotification(c);
int level = i.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
int plugged = i.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
SharedPreferences getAlarm = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
String alarms = getAlarm.getString("ringtones", "content://media/internal/audio/media/45"); // /system/media/audio/ringtones/ANDROMEDA.ogg , content://media/internal/audio/media/45
Uri uri = Uri.parse(alarms);
if(plugged == 2) {
if(level == 100) {
if(uri != null) {
if(flag == false) {
playAlarm(c, uri);
notification.initNotification(c, true);
Toast.makeText(c, "Battery charge is completed. Unplug your mobile phone!", Toast.LENGTH_LONG).show();
flag = true;
}
}
}
} else if (plugged == 0) {
if(uri != null) {
stopAlarm();
}
notification.cancelNotification(c);
//Toast.makeText(c, "Mobile is unplugged", Toast.LENGTH_LONG).show();
}
}
};
//play alarm method
private void playAlarm(Context c, Uri uri) {
mMediaPlayer = new MediaPlayer();
try {
mMediaPlayer.reset();
mMediaPlayer.setDataSource(getBaseContext(), uri);
final AudioManager audioManager = (AudioManager) c.getSystemService(Context.AUDIO_SERVICE);
if (audioManager.getStreamVolume(AudioManager.STREAM_ALARM) != 0) {
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
mMediaPlayer.prepare();
mMediaPlayer.start();
}
} catch (Exception ex) {
ex.printStackTrace();
onDestroy();
}
}
//method to stop playing alarm
private void stopAlarm() {
mMediaPlayer.stop();
flag = false;
}
//method to stop service
public void onDestroy() {
super.onDestroy();
notification.cancelNotification(this);
unregisterReceiver(this.mBatInfoReceiver);
stopAlarm();
Toast.makeText(this, "Service Stopped", Toast.LENGTH_LONG).show();
}
}
This is my main activity
public class BatteryNotify extends PreferenceActivity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.xml.prefs);
addPreferencesFromResource(R.xml.prefs);
SharedPreferences getCB = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
boolean cb = getCB.getBoolean("checkbox", true);
final CheckBoxPreference checkboxPref = (CheckBoxPreference) getPreferenceManager().findPreference("checkbox");
if(cb == true) {
startService(new Intent(getBaseContext(), BatteryService.class));
} else if(cb == false) {
stopService(new Intent(getBaseContext(), BatteryService.class));
}
checkboxPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
if(newValue.toString().equals("true")) {
startService(new Intent(getBaseContext(), BatteryService.class));
} else {
stopService(new Intent(getBaseContext(), BatteryService.class));
}
return true;
}
});
}
}
and here is my menifest file
<uses-sdk android:minSdkVersion="10" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".BatteryNotify"
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=".BatteryService"></service>
</application>
The best way to do this would be to create a BroadcastReceiver, register it in the manifest with the appropriate intent-filters and when it receives one it starts the Service or Activity to perform whatever task you need.
EDIT:
Create your BroadcastReceiver as a separate class and register it in the manifest. When it receives a battery event, create a PendingIntent to start the Service. That way it doesn't matter if your app isn't running. It will be started for you.
How can I stop showing my app in task manager?
You can't, for obvious security reasons.

Categories

Resources