Smart manager kills an app that hasn't been used for 3 days. My app does some background work and hence, the user doesn't need to open it.
What can I do so that it doesn't enter app optimization mode ( Android OS 5.0.2, 5.1.1)
I found an array with the packages that are in the whitelist from Smart Manager. There is some kind of partnership with developers and Samsung.
Galaxy S7 Android N, Smart Manager its package name now is "com.samsung.android.lool"
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName("com.samsung.android.lool", "com.samsung.android.sm.ui.battery.BatteryActivity");
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
<string-array name="exclude_from_spcm">
<item>com.sds.mdmain</item>
<item>com.whatsapp</item>
<item>com.facebook.orca</item>
<item>com.tencent.mm</item>
<item>com.skype.raider</item>
<item>com.viber.voip</item>
<item>jp.naver.line.android</item>
<item>com.kakao.talk</item>
<item>com.snapchat.android</item>
<item>com.sgiggle.production</item>
<item>kik.android</item>
<item>com.kakao.story</item>
<item>com.nhn.android.band</item>
<item>com.btb.minihompy</item>
<item>com.sec.chatonblue</item>
<item>com.sds.mobiledesk</item>
<item>com.samsung.android.spay</item>
<item>com.sec.android.app.shealth</item>
<item>com.z7.samsung.mobiledesk.z7</item>
<item>com.z7.samsung.mobiledesk.Z7</item>
<item>com.sds.mysinglesquare</item>
<item>com.samsung.uready.agent</item>
<item>com.sds.mobile.mdm.client.MDMManager</item>
<item>com.samsung.android.app.watchmanager</item>
<item>com.samsung.android.wms</item>
<item>com.samsung.accessory.goproviders</item>
<item>com.samsung.accessory.saproviders</item>
<item>com.sec.android.sidesync30</item>
<item>com.amc.ui</item>
<item>com.sec.wecontacts</item>
<item>com.bns.wecontacts</item>
<item>com.sec.weagent</item>
<item>com.sec.wetester</item>
<item>com.samsung.dbs.service</item>
<item>com.kddi.android.videopass</item>
<item>com.ktcs.whowho</item>
<item>com.google.android.wearable.app</item>
<item>com.google.android.projection.gearhead</item>
<item>com.sec.chaton.secure</item>
<item>com.estsoft.alyac</item>
<item>com.estsoft.alyac.tablet</item>
<item>com.coremobility.app.vnotes</item>
<item>com.kineto.smartwifi</item>
<item>msgplus.jibe.sca</item>
<item>com.locationlabs.sparkle.yellow.pre</item>
<item>com.locationlabs.v3client</item>
<item>com.oem.smartwifisupport</item>
<item>com.wsandroid.suite.vodaemea</item>
<item>com.vodafone.sn.vpn</item>
<item>com.vodafone.smhs</item>
<item>com.vodafone.vodafone360updates</item>
<item>com.vodafone.netperform.full</item>
<item>com.vf_nqt.client</item>
<item>com.vodafone.messaging</item>
<item>com.vodafone.safetynet.core</item>
<item>at.mobilkom.android.meina1</item>
<item>al.myvodafone.android</item>
<item>com.zentity.vodafone</item>
<item>com.appseleration.android.selfcare</item>
<item>com.myvodafone.android</item>
<item>hu.mito.android.vodafone</item>
<item>com.VodafoneIreland.MyVodafone</item>
<item>it.vodafone.my190</item>
<item>com.vodafone.android</item>
<item>com.vodafone.mCare</item>
<item>be.belgacom.hello</item>
<item>ro.vodafone.mcare.android</item>
<item>es.vodafone.mobile.mivodafone</item>
<item>com.swisscom.myswisscom</item>
<item>com.myvodafoneapp</item>
<item>za.co.vodacom.android.app</item>
<item>com.appseleration.speedtest</item>
<item>com.radioopt.tmplus</item>
<item>com.radioopt.widget</item>
<item>com.radioopt.engineering</item>
<item>com.radioopt.enterprise</item>
<item>com.radioopt.apc</item>
<item>com.radioopt.network</item>
<item>com.vodafone.accesorystore</item>
<item>at.mobilkom.android.a1apps</item>
<item>com.vodafone.myaccessories</item>
<item>com.swisscom.scappslauncher</item>
<item>com.vodafone.directaccessories</item>
<item>hr.infinum.mojvip</item>
<item>com.vodafone.appstore.sa</item>
<item>com.skt.skaf.a000as00tm</item>
<item>com.kt.mtmoney</item>
<item>com.lgt.tmoney</item>
<item>com.ebcard.skcashbee</item>
<item>com.kt.cashbee</item>
<item>com.lguplus.cashbee</item>
<item>com.hs.govsns.mobile</item>
<item>com.oculus.home</item>
<item>com.samsung.android.hmt.vrsvc</item>
<item>com.oculus.oculus360photos</item>
<item>com.oculus.oculus360videos</item>
<item>com.samsung.android.app.vrsetupwizard</item>
<item>com.samsung.android.app.vrsetupwizardstub</item>
<item>com.oculus.horizon</item>
<item>com.samsung.android.app.vr.gallery</item>
<item>com.samsung.android.app.vr.video</item>
<item>com.oculus.cinema</item>
<item>com.oculus.systemactivities</item>
<item>com.facebook.appmanager</item>
<item>com.facebook.system</item>
<item>com.ipg.gguide.dcm_app.android</item>
<item>com.ipg.gguide.dcm_wifi_app.android</item>
<item>com.nttdocomo.android.iconcier</item>
<item>jp.co.nttdocomo.ichannel</item>
<item>com.nttdocomo.android.osv</item>
<item>com.nttdocomo.android.anmane</item>
<item>com.nttdocomo.android.anmane2</item>
<item>com.rsupport.rs.activity.ntt</item>
<item>jp.co.nttdocomo.android.gs.utility2_sha2</item>
<item>jp.co.nttdocomo.android.gs.utility2</item>
<item>com.nttdocomo.android.mascot</item>
<item>com.nttdocomo.android.docomosimplehome</item>
<item>com.nttdocomo.android.lac</item>
<item>com.nttdocomo.android.settings.lac</item>
<item>com.nttdocomo.android.cloudstorageservice</item>
<item>com.mcafee.vsm_android_dcm</item>
<item>com.nttdocomo.android.gs.utility_sha2</item>
<item>com.nttdocomo.android.gs.utility</item>
<item>com.nttdocomo.android.accountwipe</item>
<item>com.nttdocomo.android.messagedl</item>
<item>com.nttdocomo.android.homeagent</item>
<item>com.nttdocomo.android.toruca</item>
<item>com.nttdocomo.android.photocollection</item>
<item>com.nttdocomo.android.photoviewer</item>
<item>jp.id_credit_sp.android</item>
<item>com.nttdocomo.android.apnmng</item>
<item>jp.co.nttdocomo.contentsheadline</item>
<item>com.mcafee.safecall.docomo</item>
<item>jp.dmapnavi.navi02</item>
<item>com.uievolution.gguide.android</item>
<item>com.showcasegig.devlawson</item>
<item>jp.co.mcdonalds.android</item>
<item>jp.co.lawson.activity</item>
<item>kr.co.nexdigm.mdm.s</item>
<item>kr.co.nexdigm.mdm.agent</item>
<item>com.sktelecom.ssm</item>
<item>com.sktelecom.ssmpush</item>
<item>com.ebcard.cashbeew.s</item>
<item>com.life360.android.safetymapd</item>
<item>com.fsp.android.friendlocator</item>
<item>com.fsp.android.c</item>
<item>com.fsp.android.h</item>
<item>com.fsp.android.phonetracker</item>
<item>com.life360.android.note4</item>
<item>com.life360.android.s6</item>
<item>fr.freemobile.android.vvm</item>
<item>fr.freemobile.android.mobilecompagnon</item>
<item>kr.co.bnkbank.push.customer</item>
<item>kr.co.bnkbank.push.employee</item>
<item>com.shinhan.sbanking</item>
<item>com.shinhan.speedup</item>
<item>com.shinhan.smartcaremgr</item>
<item>com.shinhan.smartfund</item>
<item>com.shinhan.missionbanking</item>
<item>com.shinhan.mobilebankbook</item>
<item>com.safeon.approval</item>
<item>com.shinhan.sbizbank</item>
<item>com.shinhan.trade.copper</item>
<item>com.shinhan.dingdong</item>
<item>com.shinhan.shb2chd</item>
<item>com.shcard.smartpay</item>
<item>com.shinhancard.smartshinhan</item>
<item>com.shinhancard.smartshinhan.mini</item>
<item>com.wr.alrim</item>
<item>com.IBK.SmartPush.app</item>
<item>com.hanafn.push.agent</item>
<item>com.hanabank.ebk.channel.android.hananbank</item>
<item>com.samsung.android.app.memo</item>
<item>com.samsung.android.snote</item>
<item>com.samsung.android.app.pinboard</item>
<item>com.sds.mobile.mdm.client.MDMManager</item>
<item>com.sds.emm.client</item>
<item>com.sds.emm.client.visitor</item>
<item>gogolook.callgogolook2</item>
<item>com.nhn.android.webtoon</item>
<item>com.naver.linewebtoon</item>
<item>com.naver.vapp</item>
<item>com.navercorp.android.ttsapp</item>
<item>com.nhn.android.music</item>
<item>net.daum.android.daum</item>
<item>com.daumkakao.android.brunchapp</item>
<item>com.kakao.page</item>
<item>com.vaultmicro.kidsnote</item>
<item>com.orange.vvm</item>
<item>com.telenor.mbedriftsnett</item>
<item>com.samsung.android.app.scharm</item>
<item>net.ib.android.smcard</item>
<item>com.samsungcard.certi</item>
<item>kr.co.samsungcard.mpocket</item>
<item>com.samsungcard.shopping</item>
<item>com.samsungcard.baby</item>
<item>sc.chn.hom.msa.ga</item>
<item>com.samsung.android.email.provider</item>
<item>com.samsung.oh</item>
<item>com.sec.android.app.sbrowser</item>
<item>com.microsoft.windowsintune.companyportal</item>
<item>com.icq.mobile.client</item>
<item>com.my.mail</item>
<item>com.vkontakte.android</item>
<item>ru.mail.mailapp</item>
<item>ru.ok.android</item>
<item>com.google.android.apps.tachyon</item>
<item>ru.mail</item>
<item>com.lacoon.security.fox</item>
<item>com.google.android.apps.fireball</item>
<item>com.sds.mms.ui</item>
<item>com.mcafee.android.scanservice</item>
<item>com.android.services.telephony.common</item>
<item>com.samsungcard.android.oap</item>
<item>com.sec.android.app.ocr3</item>
<item>com.sec.android.app.ocr4</item>
<item>com.mediatek.BlueMagpie</item>
<item>com.samsung.android.game.gametools</item>
<item>it.h3g.areaclienti3</item>
<item>com.skt.prod.cloud</item>
<item>com.turkcell.bip</item>
<item>com.samsung.android.intelligence.executormanager</item>
<item>com.nttdocomo.android.hcebridge</item>
<item>jp.id_credit_sp.android.devappli</item>
<item>com.knb.psb</item>
<item>com.knb.csb</item>
<item>com.knb.bsp</item>
<item>com.knb.bdr</item>
<item>com.diotek.sec.lookup.dictionary</item>
<item>com.samsung.android.onlinevideo</item>
<item>com.oculus.systemdriver</item>
<item>com.oculus.gearchina</item>
<item>com.oculus.systemservices</item>
<item>com.nttdocomo.android.iconcier_contents</item>
<item>com.nttdocomo.android.socialphonebook</item>
<item>com.nttdocomo.android.portablesim</item>
<item>com.sktelecom.ttalk</item>
</string-array>
Sadly, there is currently no way to prevent this.
The only thing you can do is instruct users to disable optimization for your app.
I did some research about this myself not long ago, here are some links I saved that might be interesting for you
https://news.samsung.com/global/smart-manager-the-way-to-keep-your-galaxy-smartphone-as-good-as-new-always
http://developer.samsung.com/forum/thread/smart-manager-kills-my-alarms/202/288300?boardName=General&listLines=15&startId=zzzzz~&curPage=3
http://developer.samsung.com/forum/thread/samsung-smart-manager-is-preventing-alarmmanager-to-work-correctly/201/288546?boardName=SDK&startId=zzzzz~&searchSubId=0000000001
Also, here is a code snippet that launches the smart manager app's BatteryActivity (if it's installed) to help users to disable the optimization:
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.samsung.android.sm", "com.samsung.android.sm.ui.battery.BatteryActivity"));
try {
getActivity().startActivity(intent);
} catch (ActivityNotFoundException ex) {
Toast.makeText(getActivity(), "Smart manager not installed on this device", Toast.LENGTH_LONG)
.show();
}
Related
Background
Apps use Intents to open other apps, sometimes with specialized Intents.
One example is this Intent, to choose a contact from WhatsApp:
val WHATSAPP_PACKAGE_NAME = "com.whatsapp"
val whatsAppPickIntent = Intent(Intent.ACTION_PICK).setPackage(WHATSAPP_PACKAGE_NAME)
This works fine in general. Same goes for when you wish to launch the app:
val launchIntent=packageManager.getLaunchIntentForPackage(WHATSAPP_PACKAGE_NAME)
The problem
Recently I was informed of a relatively new feature, allowing the user to have multiple instances of the same app. It might be available on other devices, but on OnePlus devices it's called "parallel apps". Here's an example of 2 instances of WhatsApp, each is assigned to a different phone number :
Thing is, this can break how Intents work with a single instance of the app. Now the Intent doesn't know for which app to go to. The launcher show 2 icons now for WhatsApp:
If you choose to launch WhatsApp via the normal launcher icon (the left one), it shows this dialog:
Works fine, but if you choose to use the picker intent, you still get this dialog, but when you choose an item, from the dialog, it doesn't let you really do anything with it (opens and closes the app), while showing a toast "The file format is not supported".
What I've tried
Since I don't have the device, I tried to read about it over the Internet, but I only found user-related information, such as these:
https://www.androidpolice.com/2017/08/04/new-oneplus-33t-open-beta-adds-parallel-app-support-run-multiple-instances-app/
https://www.techrepublic.com/article/how-to-run-cloned-versions-of-apps-with-oneplus-parallel-apps/
I've decided to try to investigate it further, by sending an APK to the person who told me about it, trying to see if the next code will work any different:
val whatsAppPickIntent = Intent(Intent.ACTION_PICK).setPackage(WHATSAPP_PACKAGE_NAME)
val queryIntentActivities: List<ResolveInfo> = packageManager.queryIntentActivities(whatsAppPickIntent, 0)
button2.setOnClickListener {
intent = Intent(Intent.ACTION_PICK)
val resolveInfo = queryIntentActivities[0]
toast("number of possible choices:" + queryIntentActivities.size)
intent.component = ComponentName(resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name)
startActivity(intent)
}
The toast that will be shown tells that I have only one thing that can handle the intent, and indeed when I use it, I get the same dialog for choosing which instance of it to use. And like in the original Intent, it fails with the same toast.
EDIT: Later I tried the next thing: I asked to show what are the ResolveInfo properties, before and after enabling the feature, by using this code:
val launchIntent = packageManager.getLaunchIntentForPackage(WHATSAPP_PACKAGE_NAME)
val whatsAppPickIntent = Intent(Intent.ACTION_PICK).setPackage(WHATSAPP_PACKAGE_NAME)
var queryIntentActivities: List<ResolveInfo> = packageManager.queryIntentActivities(whatsAppPickIntent, 0)
var sb = StringBuilder()
queryIntentActivities[0].dump(object : Printer {
override fun println(x: String?) {
if (x != null)
sb.append(x)
}
}, "")
val pickResult = "pick result:packageName:\"" + queryIntentActivities[0].activityInfo.packageName + "\" name:\"" + queryIntentActivities[0].activityInfo.name + "\"\n\n" + "extended:" + sb.toString()
sb = StringBuilder()
queryIntentActivities = packageManager.queryIntentActivities(launchIntent, 0)
queryIntentActivities[0].dump(object : Printer {
override fun println(x: String?) {
if (x != null)
sb.append(x)
}
}, "")
val launchResult = "launch result:packageName:\"" + queryIntentActivities[0].activityInfo.packageName + "\" name:\"" + queryIntentActivities[0].activityInfo.name + "\"\n\n" + "extended:" + sb.toString()
val body = pickResult + "\n\n" + launchResult
val emailIntent = Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto", "", null))
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "whatsApp investigation")
emailIntent.putExtra(Intent.EXTRA_TEXT, body)
startActivity(Intent.createChooser(emailIntent, "Send email..."))
The result is that both are the same, as if everything is fine. Here's the result when it's turned on/off (exact same thing) :
pick result:packageName:"com.whatsapp" name:"com.whatsapp.ContactPicker"
extended:priority=0 preferredOrder=0 match=0x108000 specificIndex=-1 isDefault=falseActivityInfo: name=com.whatsapp.ContactPicker packageName=com.whatsapp enabled=true exported=true directBootAware=false taskAffinity=com.whatsapp targetActivity=null persistableMode=PERSIST_ROOT_ONLY launchMode=0 flags=0x3 theme=0x7f110173 screenOrientation=-1 configChanges=0xfb3 softInputMode=0x0 lockTaskLaunchMode=LOCK_TASK_LAUNCH_MODE_DEFAULT resizeMode=RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION ApplicationInfo: name=com.whatsapp.AppShell packageName=com.whatsapp labelRes=0x7f100473 nonLocalizedLabel=null icon=0x7f080c15 banner=0x0 className=com.whatsapp.AppShell processName=com.whatsapp taskAffinity=com.whatsapp uid=10099 flags=0x3 privateFlags=0x1010 theme=0x7f110164 requiresSmallestWidthDp=0 compatibleWidthLimitDp=0 largestWidthLimitDp=0 sourceDir=/data/app/com.whatsapp-NaKTLVhiNTh4zEGhFdkxrg==/base.apk seinfo=default:targetSdkVersion=26 seinfoUser=:complete dataDir=/data/user/0/com.whatsapp deviceProtectedDataDir=/data/user_de/0/com.whatsapp credentialProtectedDataDir=/data/user/0/com.whatsapp enabled=true minSdkVersion=15 targetSdkVersion=26 versionCode=452238 targetSandboxVersion=1 supportsRtl=true fullBackupContent=true category=4
launch result:packageName:"com.whatsapp" name:"com.whatsapp.Main"
extended:priority=0 preferredOrder=0 match=0x0 specificIndex=-1 isDefault=falseActivityInfo: name=com.whatsapp.Main packageName=com.whatsapp labelRes=0x7f10044c nonLocalizedLabel=null icon=0x0 banner=0x0 enabled=true exported=true directBootAware=false taskAffinity=com.whatsapp targetActivity=null persistableMode=PERSIST_ROOT_ONLY launchMode=0 flags=0x3 theme=0x0 screenOrientation=-1 configChanges=0xfb3 softInputMode=0x0 lockTaskLaunchMode=LOCK_TASK_LAUNCH_MODE_DEFAULT resizeMode=RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION ApplicationInfo: name=com.whatsapp.AppShell packageName=com.whatsapp labelRes=0x7f100473 nonLocalizedLabel=null icon=0x7f080c15 banner=0x0 className=com.whatsapp.AppShell processName=com.whatsapp taskAffinity=com.whatsapp uid=10099 flags=0x3 privateFlags=0x1010 theme=0x7f110164 requiresSmallestWidthDp=0 compatibleWidthLimitDp=0 largestWidthLimitDp=0 sourceDir=/data/app/com.whatsapp-NaKTLVhiNTh4zEGhFdkxrg==/base.apk seinfo=default:targetSdkVersion=26 seinfoUser=:complete dataDir=/data/user/0/com.whatsapp deviceProtectedDataDir=/data/user_de/0/com.whatsapp credentialProtectedDataDir=/data/user/0/com.whatsapp enabled=true minSdkVersion=15 targetSdkVersion=26 versionCode=452238 targetSandboxVersion=1 supportsRtl=true fullBackupContent=true category=4
So I wanted to check on something else: Try to put a widget-shortcut of WhatsApp (called "whatsApp chat"), that requires you to choose a contact, when this feature is turned on.
Turns out, it can't handle it well. It asks which app to create the widget to: the original or the clone. If you choose the original, all is fine. If you choose the clone, it adds the widget all fine and well, but when clicking on it, it goes to the main window of the app instead of going to the person.
The questions
How can I differentiate between the main instance and the "cloned" one? I mean, how can an Intent be directed to a single instance (the main one) of the targeted app? I ask this about both of the Intents I've presented (launch and picker).
How does this feature even work? Where does the private data of each instance gets saved now? Does each of them have a process, with a different name?
Do other devices of other OEMs have this feature? Does it work there the same way as here ?
Why do we see the toast message, if the user chose the app to target to? Is it maybe a buggy feature, that will work only for launch-intents?
Is there at least a way to know that a given app (given a package name of it) has this feature enabled for it?
During developing application in Xamarin Android we encountered strange error. The pick image/video (whether its from camera or documents UI) application sometimes crashes with no error. Scenario is that we open application, make steps to the activity, where the images are chosen, and then open the camera or document UI by standard way:
public void ChooseMediaAfterTypeChose (bool photo, bool camera) {
try {
string title = "";
int id;
Intent iIntent;
if (camera) {
if (photo) {
iIntent = new Intent("android.media.action.IMAGE_CAPTURE");
id = Const.AND_pickImageID_camera;
App._file = new File (App._dir, "myPhoto.jpg");
iIntent.PutExtra (Android.Provider.MediaStore.ExtraOutput, Uri.FromFile (App._file));
} else {
iIntent = new Intent("android.media.action.VIDEO_CAPTURE");
id = Const.AND_pickVideoID_camera;
App._file = new File (App._dir, "myVideo.mp4");
iIntent.PutExtra (Android.Provider.MediaStore.ExtraOutput, Uri.FromFile (App._file));
}
} else {
iIntent = new Intent ();
iIntent.SetAction (Intent.ActionGetContent);
if (photo) {
iIntent.SetType ("image/jpg");
title = Static.mainData.currentTexts.ChoosePhoto;
id = Const.AND_pickImageID_galery;
} else {
iIntent.SetType ("video/mp4");
title = Static.mainData.currentTexts.ChooseVideo;
id = Const.AND_pickVideoID_galery;
}
}
if (camera) {
StartActivityForResult (iIntent, id);
} else {
StartActivityForResult (Intent.CreateChooser (iIntent, title), id);
}
} catch (Exception ex) {
ShowError (Static.mainData.currentTexts.MediaError);
W.L(ex.Message);
}
}
The chosen application crashes during image/video picking (E.g. during browsing images in gallery wthout picking any). When that happens we never get to any method in our code.
What we have:
When user don't pick photos, the application runs without any memory crash
Sometimes the picking proceedes without error.
We think that the issue is mainly on Android 4.4.2 (It happend to us only on devices with this android - on other android version devices we didn't encounter it)
What we tried:
We put all permissions to manifest (read/write external storage, hardware.camera etc.)
We delete almost all memory stored content to save up memory
All Activities are unload from memory when they leave the screen
Logcat says that every process connected (Application and the active application) just died with no trace to any error
Our question is if anyone stumbled to similar issue and how to handle it. The second question is if there is any way to find out whats happening.
EDIT:
App._dir code added.
App._dir = new Java.IO.File (
Environment.GetExternalStoragePublicDirectory (
Environment.DirectoryPictures), "Camera");
if (!App._dir.Exists ())
{
App._dir.Mkdirs( );
}
I'm trying to tell the google cloud printing app to print a document, be it a .png file or an pdf. After checking if the app is installed via
public static boolean isCloudPrintInstalled(Context ctx){
String packageName = "com.google.android.apps.cloudprint";
android.content.pm.PackageManager mPm = ctx.getPackageManager();
try{
PackageInfo info = mPm.getPackageInfo(packageName, 0);
boolean installed = (info != null);
return installed;
}catch(NameNotFoundException e){
return false;
}
}
i send the user to the PrintingDialogActivity if it is missing, as described here: https://developers.google.com/cloud-print/docs/android
But i would like to use the app, if it is installed. If i send the following intent:
File theFile = new File(filePath); //file is NOT missing
Intent printIntent = new Intent(Intent.ACTION_SEND);
printIntent.setType(Helper.getMimeType(filePath));
printIntent.putExtra(Intent.EXTRA_TITLE, titleOfFile);
printIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(theFile));
ctx.startActivity(printIntent);
The getMimeType method is this:
public static String getMimeType(String url) {
String method = "Helper.getMimeType";
String type = null;
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
//Fix for Bug: https://code.google.com/p/android/issues/detail?id=5510
if(extension == null || extension.equals("")){
extension = url.substring(url.lastIndexOf('.'));
}
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
//should i consider just not using the MimeTypeMap? -.-
if(type == null || type.equals("")){
if(extension.toLowerCase(Locale.getDefault()).equals(".txt") == true){
type = "text/plain";
}else{
Log.e(method, "Unknown extension");
}
}
return type;
}
it returns "application/pdf" for pdf files.
On my android 4.0.3 device i get the action chooser and can choose the google cloud print app, which then allows to do stuff like saving the file to google drive. It works.
But if i start this intent on my Android 5.1.1 device (Nexus 5), the action chooser also opens, but it doesn't have the google cloud printing app or anything else printing related in it. Cloud print is preinstalled and currently on version 1.17b. I didn't kill it's process with some form of energy saving app. The device is not routed. What am i missing?
I also tried entering "text/html" by hand as the mime type, because that was the solution to another stackoverflow thread - but it doesn't solve mine.
Setting the mimetype to */* also doesn't make the actionchooser offer me the printer
After a lot of googling and testing it is rather unclear to me, if printing via intent is still possible on android 5 with google cloud print. BUT what does work is to create a custom PrintDocumentAdapter, as described in this post: https://stackoverflow.com/a/20719729/1171328
I have been searching for this from past few days and I came to know that:
"Dual SIM is not supported in Android out of the box. It is a custom modification by manufacturers, and there is no public API to control it."
There is a solution provided in the below link but its not working on my phone Samsung Galaxy S4 Mini.
Call from second sim
I also found this link, which I found very informative.
http://www.devlper.com/2010/06/using-android-telephonymanager/
Now I know that using the following code, I might have a chance to get lucky to make it working:
Intent callIntent = new Intent(Intent.ACTION_CALL)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
callIntent.setData(Uri.parse("tel:" + phone));
context.startActivity(callIntent);
callIntent.putExtra("com.android.phone.extra.slot", 0); //For sim 1
and
callIntent.putExtra("com.android.phone.extra.slot", 1); //For sim 2
I am not sure about this, but I have a question.
In Settings under the SIM Card Manager section, when I have to choose a preferred SIM card for Voice Call, I get four options:
Current Network
Ask Always
SIM 1
SIM 2
When I choose Ask Always option then before making a call I am always asked for choosing a SIM Card, displayed in a Dialog Box, to make the call. My question is can I exploit this thing in my App where I press a button to make a call but it always asks me the same way it does when I chose Ask Always option.
I am sorry, I made this question lengthy, but I think it required it. Please help and big thanks in advance.
EDIT:
How can I achieve this, everytime I press any button (Kind of similar to Ask Always option in Settings) :
Code:
private final static String simSlotName[] = {
"extra_asus_dial_use_dualsim",
"com.android.phone.extra.slot",
"slot",
"simslot",
"sim_slot",
"subscription",
"Subscription",
"phone",
"com.android.phone.DialingMode",
"simSlot",
"slot_id",
"simId",
"simnum",
"phone_type",
"slotId",
"slotIdx"
};
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + "any number"));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("com.android.phone.force.slot", true);
intent.putExtra("Cdma_Supp", true);
//Add all slots here, according to device.. (different device require different key so put all together)
for (String s : simSlotName)
intent.putExtra(s, 0); //0 or 1 according to sim.......
//works only for API >= 21
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
intent.putExtra("android.telecom.extra.PHONE_ACCOUNT_HANDLE", (Parcelable) " here You have to get phone account handle list by using telecom manger for both sims:- using this method getCallCapablePhoneAccounts()");
context.startActivity(intent);
TelecomManager telecomManager = (TelecomManager) this.getSystemService(Context.TELECOM_SERVICE);
List<PhoneAccountHandle> phoneAccountHandleList = telecomManager.getCallCapablePhoneAccounts();
Intent intent = new Intent(Intent.ACTION_CALL).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setData(Uri.parse("tel:" + number));
intent.putExtra("com.android.phone.force.slot", true);
intent.putExtra("Cdma_Supp", true);
if (simselected== 0) { //0 for sim1
for (String s : simSlotName)
intent.putExtra(s, 0); //0 or 1 according to sim.......
if (phoneAccountHandleList != null && phoneAccountHandleList.size() > 0)
intent.putExtra("android.telecom.extra.PHONE_ACCOUNT_HANDLE", phoneAccountHandleList.get(0));
} else { 1 for sim2
for (String s : simSlotName)
intent.putExtra(s, 1); //0 or 1 according to sim.......
if (phoneAccountHandleList != null && phoneAccountHandleList.size() > 1)
intent.putExtra("android.telecom.extra.PHONE_ACCOUNT_HANDLE", phoneAccountHandleList.get(1));
}
startActivity(intent);
I have an answer for this problem as I was looking for this option. Here are the steps:
first you need xposed framework and;
install miui application and;
add preferred sim option in contact
I develop a game that is heavily dependent upon timing, when I run it in the emulator it executes understandably slower than when I run it on my phone. This forces me to up all the "stats" in my game, so that I can actually "beat it" when I am developing - when Debugging, the game is unwinnable.
Is there a call, or variable, or something that I can use to determine whether I am currently running on the Emulator and not a device.
I've considered trying to detect if Framerate is low.
I've considered trying to read the "device name" from some sort of build in system field.
But neither seems like a very good method to pursue.
Any help would be great.
Use the Build.DEVICE value and compare to "sdk".
First idea:check the network operator, on the emulator, it's always equal to "Android". Not documented and just a guess that it will work everytime!
TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String networkOperator = tm.getNetworkOperatorName();
if("Android".equals(networkOperator)) {
// Emulator
}
else {
// Device
}
Second idea: the manufacturer:
public boolean isEmulator() {
return Build.MANUFACTURER.equals("unknown");
}
Third idea: seem th best one, check the debug key:
static final String DEBUGKEY =
"get the debug key from logcat after calling the function below once from the emulator";
public static boolean signedWithDebugKey(Context context, Class<?> cls)
{
boolean result = false;
try {
ComponentName comp = new ComponentName(context, cls);
PackageInfo pinfo = context.getPackageManager().getPackageInfo(comp.getPackageName(),PackageManager.GET_SIGNATURES);
Signature sigs[] = pinfo.signatures;
for ( int i = 0; i < sigs.length;i++)
Log.d(TAG,sigs[i].toCharsString());
if (DEBUGKEY.equals(sigs[0].toCharsString())) {
result = true;
Log.d(TAG,"package has been signed with the debug key");
} else {
Log.d(TAG,"package signed with a key other than the debug key");
}
} catch (android.content.pm.PackageManager.NameNotFoundException e) {
return false;
}
return result;
}
from here: How can I detect when an Android application is running in the emulator?
If you're using Google APIs, you want:
"google_sdk".equals( Build.PRODUCT );
If not, you'll want to use:
"sdk".equals( Build.PRODUCT );
The older (since deprecated) way to do this was to check ANDROID_ID, which is null on the AVD, but this doesn't work on API 7 and above:
// ONLY WORKS ON 2.1 AND BELOW
String android_id = Secure.getString(getContentResolver(), Secure.ANDROID_ID);
if (android_id == null) {
// Emulator!
} else {
// Device
}
Dan S gave a good answer about how to detect when running on the emulator. However, a few tips:
Instead of relying on something in the SDK, why not just set up your own flag? Just keep a public final static boolean isEmulator that you change from true to false depending on the environment, and build your code with ifs and elses around it. The Build.DEVICE method is not 100% safe, since some rooted devices might have that borked.
Low framerate detection could be a good thing to implement. Given the wide range of Android devices, it might prove helpful on lower-end ones.