I want to show image. where I have to perform operations in service and display result in UI. I don't want to use async task as per requirment. I don't know how to proceed and display image. Please help me.
My code has follows:
public class Service_Photo extends Service {
public Service_Photo() {
}
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "The new Service was Created", Toast.LENGTH_LONG).show();
}
#Override
public void onStart(Intent intent, int startId) {
// For time consuming an long tasks you can launch a new thread here...
Toast.makeText(this, " Service Started", Toast.LENGTH_LONG).show();
updateImages();
}
private void updateImages()
{
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
String fileName = "am/a.jpg";
File f = new File(baseDir + File.separator + fileName);
if(f.exists()){
Bitmap myBitmap = BitmapFactory.decodeFile(f.getAbsolutePath());
// img = (ImageView)findViewById(R.id.image);
// img.setImageBitmap(myBitmap);
Toast.makeText(getApplicationContext(), "Hello"+myBitmap.toString(), Toast.LENGTH_SHORT)
.show();
}
}
#Override
public void onDestroy() {
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
}
public class ImageDisplay extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//how to display the operation performed in service and display in image from service?
}
}
The best solution in your case is to use broadcast receivers. So in your activity
BroadcastReceiver mReceiver = new BroadcastReceiver(onReceive(Context context, Intent intent)
{
if(intent.getAction().equals("your_load_photo_action"))
{
ImageDisplay.this.runOnUiThread(new Runnable() {
#Override
public void run() {
view.setImageBitmap("YourImage");
}
});
}
});
#Override
public void onResume()
{
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver,
new IntentFilter("your_load_photo_action"));
}
#Override
public void onPause()
{
LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
}
and on your onCreate() initialize your view
And in your service, in updateImages()
Just send broadcast an intent with the action "your_load_photo_action"
Related
I am trying to create a service class with a inner class which is a Handler class , unfortunately I am not able to access handler.obtainMessage() in this class .. Can any one give suggestions on this ?
Source code for the Service class:
public class MyService extends Service {
private MyHandler myHandler;
private final class MyHandler extends Handler {
public MyHandler(Looper looper) {
super(looper);
}
public void handleMessage(Message msg) {
try {
Thread.sleep(5000);
// use the unique startId so you don't stop the
// service while processing other requests
stopSelfResult(msg.arg1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public void close() {
}
#Override
public void flush() {
}
#Override
public void publish(LogRecord record) {
}
}
#Override
public void onCreate() {
Toast.makeText(this, "Service Created", Toast.LENGTH_SHORT).show();
// Create a new HandlerThread with a specified priority
HandlerThread thread = new HandlerThread("MyHandlerThread",Thread.NORM_PRIORITY);
// Start the handler thread so that our Handler queue will start
// processing messages
thread.start();
// Run the handler using the new HandlerThread
myHandler = new MyHandler(thread.getLooper());
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Message msg = myHandler.obtainMessage();
msg.arg1 = startId;
myHandler.sendMessage(msg);
return START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onDestroy() {
Toast.makeText(this, "Service Done", Toast.LENGTH_SHORT).show();
}
}
You've got the wrong Handler class imported. It should be android.os.Handler, not java.util.logging.Handler.
I run the code and get the following result, but I hope that the App can run at the order "A" -> "Service OnDestroy" -> "B" -> "C", how can I do ?
In My Way 2 section, I try to place the code into the function new Handler().postDelayed(new Runnable() {}, it's OK , it ran at the order "A" -> "Service OnDestroy" ->"B" ->"C",
I don't konw why the way can success, I don't know if the way is good way!
Result
11-13 10:04:32.137 27947-27947/info.dodata.screenrecorder E/My﹕ A
11-13 10:04:32.147 27947-27947/info.dodata.screenrecorder E/My﹕ B
11-13 10:04:32.157 27947-27947/info.dodata.screenrecorder E/My﹕ C
11-13 10:04:32.157 27947-27947/info.dodata.screenrecorder E/My﹕ Service OnDestroy
UIAbou.cs
public class UIAbout extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_about);
Intent intent1 = new Intent(UIAbout.this,bll.RecordService.class);
startService(intent1);
Button btnReturn = (Button) findViewById(R.id.btnReturn);
btnReturn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.e("My", "A");
Intent intent1 = new Intent(UIAbout.this,bll.RecordService.class);
stopService(intent1);
Log.e("My", "B");
Toast.makeText(getApplicationContext(), "OK", Toast.LENGTH_LONG).show();
Log.e("My", "C");
}
});
}
}
RecordService.cs
public class RecordService extends Service {
private Context mContext;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate(){
}
#Override
public void onDestroy(){
Log.e("My","Service OnDestroy");
super.onDestroy(); //It seems that the APP is OK if I remove this.
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent,flags,startId);
}
}
=======================My Way 1 ======================================
I set a mark isServiceStoped to monitor if Stop Service is finished, but my app is hang up after disply the result "11-13 11:31:23.107 7599-7599/info.dodata.screenrecorder E/My﹕ A"
New UIAbout.cs
public class UIAbout extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_about);
Intent intent1 = new Intent(UIAbout.this,bll.RecordService.class);
startService(intent1);
Button btnReturn = (Button) findViewById(R.id.btnReturn);
btnReturn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.e("My", "A");
Intent intent1 = new Intent(UIAbout.this, bll.RecordService.class);
stopService(intent1);
while (RecordService.isServiceStoped==false){
//It block
}
Log.e("My", "B");
Toast.makeText(getApplicationContext(), "OK", Toast.LENGTH_LONG).show();
Log.e("My", "C");
}
});
}
}
New RecordService.cs
public class RecordService extends Service {
public static boolean isServiceStoped=true;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate(){
}
#Override
public void onDestroy(){
Log.e("My", "Service OnDestroy");
isServiceStoped=true;
super.onDestroy(); //It seems that the APP is OK if I remove this.
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
isServiceStoped=false;
return super.onStartCommand(intent,flags,startId);
}
}
=====================My Way 2==========================================
I try to place the code into the function new Handler().postDelayed(new Runnable() {}, it's OK , it ran at the order "A" -> "Service OnDestroy" ->"B" ->"C",
I don't konw why the way can success, I don't know if the way is good way
The last UIAbout.cs
public class UIAbout extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_about);
Intent intent1 = new Intent(UIAbout.this,bll.RecordService.class);
startService(intent1);
Button btnReturn = (Button) findViewById(R.id.btnReturn);
btnReturn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.e("My", "A");
Intent intent1 = new Intent(UIAbout.this, bll.RecordService.class);
stopService(intent1);
new Handler().postDelayed(new Runnable() {
public void run() {
Log.e("My", "B");
Toast.makeText(getApplicationContext(), "OK", Toast.LENGTH_LONG).show();
Log.e("My", "C");
}
}, 1);
}
});
}
}
The last RecordService.cs
public class RecordService extends Service {
private Context mContext;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate(){
}
#Override
public void onDestroy(){
Log.e("My", "Service OnDestroy");
super.onDestroy(); //It seems that the APP is OK if I remove this.
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent,flags,startId);
}
}
No, you can't stop a service synchronously. stopService() is request to stop the service. It will stop sometime later, as soon as it can.
No, you can't remove super.onDestroy() from your onDestroy() method and still have it work properly.
You can not control the timing to completely stop the running service. Use stopService() and the rest is out of your hands. You can use an handler to monitor is the service has stopped before moving to B although I am not sure why would you do it. Not a good practice.
Yeah you can remove super.onDestroy() in onDestroy but I would not advise you to do so. Your app may run but it will be leaving unwanted resources around.
Here how onDestroy() looks like in the android SDK:
#CallSuper
protected void onDestroy() {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onDestroy " + this);
mCalled = true;
// dismiss any dialogs we are managing.
if (mManagedDialogs != null) {
final int numDialogs = mManagedDialogs.size();
for (int i = 0; i < numDialogs; i++) {
final ManagedDialog md = mManagedDialogs.valueAt(i);
if (md.mDialog.isShowing()) {
md.mDialog.dismiss();
}
}
mManagedDialogs = null;
}
// close any cursors we are managing.
synchronized (mManagedCursors) {
int numCursors = mManagedCursors.size();
for (int i = 0; i < numCursors; i++) {
ManagedCursor c = mManagedCursors.get(i);
if (c != null) {
c.mCursor.close();
}
}
mManagedCursors.clear();
}
// Close any open search dialog
if (mSearchManager != null) {
mSearchManager.stopSearch();
}
getApplication().dispatchActivityDestroyed(this);
}
* Sample *
There could be some compile errors, but you will get the idea.
public class UIAbout extends Activity {
private Handler mHandler = new Handler();
private Runnable checkServiceHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_about);
Intent intent1 = new Intent(UIAbout.this,bll.RecordService.class);
startService(intent1);
Button btnReturn = (Button) findViewById(R.id.btnReturn);
btnReturn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.e("My", "A");
Intent intent1 = new Intent(UIAbout.this, bll.RecordService.class);
stopService(intent1);
checkServiceHandler = new Runnable() {
public void run() {
if(RecordService.isServiceStoped){
mHandler.removeCallbacks(checkServiceHandler );
somemethod();
} else{
mHandler.postDelayed(checkServiceHandler, 500);
}
}
};
mHandler.postDelayed(checkServiceHandler, 500); }
});
}
private void somemethod(){
Log.e("My", "B");
Toast.makeText(getApplicationContext(), "OK", Toast.LENGTH_LONG).show();
Log.e("My", "C");
}
}
You should implement your code in a way that you don't care when exactly your service is destroyed.
Anyway. If you really need the exact moment, you can fire an intent from your service using Android's broadcast system.
In your service:
#Override
public void onDestroy()
{
super.onDestroy();
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(CONST_SERVICE_DESTROYED));
}
In your activity:
private BroadcastReceiver receiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
// your B here
// your C here
}
};
And you need to register and unregister your receiver like this:
#Override
protected void onResume()
{
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(receiver, new IntentFilter(CONST_SERVICE_DESTROYED));
}
#Override
protected void onPause()
{
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
}
A good explanation and examples of Android's broadcast system can be found here
I have to create an app for sending programmed messages, if I create a single service for a single message is all ok, but if I create messages how do I handle the deletion of a specific service? also after the stop of the first service if i try to create other service crash all... i use a timer for my service
public class service extends Service
{
private static Timer timer = new Timer();
int i=1;
#Override
public IBinder onBind(Intent arg0)
{
return null;
}
#Override
public void onCreate()
{
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags,int startId){
Toast.makeText(getApplicationContext(), "service start", Toast.LENGTH_SHORT).show();
timer.scheduleAtFixedRate(new mainTask(), 0, 20*1000);
return service.START_NOT_STICKY;
}
#Override
public void onDestroy()
{
super.onDestroy();
Toast.makeText(getApplicationContext(), "distrutta", Toast.LENGTH_SHORT).show();
Log.i("PROVA SERVICE", "Distruzione Service");
}
private class mainTask extends TimerTask
{
public void run()
{
toastHandler.sendEmptyMessage(0);
}
} private final Handler toastHandler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
if (i==1)
{
Toast.makeText(getApplicationContext(), "test1", Toast.LENGTH_SHORT).show();
i++;}
else
{
i=0;
Toast.makeText(getApplicationContext(), "fine", Toast.LENGTH_SHORT).show();
stopSelf();
timer.cancel();
}
}
};
service call:
Intent i=(new Intent(this,service.class));
startService(i);
I'm developing a tracking app. and i have problem with GPS module. The app must record a route. App work fine, but sometimes when the device is not moving, GPS still receive
continuous coordinate that don't indicate my position, error is within a radius of 20 meter, and when I'm moving again work fine.
Please give me some tips that can help me to fix this problem. Thanks a lot.
I have 3 calsses
1 - GPSReceiver here is method for get location
public void getMyLoction(){
_locationManager = (LocationManager) _context.getSystemService(LOCATION_SERVICE);
_isGPSEnabled =_locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (_isGPSEnabled) {
if (_location == null) {
_locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0, this);
if (_locationManager != null) {
_location = _locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
setLocation(_location);
}
}
}
}
2 RecordingActivity (take coordonates form services and processes then) work fine, a comment in method what they do.
public class RecordingActivity extends FragmentActivity {
public final static String BROADCAST_ACTION = "map.trackv";
public BroadcastReceiver receiver;
private GoogleMap map;
private TextView _messageToUser;
private Coordinate _pointFromService;
private long _timeWhenStartButtonWasPressed;
private List<Coordinate> _unprocessedCoords;
private List<Coordinate> _processedCoords;
private Button _stopButton;
private Button _startButton;
private String _startRecordingDate;
private String _stopRecordingDate;
private GPSReceiver _gps;
private DataBaseOperations _dataSource;
private boolean _recording;
private boolean _gpsStatus;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recording_route);
initActvity();
checkIfGPSisOn();
try {
Runtime.getRuntime().exec("logcat -f" + " /sdcard/Logcat.txt");
} catch (IOException e) {
// TODO Auto-generated catch block
Log.d("nu pot", "DDDDD");
e.printStackTrace();
}
receveirWork();
IntentFilter intentFilt = new IntentFilter(BROADCAST_ACTION);
registerReceiver(receiver, intentFilt);
}
public void checkIfGPSisOn() {
//check on start
}
public void receveirWork() {
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// request points and process then,
}
};
}
#Override
protected void onDestroy() {
super.onDestroy();
if (_stopButton.isEnabled())
{
stopService(new Intent(this, RecordingService.class));
_unprocessedCoords = null;
_processedCoords = null;
}
unregisterReceiver(receiver);
}
#Override
protected void onResume() {
if (!_stopButton.isEnabled()) {
_startButton.setEnabled(true);
_messageToUser.setText(Constants.PRESS_START_BUTTON);
map.clear();
}
super.onResume();
}
// actiune buton start;
public void startButtonEvent(View V) {
buttonsStateAndMessageToShow(false, true, Constants.MESSAGE_TO_WAIT);
_timeWhenStartButtonWasPressed = System.currentTimeMillis();
startService(new Intent(this, RecordingService.class));
// start service to get position
}
public void stopButtonEvent(View V) {
stopService(new Intent(this, RecordingService.class));
// stop service
// save route in BD
// resetData;
}
public void initActvity() {
// init date
}
#Override
protected void onSaveInstanceState(Bundle outState) {
// save state
}
}
3 RecordingServices class, ii think here is the problem.
public class RecordingService extends Service {
private Thread _backgroundWork;
private boolean _threadCanRun;
private GPSReceiver _gps;
private Coordinate _pointToSent;
public void onCreate() {
super.onCreate();
_threadCanRun = true;
_backgroundWork = new Thread(new Runnable() {
#Override
public void run() {
Looper.prepare();
getLocationFromGPS();
Looper.loop();
}
});
}
public int onStartCommand(Intent intent, int flags, int startId) {//
_backgroundWork.start();
return super.onStartCommand(intent, flags, startId);
}
public void onDestroy() {
_threadCanRun = false;
super.onDestroy();
}
public IBinder onBind(Intent intent) {
return null;
}
public void getLocationFromGPS() {
while (_threadCanRun) {
Intent _intent = new Intent(RecordingActivity.BROADCAST_ACTION);
_gps = new GPSReceiver(this);
_gps.getMyLoction();
if (_gps.getIsGPSEnabled()) {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {}
sentPoint(_intent);
} else {
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {}
_intent.putExtra("latitude", 0);
_intent.putExtra("longitude", 0);
_intent.putExtra("time", 0);
_intent.putExtra("GPSstatus", false);
sendBroadcast(_intent);
}
}
}
private void sentPoint(Intent _intent) {
_pointToSent = new Coordinate(_gps.getLatitude(), _gps.getLongitude(), _gps.getTime());
_intent.putExtra("latitude", _pointToSent.getLatitude());
_intent.putExtra("longitude", _pointToSent.getlongitude());
_intent.putExtra("time", _pointToSent.getTime());
_intent.putExtra("GPSstatus", _gps.getIsGPSEnabled());
sendBroadcast(_intent);
_pointToSent = null;
}
}
repeating the Location update request depends on how u implemented your tracking system
but in general(which is not recommended , just change your request update rate to save client Battery usage) you can find the distance between your locations by location1.distanceTo(location2) so if the distance is smaller than 30m then put the new location away
This IntentService I created will show Toasts in onStartCommand() and in onDestroy(), but not in onHandleIntent(). Am I missing something about the limitations of an IntentService?
public class MyService extends IntentService {
private static final String TAG = "MyService";
public MyService(){
super("MyService");
}
#Override
protected void onHandleIntent(Intent intent) {
cycle();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); //This happens!
return super.onStartCommand(intent,flags,startId);
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
Toast.makeText(this, "service stopping", Toast.LENGTH_SHORT).show(); //This happens!
super.onDestroy();
}
private void cycle(){
Toast.makeText(this, "cycle done", Toast.LENGTH_SHORT).show(); //This DOESN'T happen!
Log.d(TAG,"cycle completed"); //This happens!
}
}
The accepted answer is not correct.
Here is how you can show toast from onHandleIntent():
Create a DisplayToast class:
public class DisplayToast implements Runnable {
private final Context mContext;
String mText;
public DisplayToast(Context mContext, String text){
this.mContext = mContext;
mText = text;
}
public void run(){
Toast.makeText(mContext, mText, Toast.LENGTH_SHORT).show();
}
}
Instantiate a Handler in your service's constructor and call the post method with a DisplayToast object inside.
public class MyService extends IntentService {
Handler mHandler;
public MyService(){
super("MyService");
mHandler = new Handler();
}
#Override
protected void onHandleIntent(Intent intent) {
mHandler.post(new DisplayToast(this, "Hello World!"));
}
}
You should start the Toast on the main thread:
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
}
});
This is because otherwise the thread of the IntentService quits before the toast can be send out, causing a IllegalStateException:
java.lang.IllegalStateException: Handler (android.os.Handler) {12345678} sending message to a Handler on a dead thread
onHandleIntent() is called from a background thread (that is what IntentService is all about), so you shouldn't do UI from there.
Another option is RxJava, e.g.:
private void showToast(final String text) {
Observable.just(text)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<String>() {
#Override
public void call(String s) {
Toast.makeText(getApplicationContext(), s, Toast.LENGTH_LONG).show();
}
});
}
Caveat: I'm new to Android.