I'm trying to run a thread by starting it with a service, but it won't start. It won't even log.
This is my inner service class. The service class creates a new background thread and starts it.
The backgroundthread and the service class are both innerclasses so they can reach the variables.
public class MyService extends Service {
private BackgroundThread background;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show();
Log.d(TAG, "onCreate");
background = new BackgroundThread();
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
Log.d(TAG, "onDestroy");
}
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, startId, startId);
Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
Log.d(TAG, "onStart");
background.start();
return startId;
}
}
I'm starting the service in the MainActivity by this:
startService(new Intent(this, MyService.class));
And this is my manifest:
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.antioversleepapp.MainActivity"
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.example.antioversleepapp.SettingsActivity"
android:label="#string/title_activity_settings" >
</activity>
<activity
android:name="com.example.antioversleepapp.InfoActivity"
android:label="#string/title_activity_info" >
</activity>
<service android:enabled="true" android:name="com.example.antioversleepapp.MyService" />
</application>
Please help me out
This is my inner service class
That is not possible. It either needs to be a static inner class (in which case, your <service> element also needs changing) or it needs to be a separate public class.
The backgroundthread and the service class are both innerclasses so they can reach the variables.
I do not see any "variables" that your service needs to "reach". Moreover, it is impossible for Android to create an instance of an inner class, since it does not have an instance of the outer class.
try this code in your start service button, I hope it works :
Intent intent = new Intent(MainActivity.this,Service.class);
MainActivity.this.startService(intent);
Related
I have a project which is only a service and it has no activity and user interface. I want to start my application background service when phone boot completely. but I never receive the "BOOT_COMPLETED" Message from OS. these are my code:
Manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.droid.arghaman.location_tracker">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<receiver android:name=".BootBroadcastReceiver"
android:enabled="true"
android:exported="false"
android:label="StartServiceAtBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
</receiver>
</application>
<service android:name=".mySevice"></service>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>
</manifest>
Broadcast Receiver:
public class BootBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("boot Received", intent.getAction());
Intent serviceLuncher = new Intent(context, myService.class);
context.startService(serviceLuncher);
}
}
myService:
public class LocationNotifierService extends Service {
Timer timer ;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate(){
timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
Toast.makeText(getBaseContext(),"Location",Toast.LENGTH_SHORT).show();
}
},3000);
}
#Override
public void onDestroy(){
}
#Override
public int onStartCommand(Intent intent, int flagId, int startId){
return START_STICKY;
}
}
but I never get "boot Received" log.
is there any mistake and is there any way to debug my program?
I Recommend that my project must have only this Service and it cannot have any UI.
I never receive the "BOOT_COMPLETED" Message from OS
Partly, that is because you do not have a <receiver> set up to receive android.intent.action.BOOT_COMPLETED broadcasts.
Partly, that is because your app will not receive broadcasts until something on the device uses an explicit Intent to start one of your components. The way your app is set up — without an activity that the user can run — it is unlikely that any app will do this, and so your code will never run.
Also, please bear in mind that Android O has changes designed specifically to prevent background services from running for very long and to limit your ability to get background location updates (which your location_tracker name suggests that you want to add in the future). You may wish to reconsider whether writing this app the way that you are is a wise course.
try this in your manifest
<receiver android:name=".BootBroadcastReceiver"
android:enabled="true"
android:exported="false"
android:label="StartServiceAtBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
I created a simple service example. When I start the service it uses 6.6MB or more. Some time later it increases automatically. I checked this link but found no solution. How can I confirm how much the RAM usage increased?
Service class
public class MyTestService extends Service {
public MyTestService() {
}
#Override
public void onCreate() {
super.onCreate();
Log.e("MyTestService", "onCreate");
}
#Override
public void onLowMemory() {
super.onLowMemory();
Log.e("MyTestService", "onLowMemory");
}
#Override
public IBinder onBind(Intent intent) {
Log.e("MyTestService", "onBind");
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("MyTestService", "onStartCommand");
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.e("MyTestService", "onDestroy");
}
}
Activity class where i only start & stop service
1. OnStartService
startService(new Intent(this, MyTestService.class));
2. OnStopService
stopService(new Intent(this, MyTestService.class));
Manifiest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.sample.service">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".ServiceCheckActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".MyTestService"
android:enabled="true"
android:exported="true"></service>
</application>
Memory usage usually increases because of lingering objects, which is not garbage collected yet, causing sawtooth - like plot in ddms. Android manages Service's lifecycle, so if it is empty, maybe you should not worry about it. For avoiding that consider using 'Flyweight' design pattern, if you need to create a lot of temporary objects.
I have a service. In the service, I will call a function in class. The function allows opening an Intent
My service is
public class service extends Service
{
private static final String TAG = "MyService";
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
public void onDestroy() {
Log.d(TAG, "onDestroy");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
return START_STICKY;
}
}
And my class is
public class classIntent extends Application{
public void homeIntent()
{
Intent intent1 = new Intent(Intent.ACTION_MAIN);
intent1.addCategory(Intent.CATEGORY_HOME);
intent1.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent1.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent1);
}
In the service, I will call homeIntent() function as follows steps:
In the onCreate() of the service, I will use
private classIntent cIntent;
#Override
public void onCreate() {
cIntent=new classIntent();
...}
Then in the onStartCommand() function, I used
cIntent.homeIntent();
However, I got the error such as:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.content.Context.startActivity(android.content.Intent)' on a null object reference
How can I solve it? Do I right when my class classIntent extended from Application? I want to use some functions in the class such as: getApplicationContext()...If not correct, which class do I need to extend? I am running the app in the background. Thank all
My manifest is
<application android:label="#string/app_name"
<activity android:name=".MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service android:enabled="true" android:name=".service" />
<activity android:enabled="true" android:name=".classIntent" />
</application>
You really not need to do this way, and it is very wrong.
Your class name code-style is not good, should be ClassName
<activity android:enabled="true" android:name=".classIntent" /> classIntent is not a Activity in you code.
you just need to:
use getApplication().startActivity() to do the work, getApplication() is a function Service, Activity has, if you only need the Application context, not some activities.
If you need to make code clear, I suggest a static makeIntent function you can put in your helper class or the class associate with the intent.
the code in Service only need call getApplication().startActivity(XXX.makeIntent())
I have an application that I would like to have automatically start following boot completion. The following code seems overly complicated and I get erratic application starts when swiping to a neighbouring workspace.
What am I missing here? I have an activity class, a service class, as well as a broadcast receiver. Below is my code (in that order) followed by the manifest.
public class BlueDoor extends Activity implements OnClickListener{
Button btnExit;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.main);
btnExit = (Button) this.findViewById(R.id.ExitButton);
btnExit.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.ExitButton:
System.exit(0);
break;
}
}
}
service.class
public class BlueDoorStartService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
callIntent.setClass(this, BlueDoor.class);
startActivity(callIntent);
// do something when the service is created
}
}
broadcast receiver
public class StartBlueDoorAtBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
Intent serviceIntent = new Intent(context, BlueDoorStartService.class);
context.startService(serviceIntent);
}
}
}
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.bluedoor"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver
android:name=".StartBlueDoorAtBootReceiver"
android:enabled="true"
android:exported="false" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service android:name=".BlueDoorStartService" >
</service>
<activity
android:name=".BlueDoor"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
UPDATE Solution(s), 10/22/2015:
Changing the service to:
public class BlueDoorStartService extends Service {
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
}
and the receiver to:
public class StartBlueDoorAtBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Start Service On Boot Start Up
Intent serviceIntent = new Intent(context, BlueDoorStartService.class);
context.startService(serviceIntent);
//Start App On Boot Start Up
Intent App = new Intent(context, BlueDoor.class);
App.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(App);
}
}
resulted in a working configuration using a service w/no misbehaving. However deleting the service all together and modifying the receiver thus:
public class StartBlueDoorAtBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent App = new Intent(context, BlueDoor.class);
App.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(App);
}
}
also resulted in a functional as well as a more concise configuration that starts the application following boot completion.
Your BroadcastReceiver calls
context.startService(serviceIntent)
so the service will be created if it doesn't exist yet (which will be the case shortly after booting) and thus start the activity from its onCreate() method. So the app works, to a certain extent.
BUT when you call startService(), the system always calls the service's onStartCommand() method. You did not override that method, so the system uses the standard implementation from class android.app.Service.
As you can read on grepcode.com, the method will return a value like START_STICKY by default. This tells the system to keep the service alive until it is explicitly stopped.
In your case, I suppose the system reacted to the swiping by temporarily killing and then reanimating (= creating) the service, which in turn started your activity.
Some information on the service lifecycle can be found here.
What you can do:
Override onStartCommand() to start the activity from there instead of from onCreate(). Then use stopSelf(int) like described here
One last thing: when exiting from the activity, don't use System.exit(0) but call finish() instead, see this SO answer for "why".
I've the same issue described here but i can't understand whats wrong.
My issue is: Unable to start service Intent { act=.connections.MoodyService } U=0: not found
EDIT
I've changed my package from connections to service in the source code, sorry for the confusion
My manifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.moody"
android:installLocation="auto"
android:versionCode="0"
android:versionName="0.6.7 alpha" >
<uses-sdk
android:maxSdkVersion="18"
android:minSdkVersion="14"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:allowClearUserData="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="activities.MainActivity"
android:label="#string/app_name" >
</activity>
<activity
android:name="activities.Menu_esq"
android:label="#string/title_activity_menu_esq" >
</activity>
<activity
android:name="activities.BaseActivity"
android:label="#string/title_activity_base" >
</activity>
<activity
android:name="activities.MainView"
android:label="#string/title_activity_main_view" >
</activity>
<activity
android:name="activities.LoginActivity"
android:label="#string/app_name"
android:noHistory="true"
android:windowSoftInputMode="adjustResize|stateVisible" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.example.moody.LeftActivity"
android:label="#string/title_activity_left" >
</activity>
<activity
android:name="com.example.moody.RightActivity"
android:label="#string/title_activity_right" >
</activity>
<activity
android:name="activities.UserDetailsActivity"
android:label="#string/title_activity_user_details" >
</activity>
<activity
android:name="fragments.TopicsPreview"
android:label="#string/title_activity_copy_of_topics_preview" >
</activity>
<activity android:name="activities.Loading" >
</activity>
<service
android:name=".service.MoodyService"
android:icon="#drawable/ic_launcher"
android:label="#string/moody_service" >
</service>
</application>
service is the package and MoodyService is the class name
My service class
public class MoodyService extends Service {
public MoodyService() {
// TODO Auto-generated constructor stub
}
private boolean isRunning = false;
Object getContent;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
// Announcement about starting
Toast.makeText(this, "Starting the Demo Service", Toast.LENGTH_SHORT)
.show();
// Start a Background thread
isRunning = true;
Thread backgroundThread = new Thread(new BackgroundThread());
backgroundThread.start();
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
// Stop the Background thread
isRunning = false;
// Announcement about stopping
Toast.makeText(this, "Stopping the Demo Service", Toast.LENGTH_SHORT)
.show();
}
private class BackgroundThread implements Runnable {
int counter = 0;
public void run() {
try {
counter = 0;
while (isRunning) {
System.out.println("" + counter++);
new Contents().getAll(getResources(),
getApplicationContext());
Thread.currentThread().sleep(5000);
}
System.out.println("Background Thread is finished.........");
} catch (Exception e) {
e.printStackTrace();
}
}
}
And in my main Intent.
Intent start = new Intent(".service.MoodyService");
this.startService(start);
and also tried
Intent intent = new Intent(this, MoodyService.class);
this.startService(intent);
and tried with the full path
<service
android:name="com.example.moody.service.MoodyService"
android:icon="#drawable/ic_launcher"
android:label="#string/moody_service" >
Solved
I deleted the period in the beginning of the package name in the manifest and it worked, in another words:
This doesn't work:
.yourPackage.YourClass
But this does work:
yourPackage.YourClass
And in the main:
Intent intent = new Intent(this, MoodyService.class);
this.startService(intent);
But it goes against what is written in the documentation:
android:name The name of the Service subclass that implements the service. This should be a fully qualified class name (such as,
"com.example.project.RoomService"). However, as a shorthand, if the
first character of the name is a period (for example, ".RoomService"),
it is appended to the package name specified in the
element. Once you publish your application, you should not change this
name (unless you've set android:exported="false").
There is no default. The name must be specified.
The service must be also be included in the Manifest:
<service android:name="com.x.x.serviceclass"></service>
Make sure you have declared your service in the manifest file.
<service
android:name=".MyService"
android:enabled="true" >
</service>
and try writing getApplicationContext() instead of "this" keyword
startService(new Intent(getApplicationContext(), MoodyService.class));
I don't know why you are using that package-like name for your service name, but why don't you use class name for starting the service?
Intent intent = new Intent(context, YourService.class);
context.startService(intent);
I think in manifest package name for service is wrong as you said your package name is connections so it should be like this
android:name ="connections.MoodyService"
or
android:name="com.example.moody.connections.MoodyService"
to invoke service do
Intent intent = new Intent(this, MoodyService.class);
this.startService(intent);
my service is in "service" package and my manifest service enrty like this;
<service
android:name="service.TimerService"
android:exported="false" >
</service>
Did you create an empty constructor in the service?
If not, try that.
Also uncertain if you can use the Intent like that. You could try the 'new Inten(this, MoodyService.class)' construction.
Did you try to use the android:name that you specified in the Manifest?
Android Manifest:
<service
android:enabled="true"
android:name="UploadService" />
The call would be sth like this:
Intent intent = new Intent("UploadService");