I hava a question about Android Receiver.
I'm possible to change System app.
B is the first app, when user turns on the power. But the problem is when user chooses FACTORY Mode(like setting language, google id...), B App has to be started finishing A App setting. That's why use android:enabled="false"and A App trigger B app. But not working.
I think "android.intent.action.BOOT_COMPLETED" send just one time after booting, so after changing enable receiver B app, it's not working. Is it right?
Please can you give me some advise?
A App
PackageManager pm = getPackageManager();
ComponentName compName = new ComponentName("com.test.myapp", "com.test.myapp.receiver");
pm.setComponentEnabledSetting(compName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
B App AndoidManifest.xml
<receiver
android:name="com.test.myapp.receiver"
android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
B App
public void onReceive(Context context, Intent intent) {
if(Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())){
Intent startMainActivityIntent = new Intent(context, new.class);
startMainActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(startMainActivityIntent);
}
Why don't you just start app B from app A directly? Yes, boot completed triggered only once. But you can start app B without any receivers, look here for example
Related
I need to start a few services provided by other apps, let them execute whatever the want to execute, and kill them once they call me back and I receive the data collected. Sadly startService(serviceIntent); crashes with
Unable to start activity ComponentInfo{…}: java.lang.IllegalStateException: Not allowed to start service Intent {…}: app is in background uid UidRecord{70fcf01 u0a90 CEM bg:+1h49m29s56ms idle procs:1 seq(0,0,0)}
It appears that this is by design, here's the crashing AOSP code.
My code crashing looks like this:
final PackageManager pm = getPackageManager();
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory("my.special.service.CATEGORY");
List<ResolveInfo> results = pm.queryIntentServices(intent, PackageManager.GET_META_DATA);
for (ResolveInfo info : results) {
ComponentName name =
new ComponentName(info.serviceInfo.applicationInfo.packageName, info.serviceInfo.name);
Intent serviceIntent = new Intent();
serviceIntent.setComponent(name);
startService(serviceIntent); // 💥 K A B O O M
bindService(serviceIntent, boundServiceConnection, BIND_AUTO_CREATE);
}
The way service is defined in another app's Manifest.xml:
<service
android:name=".ServiceFromAnotherApp"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<categoy android:name="my.special.service.CATEGORY" />
</intent-filter>
</service>
Any ideas if there're any workarounds, maybe different architecture?
Core trait that I want to retain is:
to be able to create a service
tell it to fetch additional data (potentially several times during its lifecycle)
get callback from the service once it finishes every subsequence fetch
First of all, I have researched a lot about my issue, but I could not find a proper solution so I am posting my query here. Hope to get a better solution to the issue:
I have a requirement where I need to ask for password to the user before user deletes my app from settings or from any other application like MyAppSharer. I have found one solution where I can successfully be able to call my activity when user clicks on Uninstall button. I have applied trick here, and calling service. In service, I run timer which runs every 1 second and in that one second, it checks for top most activity of running task. This is running perfectly as per expected.
Now, my issue is, this activity apppears on each of application user tries to uninstall. I need that the activity which I call, should only appear for my application when user tries to uninstall my application.
Here is my code:
public static final String PACKAGE_INSTALLER = "com.android.packageinstaller";
public static final String PACKAGE_INSTALLER_UNINSTALL_ACTIVITY = "com.android.packageinstaller.UninstallerActivity";
alarmTimer.scheduleAtFixedRate(new TimerTask() {
public void run() {
mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);;
ComponentName topActivity = mActivityManager.getRunningTasks(1).get(0).topActivity;
final String packageName = topActivity.getPackageName();
String className = topActivity.getClassName();
Log.v(TAG, "packageName:" + packageName);
Log.v(TAG, "className:" + className);
if (PACKAGE_INSTALLER.equals(packageName)
&& PACKAGE_INSTALLER_UNINSTALL_ACTIVITY.equals(className)) {
//Here I need to apply one condition where package name received to be matched with my package name. But I am not sure how to fetch package name of selected application for uninstalling
//To Cancel Existing UninstallerActivity and redirect user to home.
Intent homeIntent = new Intent();
homeIntent.setAction(Intent.ACTION_MAIN);
homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
homeIntent.addCategory(Intent.CATEGORY_HOME);
startActivity(homeIntent);
//To open my activity
Intent loginActivity = new Intent(UninstallService.this, Act_Login.class);
loginActivity.putExtra(Constants.KEY_IS_FROM_SERVICE, true);
loginActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(loginActivity);
}
}
}, 0, 1000);
you should try something like the following :
1st - declare your broadcast recevier in the Manifest file , that will listen to QUERY_PACKAGE_RESTART :
<receiver android:name=".UninstallReceiver">
<intent-filter android:priority="999999">
<action android:name="android.intent.action.QUERY_PACKAGE_RESTART" />
<data android:scheme="package" />
</intent-filter>
</receiver>
2nd - your UnunstallIntentReceiver java class like the following :
public class UninstallReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
// fetching package names from extras
String[] packageNames = intent.getStringArrayExtra("android.intent.extra.PACKAGES");
if(packageNames!=null){
for(String packageName: packageNames){
if(packageName!=null && packageName.equals("application_package")){
// start your activity here and ask the user for the password
}
}
}
}
}
and please give me some feedback
Hope That Helps.
If this is a corporate requirement (if you want to block a regular user from uninstalling your app, no chance, thanks Google for protecting us from bad devs), you should create a device administrator application. This way, although the user still can delete the app, it's one extra step if you want to prevent accidental erasing.
Before deleting your app, if it's enabled as device admin, the user must first disable the app as administrator, and the app receives this broadcast.
In your XML, put
<activity android:name=".app.DeviceAdminSample"
android:label="#string/activity_sample_device_admin">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<receiver android:name=".app.DeviceAdminSample$DeviceAdminSampleReceiver"
android:label="#string/sample_device_admin"
android:description="#string/sample_device_admin_description"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data android:name="android.app.device_admin"
android:resource="#xml/device_admin_sample" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
In the receiver, you have at least two methods worth noticing:
#Override
public CharSequence onDisableRequested(Context context, Intent intent) {
…
}
#Override
public void onDisabled(Context context, Intent intent) {
…
}
This way you know the user is potentially going to erase your app.
Complete guide for device administration is at https://developer.android.com/guide/topics/admin/device-admin.html
If you have root permissions make your app system (remove your apk-file from /data to /system directories). Then reboot device. After reboot your app is not available to delete by user (not superuser).
The only way i see, is to provide your own uninstaller as part of your app (= an activity that lists all apps and allows to uninstall them). Your service could then check if your app was the one that started the packageinstaller and if not redirect the user.
It is not possible (at least on the Android 4.4 I tested with) to grab the uninstaller activity data without root or being a system app. This is because the uninstaller is not called as an independent task, but as an activity on the stack of the starting task (which is the Settings app when uninstalling from settings, etc). You can only see the Task details of the calling task.
However there might be some really dirty possibility left, that i didn't test to the end: You could register the hidden interface IThumbnailReceiver [1] with the hidden three argument version of ActivityManager.getRunningTasks [2]. It seems like only the GET_TASKS permission is needed to grab a thumbnail (see [3]). It should be possible to find out which app is going to be removed from the app thumbnail... - But as this solution uses hidden APIs, there is no guarantee that it will work with older/newer/vendored Android versions.
https://github.com/omnirom/android_frameworks_base/blob/android-4.4/core/java/android/app/IThumbnailReceiver.aidl
https://github.com/omnirom/android_frameworks_base/blob/android-4.4/core/java/android/app/ActivityManager.java#L766
https://github.com/omnirom/android_frameworks_base/blob/android-4.4/services/java/com/android/server/am/ActivityManagerService.java#L6725
I need my android app to be in background mode after a phone restart/power on.
Currently I am using the following code, so that my app successfully gets launched after a phone restart/power on.
AndroidManifest.xml:
<receiver android:enabled="true" android:name="my_package.BootUpReceiver" android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
BootUpReceiver.java:
public class BootUpReceiver extends BroadcastReceiver
{
private static SharedPreferences aSharedSettings;
#Override
public void onReceive(Context context, Intent intent)
{
aSharedSettings = context.getSharedPreferences("MyPreferences", Context.MODE_PRIVATE);
boolean isUserLoggedIn = aSharedSettings.getBoolean(Key.AUTHENTICATED, false);
if(isUserLoggedIn)
{
Intent aServiceIntent = new Intent(context, MyHomeView.class);
aServiceIntent.addCategory(Intent.CATEGORY_HOME);
aServiceIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(aServiceIntent);
}
}
}
As I said above, my app successfully gets launched after a phone restart/power on.
However, after the phone restart/power on, my app was in foreground mode. But I need my app to be in background mode.
Can anyone please say, how to make an app to be in background mode after a phone restart or power on.
I even tried by changing the intent category to
<category android:name="android.intent.category.HOME" />
But no use in it. Can anyone please help me?
Thanks.
I need my app to be just running in background after the phone restart, so that users can select from the minimized app
I think your approach is wrong. All you are trying to do now is to add icon of your app to recent apps list. Your app won't run in background and I think you don't really want it. Am I right?
Recent apps list managed by android and IMHO forcing your app to be in recent apps list is not a very good idea. User will start you app when he wants from launcher or icon on his desktop.
If your broadcast receiver is working fine and app is starting successfully then you can use the below code in your MyHomeView activity's onCreate method to go to the home screen.
Trick is to click HOME button programmatically when app starts.
Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
you can pass some variable from the BroadcastReceiver to differentiate a normal request and BroadcastReceiver's request to make the above code conditional.
But if you want to execute it always in background then it would be better to use Service.
It is recommended to change your code to the service to run it in background.
The suggestion which Leonidos replied is correct.
However, Just a workaround for this:
In my BootUpReceiver, I had a seperate boolean flag for this! (Its a bad way. but just a workaround)
SharedPreferences.Editor aPrefEditor = aSharedSettings.edit();
aPrefEditor.putBoolean(Key.IS_DEVICE_RESTARTED, true);
aPrefEditor.commit();
In Oncreate method of MyHomeView:
boolean isDeviceRestarted = aSharedSettings.getBoolean(Key.IS_DEVICE_RESTARTED, false);
if(isDeviceRestarted)
{
SharedPreferences.Editor aPrefEditor = aSharedSettings.edit();
aPrefEditor.putBoolean(MamaBearKey.IS_DEVICE_RESTARTED, false);
aPrefEditor.commit();
moveTaskToBack(true);
}
Thanks
I'm new to android and am trying to make an application that when the user presses a particular button in App A, he is sent to App B. The user can then come back to App A by pressing another button in App B. No content is transferred from one app to another.
I want to accomplish this by making custom intents for both the applications. How should I start with this? Also what exactly is Broadcastreceiver and do I need to use it for the above mentioned problem?
Thanks!
Switching between another Application can be by two ways that is
1.) If you know the MainActivity of the Application to Call, you use
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(new ComponentName(
"package_name","package_name.MainActivity"));
startActivity(intent);
2.) If you don't know the MainActivity to Call you just use PackageName, you use
Intent LaunchIntent = getPackageManager()
.getLaunchIntentForPackage("package_name");
startActivity(LaunchIntent);
I don't think you need a BroadCastReceiver here as it is what you use when you want to catch some event/action for eg- Low Battery. For further details check my answer here
See Code to launch external app explicitly (especially this answer). You'll have to create a custom intent for each of the applications, and then call that intent explicitly.
In App A Manifest:
<intent-filter>
<action android:name="com.mycompany.APP_A" />
</intent-filter>
In App B Manifest:
<intent-filter>
<action android:name="com.mycompany.APP_B" />
</intent-filter>
In App A Button Press:
Intent intent = new Intent();
intent.setAction("com.mycompany.APP_B");
startActivity(intent);
In App B Button Press:
Intent intent = new Intent();
intent.setAction("com.mycompany.APP_A");
startActivity(intent);
I want create an app that works like that:
When I take my device, I will unlock it and this app will be alredy opened. Then this app will show a compromise term of use the tablet. There will be two options, allow or refuse. If I choose allow, the app will finish; when I choose refuse, nothing happens until I choose allow.
Then, after I use my device, it will lock, then... I will unlock, and the app will be there again!
How can I put this app to auto-run when I unlock the device?
Add the receiver in menifest file
<receiver android:name=".ScreenReceiver">
<intent-filter>
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
</receiver>
Create a broadcast receiver which works to open app when phone is unlocked.
public class ScreenReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
System.out.println(intent.getAction());
if (intent.getAction().equals(Intent.ACTION_USER_PRESENT))
{
Intent intent1 = new Intent(context,MainActivity.class);
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent1);
}
}
Already asked, and answered: android unlock screen intent?
You'll need to listen for that intent and then you can launch your app.