Hi all i did research more than a lot but no one give me the right answer .
I am surprised because my question is so simple ,but didn't found a single solution.
I found a lots of question like mine but people making their answer round and round ,i am really sick of this now this is my last and final try
i will appreciate if any of you resolve it
Let me light up mu Question again in Brief:
i just want to make a simple service which hear the power button (really so simple) ,Now i did that easy thing , i mean i made a service with a broadcast receiver ok (Quite Simple) , and it run well , But!!! whenever i kill the app from background task , then the service stopped automatically , what i want here , that killing the task do not effect my service (how simple is this)
(Note: 1. i already used START_STICKY and Service.START_STICKY
2.Also i did a bad thing that is is called service in onDestroy.
But Still got thumbs down.
)
Please give me a fine solution
I will only appreciate after answer
(Because i am really so sick of this )
Here is my Code
MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(this, MyService.class));
}
MyService:
public class MyService extends Service {
private BroadcastReceiver mReceiver = null;
public MyService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
#Override
public void onCreate() {
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
mReceiver = new ScreenReceiver();
registerReceiver(mReceiver, filter);
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
ScreenReceiver:
public class ScreenReceiver extends BroadcastReceiver {
public static boolean wasScreenOn = true;
#Override
public void onReceive(final Context context, final Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
Log.e("LightWriter", "I WORK BRO.");
wasScreenOn = false;
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
Log.e("LightWriter", "I WORK BRO.");
wasScreenOn = true;
}
}}
I am felling so dumb about this , hey i got the answer
1. Those who think that its not possible are wrong
i just try with other device and it works well
the issue with my device is i have marshmallow , so if any one have it allow permission from permission manager (works fine ).
Thanks for your time:)
Related
I am building a game where I want the user to go through many activities in 20 seconds. Once the 20 seconds is over, I want to send the user to the GameOver screen. To run the timer in the background, I used a service. The issue is, the service doesn't seem to be running?
The weird thing is, that even the toast isn't showing. Here is the place where I call the service:
Here is the manifest:
Please let me know as to why the service or the timer aren't running. Thank you so much for all of your help, I really appreciate it! If you need any more code, just let me know and I will show you. Thanks!
:-)
{Rich}
Services can't interact with UI, which is what Toast does. If you want to do that, try using runOnUIThread along with getApplicationContext or the fancy way with binding/callbacks. Also, take a look at AlarmManager, might be a simpler solution instead of running a service.
BroadcastReciever should be a solution to get and to show the toasts. Just send the message from service and catch it in activity. Then use it wherever you want.
//Service class
final static String ACTION = "ACTION";
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
intent = new Intent();
intent.setAction(ACTION);
intent.putExtra("StartToast", "Started!");
sendBroadcast(intent);
return START_STICKY;
}
//Activity class
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent = new Intent(MainActivity.this, ServiceClass.class);
myReceiver = new MyReceiver();
intentFilter = new IntentFilter();
intentFilter.addAction(ServiceClass.ACTION);
registerReceiver(myReceiver, intentFilter);
}
private class MyReceiver extends BroadcastReceiver {
public String startToast;
#Override
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
startToast = arg1.getStringExtra("StartedToast");
Toast.makeText(MainActivity.this, startToast, Toast.LENGTH_SHORT).show();
}
Once you register this receiver, you get the message and create a toast automatically when you send data with intent.putExtra(....); .
I am implementing in my Android app a splash screen which:
dowloads a sqlite database from a server
loads urls to get JSONs
creates a sqlite database in the device and execute several queries
I am using AsyncTask to do everything, my problem will occur if the user close the app in the middle of the process or turn off the device because the app:
could be creating a database or executing crucial queries in the device
could be downloading the sqlite db from a server
could be running several important process
etc
Definitely, the entire process (3-5 seconds) is important.
So... How could I avoid this? should I use handlers, loaders, on-(pause, stop, destroy) methods in order to get my objective? Can you give me an example?
As mentioned in the comment above, you should use a service as their lifecycle is separate to that of the activity.
Create the service like so:
public class MyService extends Service {
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Do everything you need to here, then call stop:
Log.d("DEBUG", "Started...");
stopSelf();
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
Intent intent = new Intent("com.example.androidexample.SERVICE_STOPPING");
sendBroadcast(intent);
super.onDestroy();
}
}
Then in the activity:
public class MainActivity extends Activity {
private ServiceCompleteReceiver receiver;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter filter;
receiver = new ServiceCompleteReceiver();
filter = new IntentFilter("com.example.androidexample.SERVICE_STOPPING");
startService(new Intent(this, MyService.class));
registerReceiver(receiver, filter);
}
public class ServiceCompleteReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Do whatever needs to be done here
unregisterReceiver(receiver);
}
}
}
EDIT :
Don't forget to add it to your manifest as well
<service
android:name="com.example.androidexample.MyService"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
</service>
I've got a Service in my Android application. During onStartCommand, I pass the Service object to another class. Then, from there, there's a thread that after 30 seconds starts another Service. It is something like this:
public class FooService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
MyClass mc = new MyClass(this);
mc.testMethod();
stopSelf();
return START_NOT_STICKY;
}
}
And this is MyClass:
public class MyClass {
private Service service;
public MyClass(Service service) {
this.service = service;
}
public void testMethod() {
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(20*1000);
Intent intent = new Intent(service, BarService.class);
service.startService(intent);
}
catch (Exception e) {
// CATCH!
}
}
}).start();
}
}
Now, as you can see, in FooService I call stopSelf() wich destroys that Service object. By the way MyClass has got a copy of that Service that was passed by value. After 20 seconds, we can start BarService from MyClass. I've tested it and it works but I can't understand why! The way I wrote the code is dirty (for me). Is it correct to start another service from one that was destroyed? Thank you for your help.
I've tested it and it works but I can't understand why
It works today on the environments you tested in. It may not work in all environments (e.g., ROM mods) and may not work tomorrow (e.g., Android OS updates). A destroyed Context, such as your stopped service, should not be used for anything. It happens that presently you can still use it to call startService() later, but that behavior is not guaranteed.
Is it correct to start another service from one that was destroyed?
No. In this case, I fail to see why you need two services in the first place.
I've got a copy of that service
No, you do not.
I have a simple widget that does some calculations once the screen comes on and displays them and clears all the fields once the screen goes off ... i have a broadcast receiver setup in my service which listens to ACTION_SCREEN_ON and ACTION_SCREEN_OFF.
This works perfectly as long as the phone doesn't go to sleep for a long period of time or there is heavy usage of the phone - once this happens my widget process is killed (the service is still running but the process is killed) after this when the screen goes off and comes back on my widget doesn't update as the ACTION_SCREEN_ON intent is not caught by my service :(
public class CDTservice extends Service {
#Override
public void onCreate() {
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
m_receiver = new ScreenBroadcastReceiver();
registerReceiver(m_receiver, filter);
Log.d("Widgettool", "works");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
start();
Toast.makeText(getBaseContext(), "SERVICE ON", Toast.LENGTH_SHORT).show();
return START_REDELIVER_INTENT;
}
#Override
public void onDestroy() {
stop();
unregisterReceiver(m_receiver);
}
public void start()
{
RemoteViews View = new RemoteViews(this.getPackageName(), R.layout.main);
updatewidgetclass x= new updatewidgetclass(this, View, widgetId);
x.start(); // does calculations and displays on widget
}
public void stop()
{
RemoteViews Viewclear = new RemoteViews(this.getPackageName(), R.layout.main);
updatewidgetclass y = new updatewidgetclass(this, Viewclear, widgetId);
y.stop(); // clears resources and stops
}
private class ScreenBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
Log.d("ON SCREEN ON", "might hang here");
start();
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
stop();
}
}
}
sometimes when the widget process is not claimed by the android system the widget works perfectly for days and perfectly displays the values ACTION_SCREEN_ON
the problem arises when - i check in settings>apps>running - i can see my widget name and it says 0 processes and 1 service
i assume the broadcast receive is happening on the main process and hence its not receiving it when the process gets killed.
I have a work around in place for this but would really like to fix the issue.
Any helps is highly appreciated
I agree with #CommonsWare that having a service running in the bg at all times just to detect when the screen turns on and off is a very bad idea. Do you really need ACTION_SCREEN_ON, or will ACTION_USER_PRESENT (phone unlocked) suffice? This way, you do not need a service at all, and you can just define the receiver in the manifest.
If you really wanted to, you could register your service/ACTION_SCREEN_OFFreceiver in your ACTION_USER_PRESENT receiver so that the service is only running when the user is actually using the device.
I know this doesn't really answer your question, but it does provide a useful workaround to your problem.
So I have a small little app which downloads a very small amount of data from the net. Everything else works just fine and downloads properly, but when connection changes (I lose wifi range) the download won't complete and the user doesn't get their data.
I have an idea how to handle this. I set up a BroadcastReceiver on my main Activity which communicates with my IntentService. When the IntentService completes the download, I then unregister the receiver. To top all this, I set up a Broadcastreceiver to listen connectivity changes and if connection is available, and if there is a connection, the main activity sends an Intent to start the download. See here:
Main Activity:
public class Sample extends Activity {
private BroadcastReceiver connectivityReceiver;
private ResponseReceiver receiver;
protected void onCreate(Bundle sis){
super.onCreate(sis);
IntentFilter intentFilter = new IntentFilter(
"android.net.conn.CONNECTIVITY_CHANGE");
registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
if (Network.isOnline()) {
fireUpDownloadingIntent();
}
}
}, intentFilter);
}
public class ResponseReceiver extends BroadcastReceiver {
public static final String ACTION_RESP = "com.irough.intent.action.URL_LOADED";
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getBooleanExtra(DLService.DOWNLOAD_COMPLETE, false) {
unRegisterReceiver(connectivityReceiver);
}
}
}
}
DLService.java:
public class DLService extends IntentService {
public static final String DOWNLOAD_COMPLETE = "dlc";
public DLService() {
super("DLService");
}
#Override
protected void onHandleIntent(Intent intent) {
Intent broadcastIntent = new Intent();
broadcastIntent.setAction(ResponseReceiver.ACTION_RESP);
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
broadcastIntent.putExtra(DOWNLOAD_COMPLETE, true);
sendBroadcast(broadcastIntent);
}
}
The code about should work just fine, but is there an easier or better way to do it? Doesn't have to be done on Service, Asynctask force closes on me when connection drops and that's why put the download action to a service.
If you lose the connection in your download, I imagine your download will throw some sort of exception. If I were, I'd simply notify the user (using the android notification api), and give them the option to try to redownload the data.
Preferably though, (and contrary to my previous post in a similar question), you could use my new favorite class in the android, the AsyncTaskLoader. It sounds like it exactly fits the bill for what you want to do here. Bascially, if there's an error downloading, just have your loader return null. Then in your onLoaderFinished hook in your activity, do what ever you need to do in regards to informing the user. Note that this class is only available to API levels 3 and above, but can still be accessed by lower API levels through the android compatibility package.