I have a basic Android application that is supposed to reboot the phone continuously a set number of times. In order to do this, I need the application to be started upon phone startup. In order to that, I essentially followed the instructions found here, adding the permissions to the manifest and creating a BroadcastReceiver class that starts the activity. Here is some of my relevant code:
public class StartMyServiceAtBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("StartMyServiceAtBootReceiver called.");
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
// Intent activityIntent = new Intent("com.example.rebooter.MainActivity");
Intent activityIntent = new Intent(context,MainActivity.class);
activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(activityIntent);
}
}
}
From the manifest file:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.rebooter"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</activity>
<service
android:name=".RebootManager"
android:label="Reboot Manager" >
<action android:name="com.example.rebooter.RebootManager" />
</service>
<receiver android:name=".StartMyServiceAtBootReceiver"
android:enabled="true"
android:exported="true"
android:label="StartMyServiceAtBootReceiver" >
<action android:name="android.intent.action.BOOT_COMPLETED" />
</receiver>
</application>
In the Eclipse emulator, the application appears to be working properly. That is, though my emulator isn't rooted and the phone doesn't execute the reboot commands correctly, I do see that, upon startup, the correct activity is started.
Now, when I'm trying it on a particular system running Android 4.0.4, everything in the application is working properly EXCEPT boot upon startup. Any ideas?
I tried to eliminate the possibility of any hardware problems (since I'm not using a commercially-released phone) by installing another application that boots upon startup and confirming that it does indeed boot upon startup, and it does indeed show up under running apps as a cached process after startup.
I would appreciate any help. Let me know if you need any additional information.
There are a number of issues here.
First, you neglected to post StartMyServiceAtBootReceiver, the component you are expecting to get control at boot time, so we cannot comment on whether there are any particular problems with it.
Second, unless something has explicitly executed one of your components (e.g., the user launched MainActivity from the home screen), StartMyServiceAtBootReceiver will never be invoked, on Android 3.1+. Make sure you run your activity before trying a reboot, and see if that helps.
Third, you implemented a constructor on StartupManager, which is a bad idea. Please move this logic to onCreate().
Fourth, your code will likely crash in that constructor, as getApplication() will not return a valid value at this point in the code, particularly since you failed to chain to the superclass' constructor. Again, moving this code to onCreate() will help here.
Fifth, starting an activity from onCreate() of a service (let alone its constructor) is very unusual and may not be appreciated by the user. Moreover, if that service is not doing anything else, you could just as easily start that activity from StartMyServiceAtBootReceiver and skip StartupManager entirely.
Sixth, you have <intent-filter> elements on your services, as if you are expecting third party developers to invoke those services. If that is the case, fine. If not, please remove the <intent-filter> elements and use explicit Intents within the rest of your app code to refer to them (e.g., new Intent(this, StartupManager.class)), for better security. Or, add android:exported="false" to those services, though that is automatic if you remove the <intent-filter> elements.
Related
I have a simple React Native app, with a single activity MainActivity. The app is meant to be used for an online orders system, so it's meant to be "on" all the time. When the app receives a notification I want to open the app if killed, and bring to the foreground if in background. I have made this work in the past with the example code below but it doesn't work anymore, I don't know if it's an Android API change or what. Please also note I'm not an Android developer so bear that in mind.
I'm using OneSignal and here is my notification received handler:
public class SignalReceiver implements OneSignal.OSRemoteNotificationReceivedHandler {
#Override
public void remoteNotificationReceived(Context context, OSNotificationReceivedEvent notification) {
Intent intent = new Intent(context, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
context.startActivity(intent);
Log.d("ONESIGNAL", "OPENED??");
}
}
and this is my AndroidManifest.xml excerpt. The only relevant part should be the <meta-data> tag as that was added as per OneSignal documentation, but pasting other parts in case relevant:
<application
android:name=".MainApplication"
android:label="#string/app_name"
android:icon="#mipmap/ic_launcher"
android:roundIcon="#mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:launchMode="singleTop"
android:windowSoftInputMode="adjustResize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="com.onesignal.NotificationServiceExtension"
android:value="com.packagename.SignalReceiver"
/>
</application>
The log message display in Logcat in Android Studio so the code is running all fine. I also get a notification 30 seconds after the log shows, so that is also very odd!
I have noticed com.onesignal.NotificationServiceExtension doesn't actually exist if I try to import in code, but I don't know if it's meant to.
Can someone see any problem with my code, and if yes how can I get it to bring the app to foreground?
Edit
I've tried this code in Android versions 11 and 12 on Samsung devices. Standard devices, not kiosk or managed.
I also just noticed if the app has been closed for a few minutes (over 5 minutes) then the app does indeed open up. But not if it's been used recently.
I have developed application to start app on boot, but it is working on rooted devices only some of code as below.
permission and receiver in AndroidManifest.xml file is given below.
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<receiver android:enabled="true" android:name="in.com.appname.StartAppAtBootReceiver"
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>
below are the class to receive on boot.
public class StartAppAtBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent myIntent = new Intent(context, MainActivity.class);
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myIntent);
}
}
my question is that this code will work with non rooted devices?
if yes then what is missing because same app is working with rooted devices.
This must work without root.
Else try to use a simple tutorial like: Android AutoStart App after boot
Differences:
Check which action occurs.
Use startService instead of startActivity
Another tip: Set permissions in top of manifest, and receiver in application-part.
This should work without root.
There are a couple of things to notice:
app must be started at least once before it can receive BOOT_COMPLETED
if app is force closed, it will lose it ability to receive BOOT_COMPLETED until next launch.
Also, permission should be at the root of manifest and not inside application:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.x.y" >
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
.
.
.
make sure you are not running in above situations.
Well honestly, they aren't doing anything at all. Let me start by saying that I know that Android reworked receivers in 3.1, specifically boot control. I know that they made it so that ACTION_BOOT_COMPLETED cannot be used unless the application has been previously launched by the user. However, people have been successful in using them in current application, yet I am never hitting my receivers for my BOOT_COMPLETED or my SHUTDOWN.
Quick Edit - Please look at the bottom of this post for corrected Shutdown Receiver, I have gotten it to work and am now just stuck in my efforts to get BOOT_COMPLETED to work.
My manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.smashingboxes.speedblock"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="12"
android:targetSdkVersion="18" />
<!-- PERMISSIONS -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
...
<!-- RECEIVERS -->
<receiver android:name=".BootReceiver"
android:enabled="true" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name=".ShutdownReceiver" >
<intent-filter>
<action android:name="android.intent.action.SHUTDOWN" />
</intent-filter>
</receiver>
Now my implemented receiver classes are fairly straight forward:
BOOT_COMPLETED Receiver (the one that isn't working)
public class BootReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context c, Intent i) {
Intent starterIntent = new Intent(c, LaunchActivity.class);
// Start the activity (by utilizing the passed context)
starterIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
c.getApplicationContext().startService(starterIntent);
}
}
I have tried different things based on what I have seen as far as solutions, such as altering my launching activity to include
/* May need this, as of 3.1 we can't call BOOT_COMPLETED until the app has been run successfully */
Intent intent = new Intent("com.smashingboxes.speedblock.intent");
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
this.sendBroadcast(intent);
or including this in my boot receiver intent-filter in my manifest
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
Nothing seems to work. When Logs are inserted into my receiver methods they are never hit. Apparently people are still using these two receivers fairly regularly, which is why I am having trouble understanding why neither of them work. Have I missed something with my registration or something?
--EDIT--
I have solved the problem with my shutdown receiver. First, I foolishly forgot the ACTION_ portion of the tag. Secondly, HTC has separate shutdown methods, in my case I needed to add an intent-filter to my Receiver request:
<receiver android:name=".ShutdownReceiver" >
<intent-filter>
<action android:name="android.intent.action.ACTION_SHUTDOWN" />
<action android:name="android.intent.action.QUICKBOOT_POWEROFF" />
</intent-filter>
</receiver>
Now my Shutdown Receiver works, still no luck on the Boot Completed Receiver though.
I found the answer and I think that it is actually important to note, as it seems like an issue others will run into at some point. My issue was that I was launching a "Launcher Activity" called just that, LauncherActivity. Basically, it acted as my gateway to start up services, receivers, and such when the application was launched. It is a very simple Activity class:
public class LaunchActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
/* May need this, as of 3.1 we can't call BOOT_COMPLETED until the app has been run successfully */
Intent intent = new Intent("com.smashingboxes.speedapp.intent");
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
this.sendBroadcast(intent);
}
#Override
protected void onStart(){
super.onStart();
Intent serviceIntent = new Intent(this, MainService.class);
startService(serviceIntent);
// NOTE: It is VERY, VERY important that we DO NOT finish this activity.
// If we do, our BootReceiver will no longer receive its broadcast and
// we won't auto-start on boot
//finish();
}
}
Note that I was calling finish() on the LaunchActivity. The problem with this is that it seemed to tell Android that the application was in the stopped state, meaning that it won't allow the reception of the BOOT_COMPLETED broadcast, even though I had a number of services running in the background. The LauncherActivity MUST stay active throughout the entire life-cycle or the BOOT_COMPLETED receiver becomes useless. Something that I haven't really seen mentioned before, but again something I think is worth noting.
Hi I am working on soft keyboard.
I am getting exception of permission when I am accessing my service
class from my simple activity class.
Stack Trace of exception is shown below,
In above image InputServiceMethod class = Underlined by Green color.
Activity class = Underlined by Blue color.
I am getting this exception when I am calling InputServiceMethod class
from activity class.
For this I used the below code which gives me exception,
Intent intent = new Intent(v.getContext(),SoftKeyboard.class);
startService(intent);
finish();
My manifest file as shown below,
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.softkeyboard"
android:installLocation="preferExternal">
<uses-permission android:name="android.permission.VIBRATE" />
<!-- <permission android:name="android.permission.BIND_INPUT_SERVICE" -->
<!-- android:exported="true"></permission> -->
<application android:label="#string/ime_name">
<service
android:name="com.example.android.softkeyboard.SoftKeyboard"
android:permission="android.permission.BIND_INPUT_METHOD"
android:exported="true">
<intent-filter>
<action android:name="android.view.InputMethod" />
</intent-filter>
<meta-data
android:name="android.view.im"
android:resource="#xml/method" />
</service>
<activity
android:name="com.configuration.Configuration"
android:label="#string/title_activity_configuration" >
</activity>
</application>
I don't understand as even if I give permission about BIND_INPUT_METHOD it is throwing exception.
How to fix it? Thanks
It looks like you are binding service to action android.view.InputMethod while it is protected by permission android.permission.BIND_INPUT_METHOD which is used to ensure that only the system can bind to it by its protection level. So According to Android you can only define the keyboard handling service but can't call it explicitly, it will be called automatically by system whenever a input method is required. So there are two ways to solve it:
1. Let it be called by system, don't call it explicit, or
2. Sign your application with system's signature you are running on, which makes your application platform dependent. (Not advised if your building generic application).
Hope you understand the situation.
The permission you are using i.e:
permission about BIND_INPUT_METHOD
is only for system apps and mostly will work only on rooted devices,
it wont accept on unrooted devices.
I bet it's repeated question but I need to ask it again. Service cannot start even I've put following code
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver android:name=".MyBroadcastreceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<activity
android:name="com.im.HomeActivity"
android:clearTaskOnLaunch="true"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.im.ListActivity"
android:label="#string/title_activity_list" >
</activity>
<service
android:name="com.im.SyncService"
android:process=":remote" >
</service>
</application>
and
public class MyBroadcastreceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent arg1) {
Intent intent = new Intent(context, SyncService.class);
context.startService(intent);
Log.i("Autostart", "started");
}
}
Help me, please.
Is your BraodcastReciever getting invoked?
if not then the reason could be following:
Starting with 3.1 when applications are installed they are in a
“stopped” state so they will not be able to run until the user
explicitly launches them. Pressing Force Stop will return them to this
state.
once the user runs the app for the first time (and does not Force Stop
it), everything behaves as before — a reboot will cause BOOT_COMPLETED
broadcasts to be received and so on. However, if the user installs the
app, until and unless they run the app manually, no broadcasts will be
received.
So in your case you will have to create launcher activity and make sure you start that launcher activity at least once then you will start receive boot event broadcast.
Source
Starting from Android 3.1, a user must start the application at least once before your application can receive android.intent.action.BOOT_COMPLETED events.
Also android:allowBackup="true" is set in your manifest file, make sure the App is not installed on the SD card. If you are saving to external storage, you will need to setandroid.intent.action.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE instead.
On some phones(like HTC) there is a Fast Boot option, If it is activated, The BOOT_COMPLETE will not be invoked.
Another approach would be to use Intent.ACTION_SCREEN_ON and check if service is running, if it isn't, then start the service. More info available here