Android make vibrate from background [duplicate] - java

This question already has answers here:
Android keep BroadcastReceiver in background
(2 answers)
Closed 2 years ago.
I use the code below to make the phone vibrate when I receive a SMS with a specific text. But the phone vibrate only if the app is running.
How can I make the phone vibrate even when the app is closed ?
Manifest Permission
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.VIBRATE" />
SMSReceiver.java
public class SMSReceiver extends BroadcastReceiver {
private static final String TAG = "SmdReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Bundle myBundle = intent.getExtras();
if (myBundle != null) {
Object[] pdus = (Object[]) myBundle.get("pdus");
for (int i = 0; i < pdus.length; i++) {
SmsMessage message = SmsMessage.createFromPdu((byte[]) pdus[i]);
String body = message.getMessageBody();
if (body == "test") {
Log.d(TAG, "vibrate"); // is print in the console
Vibrator v = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
v.vibrate(VibrationEffect.createOneShot(duration, VibrationEffect.DEFAULT_AMPLITUDE));
} else {
v.vibrate(duration); //deprecated in API 26
}
}
}
}
}
}

Android tend to kill background apps, especially customization like MIUI. To avoid this you need, for example, to attach the worker process to a permanent notification. So that the system won't kill the app.
There are other ways to keep the app running like services and background processing.
For more details follow Background Execution Limits.
And this is another question for something similar.

Related

Display a window (dialog) above a system app

I am developing an App Locker for android. Everything works except for when you try to delete an app, the popup does not appear. I tried to force the lock-screen dialog to appear manually from within the app, but the results were crashes and ANRs.
I thought to myself that the popup is not available because the packageInstaller (System app) is using the screen at the same time, and it gets more priority.
Another thing is that when I cancel an uninstall, packageInstaller goes away and then my display appears for a fraction of a second and then disappears. Note that this is after, I need it to be present before, or even while the packageInstaller is running.
My question is if it is possible to put my window at a certain priority, so that goes even above the system app?
In my app check service, in my method that's on repeat constantly I had:
`
if (mpackageName.equals("com.google.android.packageinstaller")) {
showUnlockDialog();
}
however, this caused my lock-display to get opened a lot of times (because of the repeat), which caused the app to become irresponsive. What I now have (after omitting) is the dialog appearing after, at the end then going away on its own.
This is my show dialog method:
`
{
if (context == null) {
context = getApplicationContext();
}
LayoutInflater layoutInflater = LayoutInflater.from(context);
#SuppressLint("InflateParams") View promptsView;
promptsView = layoutInflater.inflate(R.layout.popup_unlock, null, false);
Lock9View lock9View = (Lock9View) promptsView.findViewById(R.id.lock_9_view);
Button forgetPassword = (Button) promptsView.findViewById(R.id.forgetPassword);
LinearLayout linearLayout = promptsView.findViewById(R.id.popup_background);
TextView textView = promptsView.findViewById(R.id.textView);
linearLayout.setBackgroundResource(R.drawable.gradient_list);
textView.setTextColor(getResources().getColor(R.color.colorWhite));
forgetPassword.setTextColor(getResources().getColor(R.color.colorWhite));
animateBanner1(linearLayout);
lock9View = (Lock9View) promptsView.findViewById(R.id.lock_10_view);
lock9View.setVisibility(View.VISIBLE);
lock9View.setCallBack(new Lock9View.CallBack() {
#Override
public void onFinish(String password) {
if (password.matches(sharedPreference.getPassword(context))) {
dialog.dismiss();
} else {
Toast.makeText(context, "Wrong pattern, try again", Toast.LENGTH_SHORT).show();
}
}
});
forgetPassword.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(AppCheckServices.this, PasswordRecoveryActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
dialog.dismiss();
}
});
dialog = new Dialog(context, android.R.style.Theme_Black_NoTitleBar_Fullscreen);
dialog.setCanceledOnTouchOutside(false);
dialog.setCancelable(false);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Objects.requireNonNull(dialog.getWindow()).setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
}
else {
Objects.requireNonNull(dialog.getWindow()).setType(WindowManager.LayoutParams.TYPE_PHONE);
}
dialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
dialog.setContentView(promptsView);
dialog.getWindow().setGravity(Gravity.CENTER);
dialog.setOnKeyListener(new Dialog.OnKeyListener() {
#Override
public boolean onKey(DialogInterface dialog, int keyCode,
KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK
&& event.getAction() == KeyEvent.ACTION_UP) {
Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
}
return true;
}
});
}
dialog.show();
}
As I said this works on every other app besides the packageInstaller even if I specifically lock it.
Here are my relevant Manifest Permissions:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission
android:name="android.permission.INTERNAL_SYSTEM_WINDOW"
tools:ignore="ProtectedPermissions" />
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
From What I understand, the highest "setType()" for the window manager is the:
SYSTEM_ALERT_WINDOW
It allows to have the top most display. I thought that by using this, I could block the packageInstaller.
However this too requires special permission (2003 from the crashes), and does not get granted easily.
I would appreciate any help in regard to this matter and can post anything else that is relevant.
Thanks in advance!
`

Android Studio Java. Display a pop-up window in the background

How do I display a popup when an app is in the background?
For example, I took the GetContact application, when a call is received from the user, a window with information about the call pops up on the screen.
How can this be done?
It is desirable with code examples, I will be very grateful.
Thank.enter image description here
Add required permissions in your app manifest file:
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Incoming call reciever
public class IncomingCallReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
try {
System.out.println("Receiver start");
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
Toast.makeText(context, "Incoming Call State", Toast.LENGTH_SHORT).show();
Toast.makeText(context, "Ringing State Number is -" + incomingNumber, Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
Ask Runtime permission in your MainActivity.
Add overlay view to display notification in screen.
WindowManager wm =(WindowManager)getSystemService(Context.WINDOW_SERVICE);
View view = LayoutInflater.from(context).inflate(R.layout.test, null)
wm.addView(view, mParams)
What you're looking for is Drawing over other apps. It's a tricky feature of android that I personally love. You have to deal with WindowManager and you need SYSTEM_ALERT_WINDOW permission
Implementations are huge and I guess it's better to give you some links.
Here's a good explanation about floating widgets
https://medium.com/#kevalpatel2106/create-chat-heads-like-facebook-messenger-32f7f1a62064
This is kinda close to what you want: https://github.com/codebyshubham/Calling_Person_History
Also remember that custom roms like Xiaomi have some restrictions on these widgets.
Also a great open source floating app is called QuickLyric take a look at it it might help you a lot

android: Making multiple phone calls from android app [duplicate]

I am launching an activity to make a phone call, but when I pressed the 'end call' button, it does not go back to my activity. Can you please tell me how can I launch a call activity which comes back to me when 'End call' button is pressed? This is how I'm making the phone call:
String url = "tel:3334444";
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(url));
use a PhoneStateListener to see when the call is ended. you will most likely need to trigger the listener actions to wait for a the call to start (wait until changed from PHONE_STATE_OFFHOOK to PHONE_STATE_IDLE again) and then write some code to bring your app back up on the IDLE state.
you may need to run the listener in a service to ensure it stays up and your app is restarted. some example code:
EndCallListener callListener = new EndCallListener();
TelephonyManager mTM = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
mTM.listen(callListener, PhoneStateListener.LISTEN_CALL_STATE);
Listener definition:
private class EndCallListener extends PhoneStateListener {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
if(TelephonyManager.CALL_STATE_RINGING == state) {
Log.i(LOG_TAG, "RINGING, number: " + incomingNumber);
}
if(TelephonyManager.CALL_STATE_OFFHOOK == state) {
//wait for phone to go offhook (probably set a boolean flag) so you know your app initiated the call.
Log.i(LOG_TAG, "OFFHOOK");
}
if(TelephonyManager.CALL_STATE_IDLE == state) {
//when this state occurs, and your flag is set, restart your app
Log.i(LOG_TAG, "IDLE");
}
}
}
In your Manifest.xml file add the following permission:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
This is regarding the question asked by Starter.
The problem with your code is that you are not passing the number properly.
The code should be:
private OnClickListener next = new OnClickListener() {
public void onClick(View v) {
EditText num=(EditText)findViewById(R.id.EditText01);
String number = "tel:" + num.getText().toString().trim();
Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse(number));
startActivity(callIntent);
}
};
Do not forget to add the permission in manifest file.
<uses-permission android:name="android.permission.CALL_PHONE"></uses-permission>
or
<uses-permission android:name="android.permission.CALL_PRIVILEGED"></uses-permission>
for emergency number in case DIAL is used.
We had the same problem and managed to solve it by using a PhoneStateListener to identify when the call ends, but additionally we had to finish() the original activity before starting it again with startActivity, otherwise the call log would be in front of it.
I found the EndCallListener the most functional example, to get the behaviour described (finish(), call, restart) I added a few SharedPreferences so the Listener had a reference to manage this behaviour.
My OnClick, initialise and EndCallListener only respond to calls from app. Other calls ignored.
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
public class EndCallListener extends PhoneStateListener {
private String TAG ="EndCallListener";
private int LAUNCHED = -1;
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(
myActivity.mApp.getBaseContext());
SharedPreferences.Editor _ed = prefs.edit();
#Override
public void onCallStateChanged(int state, String incomingNumber) {
String _prefKey = myActivity.mApp
.getResources().getString(R.string.last_phone_call_state_key),
_bPartyNumber = myActivity.mApp
.getResources().getString(R.string.last_phone_call_bparty_key);
int mLastCallState = prefs.getInt(_prefKey, LAUNCHED);
//Save current call sate for next call
_ed.putInt(_prefKey,state);
_ed.commit();
if(TelephonyManager.CALL_STATE_RINGING == state) {
Log.i(TAG, " >> RINGING, number: " + incomingNumber);
}
if(TelephonyManager.CALL_STATE_IDLE == state && mLastCallState != LAUNCHED ) {
//when this state occurs, and your flag is set, restart your app
if (incomingNumber.equals(_bPartyNumber) == true) {
//Call relates to last app initiated call
Intent _startMyActivity =
myActivity.mApp
.getPackageManager()
.getLaunchIntentForPackage(
myActivity.mApp.getResources()
.getString(R.string.figjam_package_path));
_startMyActivity.setAction(
myActivity.mApp.getResources()
.getString(R.string.main_show_phone_call_list));
myActivity.mApp
.startActivity(_startMyActivity);
Log.i(TAG, "IDLE >> Starting MyActivity with intent");
}
else
Log.i(TAG, "IDLE after calling "+incomingNumber);
}
}
}
add these to strings.xml
<string name="main_show_phone_call_list">android.intent.action.SHOW_PHONE_CALL_LIST</string>
<string name="last_phone_call_state_key">activityLpcsKey</string>
<string name="last_phone_call_bparty_key">activityLpbpKey</string>
and something like this in your Manifest if you need to return to the look and feel before the call
<activity android:label="#string/app_name" android:name="com.myPackage.myActivity"
android:windowSoftInputMode="stateHidden"
android:configChanges="keyboardHidden" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.SHOW_PHONE_CALL_LIST" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
and put these in your 'myActivity'
public static Activity mApp=null; //Before onCreate()
...
onCreate( ... ) {
...
if (mApp == null) mApp = this; //Links your resources to other classes
...
//Test if we've been called to show phone call list
Intent _outcome = getIntent();
String _phoneCallAction = mApp.getResources().getString(R.string.main_show_phone_call_list);
String _reqAction = _outcome.getAction();//Can be null when no intent involved
//Decide if we return to the Phone Call List view
if (_reqAction != null &&_reqAction.equals(_phoneCallAction) == true) {
//DO something to return to look and feel
}
...
myListView.setOnItemClickListener(new OnItemClickListener() { //Act on item when selected
#Override
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
myListView.moveToPosition(position);
String _bPartyNumber = "tel:"+myListView.getString(myListView.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
//Provide an initial state for the listener to access.
initialiseCallStatePreferences(_bPartyNumber);
//Setup the listener so we can restart myActivity
EndCallListener _callListener = new EndCallListener();
TelephonyManager _TM = (TelephonyManager)mApp.getSystemService(Context.TELEPHONY_SERVICE);
_TM.listen(_callListener, PhoneStateListener.LISTEN_CALL_STATE);
Intent _makeCall = new Intent(Intent.ACTION_CALL, Uri.parse(_bPartyNumber));
_makeCall.setComponent(new ComponentName("com.android.phone","com.android.phone.OutgoingCallBroadcaster"));
startActivity(_makeCall);
finish();
//Wait for call to enter the IDLE state and then we will be recalled by _callListener
}
});
}//end of onCreate()
use this to initilaise the behaviour for your onClick in myActivity e.g. after onCreate()
private void initialiseCallStatePreferences(String _BParty) {
final int LAUNCHED = -1;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(
mApp.getBaseContext());
SharedPreferences.Editor _ed = prefs.edit();
String _prefKey = mApp.getString(R.string.last_phone_call_state_key),
_bPartyKey = mApp.getString(R.string.last_phone_call_bparty_key);
//Save default call state before next call
_ed.putInt(_prefKey,LAUNCHED);
_ed.putString(_bPartyKey,_BParty);
_ed.commit();
}
You should find that clicking your list of phone numbers finishes your activty, makes the call to the number and returns to your activty when the call ends.
Making a call from outside your app while it's still around won't restart your activty (unless it's the same as the last BParty number called).
:)
you can use startActivityForResult()
This is solution from my point of view:
ok.setOnClickListener(this);
#Override
public void onClick(View view) {
if(view == ok){
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:" + num));
activity.startActivity(intent);
}
Of course in Activity (class) definition you have to implement View.OnClickListener .
Here is my example, first the user gets to write in the number he/she wants to dial and then presses a call button and gets directed to the phone. After call cancelation the user gets sent back to the application. In order to this the button needs to have a onClick method ('makePhoneCall' in this example) in the xml. You also need to register the permission in the manifest.
Manifest
<uses-permission android:name="android.permission.CALL_PHONE"></uses-permission>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Activity
import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class PhoneCall extends Activity {
EditText phoneTo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_phone_call);
phoneTo = (EditText) findViewById(R.id.phoneNumber);
}
public void makePhoneCall(View view) {
try {
String number = phoneTo.getText().toString();
Intent phoneIntent = new Intent(Intent.ACTION_CALL);
phoneIntent.setData(Uri.parse("tel:"+ number));
startActivity(phoneIntent);
} catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(PhoneCall.this,
"Call failed, please try again later!", Toast.LENGTH_SHORT).show();
}
}
}
XML
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="phone"
android:ems="10"
android:id="#+id/phoneNumber"
android:layout_marginTop="67dp"
android:layout_below="#+id/textView"
android:layout_centerHorizontal="true" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Call"
android:id="#+id/makePhoneCall"
android:onClick="makePhoneCall"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true" />
#Override
public void onClick(View view) {
Intent phoneIntent = new Intent(Intent.ACTION_CALL);
phoneIntent.setData(Uri.parse("tel:91-000-000-0000"));
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
return;
}
startActivity(phoneIntent);
}
If you are going to use a listener you will need to add this permission to the manifest as well.
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Inside PhoneStateListener after seeing the call is finished better use:
Intent intent = new Intent(CallDispatcherActivity.this, CallDispatcherActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
Where CallDispatcherActivity is the activity where the user has launched a call (to a taxi service dispatcher, in my case). This just removes Android telephony app from the top, the user gets back instead of ugly code I saw here.
To return to your Activity, you will need to listen to TelephonyStates. On that listener you can send an Intent to re-open your Activity once the phone is idle.
At least thats how I will do it.
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:"+number));
startActivity(callIntent);
**Add permission :**
<uses-permission android:name="android.permission.CALL_PHONE" />
Try using:
finish();
at the end of activity. It will redirect you to your previous activity.
When PhoneStateListener is used, one need to make sure PHONE_STATE_IDLE following a PHONE_STATE_OFFHOOK is used to trigger the action to be done after the call. If the trigger happens upon seeing PHONE_STATE_IDLE, you will end up doing it before the call. Because you will see the state change PHONE_STATE_IDLE -> PHONE_STATE_OFFHOOK -> PHONE_STATE_IDLE.
// in setonclicklistener put this code:
EditText et_number=(EditText)findViewById(R.id.id_of_edittext);
String my_number = et_number.getText().toString().trim();
Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse(my_number));
startActivity(callIntent);
// give permission for call in manifest:
<uses-permission android:name="android.permission.CALL_PHONE"></uses-permission>
#Dmitri Novikov, FLAG_ACTIVITY_CLEAR_TOP clears any active instance on top of the new one. So, it may end the old instance before it completes the process.
Add this is your xml: android:autoLink="phone"
Steps:
1)Add the required permissions in the Manifest.xml file.
<!--For using the phone calls -->
<uses-permission android:name="android.permission.CALL_PHONE" />
<!--For reading phone call state-->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
2)Create a listener for the phone state changes.
public class EndCallListener extends PhoneStateListener {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
if(TelephonyManager.CALL_STATE_RINGING == state) {
}
if(TelephonyManager.CALL_STATE_OFFHOOK == state) {
//wait for phone to go offhook (probably set a boolean flag) so you know your app initiated the call.
}
if(TelephonyManager.CALL_STATE_IDLE == state) {
//when this state occurs, and your flag is set, restart your app
Intent i = context.getPackageManager().getLaunchIntentForPackage(
context.getPackageName());
//For resuming the application from the previous state
i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
//Uncomment the following if you want to restart the application instead of bring to front.
//i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(i);
}
}
}
3)Initialize the listener in your OnCreate
EndCallListener callListener = new EndCallListener();
TelephonyManager mTM = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
mTM.listen(callListener, PhoneStateListener.LISTEN_CALL_STATE);
but if you want to resume your application last state or to bring it back from the back stack, then replace FLAG_ACTIVITY_CLEAR_TOP with FLAG_ACTIVITY_SINGLE_TOP
Reference this Answer
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent .setData(Uri.parse("tel:+91-XXXXXXXXX"));
startActivity(callIntent );
When starting your call, it looks fine.
There is a difference between android 11+ and down in bringing your app to the front though.
Android 10 or less you need to start a new intent, android 11+ you simply use BringTaskToFront
In the call state IDLE:
if (Build.VERSION.SDK_INT >= 11) {
ActivityManager am = (ActivityManager) activity.getSystemService(Activity.ACTIVITY_SERVICE);
am.moveTaskToFront(MyActivity.MyActivityTaskId, ActivityManager.MOVE_TASK_WITH_HOME);
} else {
Intent intent = new Intent(activity, MyActivity.class);
activity.startActivity(intent);
}
I set the MyActivity.MyActivityTaskId when making the call on my activity like so, it this doesnt work, set this variable on the parent activity page of the page you want to get back to.
MyActivity.MyActivityTaskId = this.getTaskId();
MyActivityTaskId is a static variable on my activity class
public static int MyActivityTaskId = 0;
I hope this will work for you. I use the above code a bit differently, I open my app as soon as the call is answered sothat the user can see the details of the caller.
I have set some stuff in the AndroidManifest.xml as well:
/*Dont really know if this makes a difference*/
<activity android:name="MyActivity" android:taskAffinity="" android:launchMode="singleTask" />
and permissions:
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.REORDER_TASKS" />
Please ask questions if or when you get stuck.
To call from app use simple intent for call, after that if you want to listen the call status then use below code
1] implement this in your class -
implements AudioManager.OnAudioFocusChangeListener
2] Add below code with overridden method
AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE); //public static final String AUDIO_SERVICE = "audio";
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
assert audioManager != null;
audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN);
#Override
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_LOSS: {
//here you can pause your playing audio
break;
}
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: {
//here you can pause your playing audio
break;
}
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: {
break;
}
case AudioManager.AUDIOFOCUS_GAIN: {
//here you will return back to the activity when your call is finsihed
//resume your audio here
break;
}
}
}
3]Add this
#Override
public void onDestroy() {
audioManager.abandonAudioFocus(this);
}

Never Ending Background Service - Java for Android

I wanted to make this service a never ending service, even if the app is killed by the user. That service starts with the app - when it is background, the service still runs-, but when I clear the background tasks on phone, it is also killed. I wanted that final part to be different, wanted this service to keep running on the device... Is that possible? Thanks for the help
public class BackgroundService extends Service {
public static Runnable runnable = null;
public Context context = this;
public Handler handler = null;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
final PackageManager manager = getPackageManager();
//Packages instalados no dispositivo
List<ApplicationInfo> packages = manager.getInstalledApplications(PackageManager.GET_META_DATA);
for (ApplicationInfo info : packages) {
Log.i("Info", "Installed package:" + info.packageName);
}
for (int i = 0; i < packages.size(); i++) {
if(packages.get(i).sourceDir.startsWith("/data/app/")){
//Non System Apps
Log.i("Info", "Installed package /NON SYSTEM/:" + packages.get(i).packageName);
}else{
//system Apps
Log.i("Info", "Installed package !/SYSTEM/!:" + packages.get(i).packageName);
}}
handler = new Handler();
runnable = new Runnable() {
public void run() {
final ActivityManager am = (ActivityManager) getBaseContext().getSystemService(ACTIVITY_SERVICE);
String currentApp ="";
// The first in the list of RunningTasks is always the foreground task.
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
UsageStatsManager usm = (UsageStatsManager) getSystemService(USAGE_STATS_SERVICE);
long time = System.currentTimeMillis();
List<UsageStats> appList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY,
time - 1000 * 1000, time);
if (appList != null && appList.size() > 0) {
SortedMap<Long, UsageStats> mySortedMap = new TreeMap<Long, UsageStats>();
for (UsageStats usageStats : appList) {
mySortedMap.put(usageStats.getLastTimeUsed(),
usageStats);
}
if (mySortedMap != null && !mySortedMap.isEmpty()) {
currentApp = mySortedMap.get(
mySortedMap.lastKey()).getPackageName();
}
}
} else {
ActivityManager.RunningTaskInfo foregroundTaskInfo = am.getRunningTasks(1).get(0);
currentApp = foregroundTaskInfo.topActivity.getPackageName();
}
boolean ApiLigaIsRunning = false;
if (currentApp.contains("maps")) {
ApiLigaIsRunning = true;
Log.i("CHOOSEN APP IS RUNNING ","YES!!!!!!!!!!! " + currentApp);
Handler handler2 = new Handler();
final String finalCurrentApp = currentApp;
handler2.postDelayed(new Runnable() {
public void run() {
Intent openMe = new Intent(getApplicationContext(), LoginActivity.class);
openMe.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(openMe);
am.killBackgroundProcesses(finalCurrentApp);
}
}, 200);
}
Toast.makeText(context, "Service is running", Toast.LENGTH_LONG).show();
List<ActivityManager.RunningAppProcessInfo> appProcesses = am.getRunningAppProcesses();
for(ActivityManager.RunningAppProcessInfo appProcess : appProcesses){
if(appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND){
if (ApiLigaIsRunning == true)
Log.i("Foreground App ", appProcess.processName);
else
Log.i("Not Working! ", appProcess.processName);
}
handler.postDelayed(runnable,200);
}
}
};
handler.postDelayed(runnable, 200);
}
#Override
public void onDestroy() {
Toast.makeText(this, "Service stopped", Toast.LENGTH_LONG).show();
}
}
Here is my Manifest file :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="***************">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
<uses-permission android:name="android.permission.REAL_GET_TASKS" />
<uses-permission android:name="android.permission.GET_TASKS"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.GET_TOP_ACTIVITY_INFO"/>
<uses-permission android:name="android.permission.INSTANT_APP_FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions" />
<application
android:allowBackup="true"
android:icon="#mipmap/icon"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".LoginActivity"
android:theme="#style/AppTheme.Dark">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".BackgroundService"
android:exported="true"
android:enabled="true"
/>
</application>
Never Ending Background Service is not possible but you can Limit Close Service
cause this will Take More Battery which Not Allowed
1- Use Forground Service
this will make service to be run with Notification Like Music App
2- Use START_STICKY
this will make your service start when it Killed
It was possible with a Broadcoast Receiver. But since Oreo (API 26) you can only perform that with a Job Scheduler.
In most cases, apps can work around these limitations by using
JobScheduler jobs. This approach lets an app arrange to perform work
when the app isn't actively running, but still gives the system the
leeway to schedule these jobs in a way that doesn't affect the user
experience. Android 8.0 offers several improvements to JobScheduler
that make it easier to replace services and broadcast receivers with
scheduled jobs.
See more at : https://developer.android.com/about/versions/oreo/background

How to start (Register) service on android boot (Start up)?

Am new to android, I would like to develop an app which can receive SMS and process the message.
I have taken a look around the web on how to receive an SMS and bellow is the code am attempting to use.
public class SmsListener extends BroadcastReceiver {
String R_Message;
private SharedPreferences preferences;
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) {
Bundle bundle = intent.getExtras(); //---get the SMS message passed in---
SmsMessage[] msgs = null;
String msg_from;
if (bundle != null) {
//---retrieve the SMS message received---
try {
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i = 0; i < msgs.length; i++) {
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
msg_from = msgs[i].getOriginatingAddress();
String msgBody = msgs[i].getMessageBody();
}
return;
} catch (Exception e) {
//Log.d("Exception caught",e.getMessage());
R_Message = "No message received";
return;
}
}
}
}
}
and here is the code i found that it can start a service so that my app can be working on background
public class SMSService extends IntentService {
/**
* A constructor is required, and must call the super IntentService(String)
* constructor with a name for the worker thread.
*/
public SMSService() {
super("SMSService ");
}
#Override
protected void onHandleIntent(Intent intent) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// Restore interrupt status.
Thread.currentThread().interrupt();
}
}
}
ref: https://developer.android.com/guide/components/services.html
I created file(s) SmsListener.java and SMSService.java in manifest i do have
<receiver android:name=".SmsListener">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
Permission:
<uses-permission android:name="android.permission.RECEIVE_SMS" />
But i don't know how to call the above two java processes and where to call them so i can verify the app is receiving SMS and it ll continue even when closed.
Note: My app will have two services which needs to be working every-time on background please show me how to add the second service.
Any help is greatly apprenticed thanks
As receivers are already declared in manifest file
SmsListener class will be automatically triggered when ever an message is received
you can process this info in smslistner
for more info refer https://developer.android.com/reference/android/content/BroadcastReceiver.html
I observe the service was suppose to be started within one of my activities as follow
Intent intent = new Intent(this, SMSservice.class);
startService(intent);
This has made it possible for the service to start.

Categories