Application background service stopped when swiped up in China Phone - java

I have been searching for answers regarding this problem with China phone (Oppo, Huawei, XiaoMi, Vivo, etc.) when app is swiped up (close), the background services stopped running.
Most of the solutions were:
Include START_STICKY and use AlarmManager to start service.
Programmatically direct user to auto-start manager to enable app by user.
Manually exclude my app from power saving mode or include my app as protected apps.
My question is how does apps like Whatsapp still receives message or notification even swiped up?
Furthermore, the solutions mentioned in 1. and 2. doesn't work if phone restarts, but how Whatsapp still can receive messages?
I have tested Samsung devices, they have no problem running background services even though the app is swiped up.
Has anyone face the same problem with China phone?

try {
Intent intent = new Intent();
String manufacturer = android.os.Build.MANUFACTURER;
if ("xiaomi".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity"));
} else if ("oppo".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.permission.startup.StartupAppListActivity"));
} else if ("vivo".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.vivo.permissionmanager", "com.vivo.permissionmanager.activity.BgStartUpManagerActivity"));
} else if ("oneplus".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.oneplus.security", "com.oneplus.security.chainlaunch.view.ChainLaunchAppListAct‌​ivity"));
} else if ("Letv".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.AutobootManageActivity"));
} else if ("Honor".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity"));
}
else if ("huawei".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity"));
}
else if ("asus".equalsIgnoreCase(manufacturer)) {
intent.setComponent(new ComponentName("com.asus.mobilemanager","com.asus.mobilemanager.autostart.AutoStartActivity"));
}
else {
Log.e("other phone ", "===>");
}
List<ResolveInfo> list = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if (list.size() > 0) {
startActivity(intent);
}
} catch (Exception e) {
e.printStackTrace();
}

I am still looking for the answer. I have contacted Google support team and they replied as follow:
Upon discussion with our engineers, this is really the expected behavior. For the reason that they use a stock ROM that disables the re-starting of background services for most apps. Users should manually enable the auto-starting of background services as they are disabled by default. This can not be programmatically enabled for all devices. So you'll have to prompt your users to perform the steps manually. Please check out this guide to learn more about this workaround.

Related

Some Android phones not opening “About device” page in Settings?

Some Android phones don't do anything when the the code below is ran. It's supposed to open the "About device" page in Settings.
For example, I know for a fact that it has no effect on the Huawei Y9 Prime 2019 running Android 10.
startActivity(new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS));
What's the best way to safeguard against this issue when it occurs? (In my app, I open this page to ask the user to perform a specific action there)
Use PackageManager.resolveActivity() to check whether such an Activity exists. If that returns null, there is no activity that matches the Intent and you have to guide your customers to the settings in another way:
Intent intent = new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS);
ResolveInfo resolveInfo = getPackageManager().resolveActivity(intent, 0);
if (resolveInfo == null) {
// help customers by describing how to get to the device info settings
} else {
startActivity(intent);
}
If an activity is not found, the method startActivity will throw android.content.ActivityNotFoundException. You should catch this exception and notify the user:
try {
startActivity(new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS));
} catch (ActivityNotFoundException e) {
// Notify the user, eg. using a popup so they can open settings manually
}

Fix the 'background service' problem on Android 8+

I have code running a service behind the scenes. It is set to run when we copy the text to the phone.
This code works fine on Android 8 below
But the problem is when I run the app on Android 8 and above
In my searches, I realized that I had to use FOREGROUND_SERVICEs and give specific access to the project.
What solutions do you suggest now?
Service Class:
public class AutoDownloadService extends Service {
private ClipboardManager mClipboardManager;
public static final String CHANNEL_ID = "ForegroundServiceChannel";
#Override
public void onCreate() {
super.onCreate();
mClipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
mClipboardManager.addPrimaryClipChangedListener(mOnPrimaryClipChangedListener);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String input = intent.getStringExtra("inputExtra");
createNotificationChannel();
Intent notificationIntent = new Intent(this, SettingsActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Foreground Service")
.setContentText(input)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
// stopSelf();
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
if (mClipboardManager != null) {
mClipboardManager.removePrimaryClipChangedListener(mOnPrimaryClipChangedListener);
}
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"Foreground Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
}
private ClipboardManager.OnPrimaryClipChangedListener mOnPrimaryClipChangedListener =
new ClipboardManager.OnPrimaryClipChangedListener() {
#Override
public void onPrimaryClipChanged() {
ClipData clip = mClipboardManager.getPrimaryClip();
String textClipBoard = clip.getItemAt(0).getText().toString();
Toast.makeText(AutoDownloadService.this, textClipBoard, Toast.LENGTH_SHORT).show();
}
};
}
Manifest
<service
android:name=".services.AutoDownloadService"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE" />
and add finally uses permission
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
I think you should use Intent Service instead of service.
what you can do is if system shutdown your service you can again trigger it after sometime using alarm manger.
As stated in documentation
While an app is in the foreground, it can create and run both
foreground and background services freely. When an app goes into the
background, it has a window of several minutes in which it is still
allowed to create and use services. At the end of that window, the app
is considered to be idle. At this time, the system stops the app's
background services, just as if the app had called the services'
Service.stopSelf() methods.
So, you solution is to run foreground service on Android >= 8.0 and do something like this
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(Intent(this, AutoDownloadService.class))
} else {
startService(Intent(this, AutoDownloadService.class))
}
}
First of all, you should not do this.
Monitoring clipboard in background is not something right.
Android 8 added some protection on this, so you should run as foreground services, to let the end user aware your app is monitoring the clipboard.
Anyway clipboard access only available to default IME from Android 10. So, your apps will not work in Android 10.
This example of my code is currently working fine but I have problems with Chinese mobile
Tested on mobile: Xiaomi 7
public class AutoDownloadService extends IntentService {
private ClipboardManager mClipboardManager;
public AutoDownloadService() {
super("AutoDownloadService");
}
#Override
public void onCreate() {
super.onCreate();
mClipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
mClipboardManager.addPrimaryClipChangedListener(mOnPrimaryClipChangedListener);
}
#Override
protected void onHandleIntent(Intent intent) {
Toast.makeText(this, " service started.", Toast.LENGTH_SHORT).show();
}
private final ClipboardManager.OnPrimaryClipChangedListener mOnPrimaryClipChangedListener =
new ClipboardManager.OnPrimaryClipChangedListener() {
#Override
public void onPrimaryClipChanged() {
ClipData clip = mClipboardManager.getPrimaryClip();
String textClipBoard = clip.getItemAt(0).getText().toString();
if (textClipBoard.startsWith("https://www.instagram.com/")) {
Toast.makeText(AutoDownloadService.this, textClipBoard, Toast.LENGTH_SHORT).show();
}
}
};
}
And in the file Manifast.xml This is how it is defined
<service android:name="com.amirhf.inatasave.services.AutoDownloadService" />
When you swipe the app from recent apps, few Chinese OEMs force stop the apps.
Once the App is force stopped, you can't post notifications, start services, receive broadcasts etc.
The only work around is : Your app should be whitelisted, added in
auto start list. Apps like WhatsApp, Facebook etc are already added by
the OEMs in the list.
This blog talks about similar problem of not receiving notifications when App is force stopped. https://hackernoon.com/notifications-in-android-are-horribly-broken-b8dbec63f48a
You can take a similar approach where you can have a "Troubleshoot" section where you can educate the user to add your app in auto start list.
If by any chance your app is very popular you can get in touch with
Chinese Manufacturer and request them to get your app whitelisted but
they do it for very popular apps. For example in my experience
Microsoft and Hike Messenger got it done for their apps.
I didn't quite understand if you're messing with file download or anything else. But I guess you're not going the right way. So here's what I may share.
From https://developer.android.com/training/scheduling/wakelock
If your app is performing long-running HTTP downloads, consider using DownloadManager.
If your app is synchronizing data from an external server, consider creating a sync adapter.
If your app relies on background services, consider using JobScheduler or Firebase Cloud Messaging to trigger these services
at specific intervals.
Also note that if you just have a task that has to done often, use JobIntentService. Its compatible with Oreo and versions below it:
Helper for processing work that has been enqueued for a job/service.
When running on Android O or later, the work will be dispatched as a
job via JobScheduler.enqueue. When running on older versions of the
platform, it will use Context.startService.
On Oreo and above versions there are limitations helping the device save resources (battery, ram...) and even when using JobIntentService you must consider them; otherwise your app may be recognized as Battery Draining App.
If what you're about to do is heavy and is important enough to be shown in notification bar, do it using ForegroundService. So that it will be taken more seriously by android system and chances of it being killed gets fewer.
Try using WorkManager it's a JetPack Library.
Advantages:
Ensures task execution, even if the app or device restarts (Guaranteed Execution)
You don’t need to write device logic to figure out what capabilities the device has and choose an appropriate API; instead, you can just hand your task off to WorkManager and let it choose the best option. It is a wrapper on all the above concepts.
Uses JobScheduler on devices with API 23+
Uses a combination of BroadcastReceiver + AlarmManager on devices with API 14-22
Ref : WorkManager Docs
Ref : Medium Article
Ref : Medium Article(1)
[Update] - stable version is out WorkManager

Read permission of installed Application in android phone?

I want to read permission of other applications installed in my android mobile using programming.
I think Android Cleaner read permission of other apps and display details like
I want get detail like this Image.
In this it's give details of Ad Network
How i get details like this app in my app?
If this app not Read Permission then How it's do it?
Well you can scrape the playstore app page for a given app and get the permissions it needs :)
Well that's just off the top of my head. On a serious note, you can do the following:
Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
List appsList = getPackageManager().queryIntentActivities(intent, 0);
for (Object app : appsList) {
ResolveInfo resolveInfo = (ResolveInfo) app;
PackageInfo packageInfo = null;
try {
packageInfo = getPackageManager().getPackageInfo(resolveInfo.activityInfo.packageName, PackageManager.GET_PERMISSIONS);
} catch (NameNotFoundException ex) {
ex.printStackTrace();
}
String[] requestedPermissions = packageInfo.requestedPermissions;
}

Getting register error :Account missing when integrating GCM for pushwoosh in android

I am successfully integrating pushwoosh in my android application.I am using GCM.here is my code:
oncreate:
PushManager pushManager = new PushManager(this,
App_id, Sender_id);
pushManager.onStartup(savedInstanceState, this);
checkMessage(getIntent());
#Override
protected void onNewIntent(Intent intent)
{
super.onNewIntent(intent);
setIntent(intent);
checkMessage(intent);
setIntent(new Intent());
}
private void checkMessage(Intent intent)
{
if (null != intent)
{
if (intent.hasExtra(PushManager.PUSH_RECEIVE_EVENT))
{
showMessage("push message is " + intent.getExtras().getString(PushManager.PUSH_RECEIVE_EVENT));
}
else if (intent.hasExtra(PushManager.REGISTER_EVENT))
{
showMessage("register");
}
else if (intent.hasExtra(PushManager.UNREGISTER_EVENT))
{
showMessage("unregister");
}
else if (intent.hasExtra(PushManager.REGISTER_ERROR_EVENT))
{
showMessage("register error");
}
else if (intent.hasExtra(PushManager.UNREGISTER_ERROR_EVENT))
{
showMessage("unregister error");
}
}
}
private void showMessage(String message)
{
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}
But when i am running my app its showing register error.I can not find what's the problem?In logcat it shows Messaging registration error:Account Missing.Please Help
Account Missing error occurred when there is no Google account on the phone. Here is the official explanation from GCM page.
There is no Google account on the phone. The Android application
should ask the user to open the account manager and add a Google
account. Fix on the device side.
For more information check here.
If you have "account missing" error you need to configure your Google Account on the device.
Open the account manager and add a Google account there.
Also make sure you can to login to the Android Marketplace from the device.
I am also facing the problem, but as far I understood that the appid and senderId is wrong here, try with the new one.

Start Android Market from App

I'm developing a lite version for an app on the Android. How can I start an Intent to open the Android Market, preferably with the full version of my app displayed? This is difficult to test on an emulator (which is the closest thing to a device I have), as there seems to be no legal way of installing the Market on it.
That query above works, but when I tried it, it looked like it was bringing up search results based on the name.
If you use something like
intent.setData(Uri.parse("market://details?id=com.wolinlabs.SuperScorepad"));
instead, it will go right to the Android Market page for your app.
I think that's more what you wanted (?)
Found answer in the end:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("market://search?q=pname:MyApp"));
startActivity(intent);
No way of testing on emulator, though.
Hi I was trying the achieve the same but with one small difference
I DIDN'T WANT TO OPEN IT EMBEDDED ON MY APP
public void start(JSONArray args, CallbackContext callback) {
Intent launchIntent;
String packageName;
String activity;
String uri;
ComponentName comp;
try {
packageName = args.getString(0); //com.android.vending
activity = args.getString(1); //com.google.android.finsky.activities.LaunchUrlHandlerActivity
uri = args.getString(2); //'market://details?id=com.triplingo.enterprise'
launchIntent = this.cordova.getActivity().getPackageManager().getLaunchIntentForPackage(packageName);
comp = new ComponentName(packageName, activity);
launchIntent.setComponent(comp);
launchIntent.setData(Uri.parse(uri));
this.cordova.getActivity().startActivity(launchIntent);
callback.success();
} catch (Exception e) {
callback.error(e.toString());
}
}
THE BIG DIFFERENCE HERE IS THAT YOU START A NEW APP NOT JUST SHOW GOOGLE PLAY IN YOUR
APP
This code is part of a Cordova plugin but is pretty obvious what you need to do to use it natively.
THE IMPORTANT LINES
launchIntent = this.cordova.getActivity().getPackageManager().getLaunchIntentForPackage(packageName);
comp = new ComponentName(packageName, activity);
launchIntent.setComponent(comp);
launchIntent.setData(Uri.parse(uri));
Regards

Categories

Resources