I have a problem with an activity after minimalising. Everything is going ok when i start an activity and press start button. But when i minimalise activity and again maximalize it, it doesnt respond to my buttons and commands. Anybody know what to do? This is my first android app so i dont know what is going on..
here are my classes :
TrackerService
package sk.tuke.smart.makac.services;
import android.app.Service;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
public class TrackerService extends Service implements LocationListener {
private Intent commandIntent;
private long duration;
private boolean paused,checkedAfterPause;
private int sportActivity;
private double distance,pace,calories;
private ArrayList<Location> finalPositionList = new ArrayList<Location>();
private LocationManager locationManager;
private static final String TAG = "TrackerService";
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.i(TAG,"onStart intent " +intent.getAction());
commandIntent=intent;
checkedAfterPause=true;
if(intent.getAction() == "sk.tuke.smart.makac.COMMAND_START"){
if(intent.getAction() == "sk.tuke.smart.makac.COMMAND_START") {
duration = 0;
}
new Timer().scheduleAtFixedRate(new TimerTask()
{
#Override
public void run() {
if(!paused){
duration++;
Intent intent1 = new Intent();
intent1.setAction("sk.tuke.smart.makac.TICK");
intent1.putExtra("duration", duration);
intent1.putExtra("distance",distance);
sendBroadcast(intent1);
Log.i(TAG,"" + duration);
}
}
}, 1000, 1000);
}else if (intent.getAction() == "sk.tuke.smart.makac.COMMAND_PAUSE"){
paused=true;
locationManager.removeUpdates(this);
}
if(intent.getAction() == "sk.tuke.smart.makac.COMMAND_CONTINUE"){
paused=false;
checkedAfterPause=false;
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,3000,10,this);
}
}
#Override
public void onCreate() {
super.onCreate();
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,3000,10,this);
}
#Override
public void onDestroy() {
locationManager.removeUpdates(this);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onLocationChanged(Location location) {
finalPositionList.add(location);
Location lastLocation;
double minDistance;
if (finalPositionList.size() != 1 && checkedAfterPause) {
lastLocation = finalPositionList.get(finalPositionList.size() - 2);
minDistance=location.distanceTo(lastLocation);
if(minDistance>=2){
distance += location.distanceTo(lastLocation);
}else{
finalPositionList.remove(finalPositionList.size()-1);
}
}
if(commandIntent.getAction() == "sk.tuke.smart.makac.COMMAND_CONTINUE" && !checkedAfterPause){
Log.i(TAG,"checking distance after pause");
lastLocation = finalPositionList.get(finalPositionList.size() - 2);
minDistance=location.distanceTo(lastLocation);
if(minDistance<=100){
distance += location.distanceTo(lastLocation);
}
checkedAfterPause=true;
}
Log.i(TAG,"locations " + finalPositionList);
Log.i(TAG,"distance = " + distance);
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
public long getDuration(){
return duration;
}
public double getPace(){
return pace;
}
}
SportsActivity
package sk.tuke.smart.makac;
import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import sk.tuke.smart.makac.helpers.MainHelper;
import sk.tuke.smart.makac.services.TrackerService;
public class StopwatchActivity extends AppCompatActivity {
private static final int MY_PERMISSIONS_REQUEST_FINE_LOCATION = 111;
private static final String TAG = "StopwatchActivity";
private boolean started;
private boolean running;
private boolean paused=false;
private long duration;
private double distance;
private MainHelper helper;
private TextView durationView,distanceView;
private Button startButton,endButton;
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction()=="sk.tuke.smart.makac.TICK"){
duration = intent.getLongExtra("duration",duration);
distance = intent.getDoubleExtra("distance",distance);
durationView.setText(helper.formatDuration(duration));
distanceView.setText(helper.formatDistance(distance));
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stopwatch);
IntentFilter intentFilter = new IntentFilter("sk.tuke.smart.makac.TICK");
registerReceiver(receiver,intentFilter);
started=false;
running=false;
helper = new MainHelper();
durationView = findViewById(R.id.textview_stopwatch_duration);
distanceView = findViewById(R.id.textview_stopwatch_distance);
startButton = findViewById(R.id.button_stopwatch_start);
endButton = findViewById(R.id.button_stopwatch_endworkout);
if(!canAccessLocation()){
ActivityCompat.requestPermissions(this,
new String[]{
Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_FINE_LOCATION);
}
}
public void toggle(View view){
Intent intent = new Intent(this,TrackerService.class);
started=true;
this.running = !this.running;
if(running && started){
startButton.setText("Stop");
endButton.setVisibility(view.GONE);
if(paused){
intent.setAction("sk.tuke.smart.makac.COMMAND_CONTINUE");
paused=false;
}else
intent.setAction("sk.tuke.smart.makac.COMMAND_START");
}
if(!running && started){
startButton.setText("Continue");
endButton.setVisibility(view.VISIBLE);
intent.setAction("sk.tuke.smart.makac.COMMAND_PAUSE");
paused=true;
}
startService(intent);
}
public void endWorkout(View view){
Intent intent = new Intent(this,TrackerService.class);
intent.setAction("sk.tuke.smart.makac.COMMAND_STOP");
startService(intent);
setContentView(R.layout.activity_workout_detail);
onStop();
}
public void openMaps(View view){
Intent intent = new Intent(StopwatchActivity.this, MapsActivity.class);
startActivity(intent);
}
#Override
protected void onStart() {
super.onStart();
}
#Override
protected void onStop() {
super.onStop();
Intent intent= new Intent(this,TrackerService.class);
stopService(intent);
}
private boolean hasPermission(String perm) {
return(PackageManager.PERMISSION_GRANTED==checkSelfPermission(perm));
}
private boolean canAccessLocation() {
return(hasPermission(Manifest.permission.ACCESS_FINE_LOCATION));
}
}
You aren't creating a connection to the service. You're only starting it, not binding it. So there's no connection to maintain.
It looks like you're trying to do quasi-binding via actions. Don't do that, properly bind the service and avoid a whole raft of problems like this.
Related
I'm trying to make a simple musicPlayer that works on Android device.To make Background-play come true, I'm using Service class.
What I want to do is below:
1.User launches app and taps start button
2.Music starts and Notification that notes the Music is playing appears
3.User taps home button and the app's UI disappears
4.Music doesn't stop
5.User tap Notification
6.UI appears with disabled start button and enabled stop button ← I'm in trouble
With My Code, UI appears. But it is not the UI which user made to disappear. How do I describe...It is new-ed UI.
So when user taps stop button,of course music doesn't stop. The Service is different one.
I want music to stop.
Is there any way to show the first created UI? the original UI?
If there's no way to show first created UI,how can I reach to first running service?
Thank you for browsing.
My Activity
package com.websarva.wings.android.servicesample;
import androidx.appcompat.app.AppCompatActivity;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity implements ServiceConnection {
public static final String LOG_TAG = "ServiceSample:";
private Intent _intent;
public static final String INTENT_ACTION = "intentAction";
private ServiceConnection _connection = new ServiceConnection(){
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
#Override
public void onServiceDisconnected(ComponentName name) {
}
};
public void onPlayButtonClick(View view){
Log.e(LOG_TAG,
"#onPlayButtonClick -_intentHash - " + _intent.hashCode()
+ "-_connectionHash" + _connection.hashCode());
bindService(_intent, _connection,Context.BIND_AUTO_CREATE);
startService(_intent);
Button btPlay = findViewById(R.id.btPlay);
btPlay.setEnabled(false);
Button btStop = findViewById(R.id.btStop);
btStop.setEnabled(true);
}
public void onStopButtonClick(View view){
Log.e(LOG_TAG,
"#onStopButtonClick -_intentHash - " + _intent.hashCode()
+ "-_connectionHash" + _connection.hashCode());
unbindService(_connection);
stopService(_intent);
Button btStop = findViewById(R.id.btStop);
btStop.setEnabled(false);
Button btPlay = findViewById(R.id.btPlay);
btPlay.setEnabled(true);
}
private BroadcastReceiver _MessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Button btStop = findViewById(R.id.btStop);
btStop.setEnabled(false);
Button btPlay = findViewById(R.id.btPlay);
btPlay.setEnabled(true);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LocalBroadcastManager.getInstance(this).registerReceiver(_MessageReceiver,new IntentFilter(INTENT_ACTION));
_intent = getIntent();
boolean isAlreadyPlaying = _intent.getBooleanExtra(SoundManageService.EXTRA_KEY_ISPLAYING,false);
if(isAlreadyPlaying){
Button btPlay = findViewById(R.id.btPlay);
btPlay.setEnabled(false);
Button btStop = findViewById(R.id.btStop);
btStop.setEnabled(true);
}
_intent = new Intent(MainActivity.this,SoundManageService.class);
bindService(_intent, _connection,Context.BIND_AUTO_CREATE);
}
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
#Override
public void onServiceDisconnected(ComponentName name) {
}
#Override
public void onDestroy(){
LocalBroadcastManager.getInstance(this).unregisterReceiver(_MessageReceiver);
super.onDestroy();
}
}
My Service
package com.websarva.wings.android.servicesample;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.IBinder;
import android.util.Log;
import androidx.core.app.NotificationCompat;
import androidx.lifecycle.LifecycleService;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import java.io.IOException;
public class SoundManageService extends LifecycleService{
public static final String CHANNEL_ID = "soundmanagerservice_notification_channel";
public static final int FINISH_NOTIFICATION_ID = 2;
public static final int START_NOTIFICATION_ID = 1;
public static final String EXTRA_KEY_ISPLAYING = "isPlaying";
MediaPlayer _player;
public SoundManageService() {
}
private class PlayerPreparedListener implements MediaPlayer.OnPreparedListener{
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
NotificationCompat.Builder builder = new NotificationCompat.Builder(SoundManageService.this,CHANNEL_ID);
builder.setSmallIcon(android.R.drawable.ic_dialog_info);
builder.setContentTitle(getString(R.string.msg_notification_title_start));
builder.setContentText(getString(R.string.msg_notification_text_start));
Intent intent = new Intent(SoundManageService.this,MainActivity.class);
intent.putExtra(EXTRA_KEY_ISPLAYING,mp.isPlaying());
PendingIntent stopServiceIntent = PendingIntent.getActivity(
SoundManageService.this,0,intent,PendingIntent.FLAG_CANCEL_CURRENT);
builder.setContentIntent(stopServiceIntent);
builder.setAutoCancel(true);
Notification notification = builder.build();
startForeground(START_NOTIFICATION_ID,notification);
}
}
private class PlayerCompletionListener implements MediaPlayer.OnCompletionListener{
#Override
public void onCompletion(MediaPlayer mp) {
stopSelf();
sendMessage();
}
}
private void sendMessage() {
Intent intent = new Intent(MainActivity.INTENT_ACTION);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
#Override
public void onCreate(){
super.onCreate();
_player = new MediaPlayer();
String channelName = getString(R.string.notification_channnel_name);
int notificationImportance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID,channelName,notificationImportance);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(notificationChannel);
}
#Override
public int onStartCommand(Intent intent,int flags,int startId){
super.onStartCommand(intent,flags,startId);
String mediaUriStr ="android.resource://" + getPackageName() + "/" + R.raw.testmusic;
Uri uri = Uri.parse(mediaUriStr);
_player = new MediaPlayer();
try{
_player.setDataSource(SoundManageService.this,uri);
_player.setOnPreparedListener(new PlayerPreparedListener());
_player.setOnCompletionListener(new PlayerCompletionListener());
_player.prepareAsync();
} catch (IOException e) {
Log.e("ServiceSample", "メディアプレーヤー準備失敗");
}
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
super.onBind(intent);
return null;
}
#Override
public boolean onUnbind(Intent intent){
return true;
}
#Override
public void onDestroy(){
if(_player.isPlaying()){
_player.stop();
}
_player.release();
_player = null;
super.onDestroy();
}
}
Changing the code (creating Intent for PendingIntent for Notification)
Intent intent = new Intent(SoundManageService.this,MainActivity.class);
to
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setClassName(getApplicationContext().getPackageName(), MainActivity.class.getName());
intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Intent.FLAG_ACTIVITY_NEW_TASK);
made the problem solved.
https://qiita.com/imp954sti/items/e075fb8a99b68dda8180
↑this Japanese note helped me.
i have the following Custom Listener
package home.dan.signalstrengthatlocation;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.SignalStrength;
import android.util.Log;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class CustomPhoneStateListener extends PhoneStateListener {
Context mContext;
public static String LOG_TAG = "CPhoneStateListener";
public CustomPhoneStateListener(Context context) {
mContext = context;
}
#Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
super.onSignalStrengthsChanged(signalStrength);
Log.i(LOG_TAG, "onSignalStrengthsChanged: " + signalStrength);
Intent i = new Intent("Signal_update");
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra("signals","signals updated");
CustomPhoneStateListener.this.mContext.startActivity(i);
//mContext.startActivity(i); also does not work
}
}
In the last command it tries to send data to the MainActivity Class to be picked up by it's onReceive method.
But this does not work. i get the following error.
android.content.ActivityNotFoundException: No Activity found to handle Intent
What is the best way to send data from above Listner class to the MainActivity class ?
EDIT -
Class below is supposed to receive information from above intent
package home.dan.signalstrengthatlocation;
import android.app.Activity;
import android.telephony.TelephonyManager;
import android.telephony.PhoneStateListener;
import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private static final int NETWORKTYPE_WIFI = 0;
private static final int NETWORKTYPE_4G = 1;
private static final int NETWORKTYPE_2G = 2;
private static final int NETWORKTYPE_NONE = 3;
public TelephonyManager mTelephonyManager;
public PhoneStateListener mListener;
private Button start_btn,stop_btn;
private TextView textview;
private BroadcastReceiver broadcastReceiver;
private String coordinates;
public String getCoordinates() {
return coordinates;
}
public void setCoordinates(String coordinates) {
this.coordinates = coordinates;
}
private String signalStrength;
public String getSignalStrength() {
return signalStrength;
}
public void setSignalStrength(String signalStrength) {
this.signalStrength = signalStrength;
}
#Override
protected void onResume() {
super.onResume();
if(broadcastReceiver == null){
broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
setCoordinates(intent.getExtras().get("coordinates").toString());
updateScrollText();
}
};
}
registerReceiver(broadcastReceiver,new IntentFilter("location_update"));
}
private void updateScrollText(){
textview.append("\n"+getCoordinates()+" "+getSignalStrength());
}
#Override
protected void onDestroy() {
super.onDestroy();
if(broadcastReceiver != null){
unregisterReceiver(broadcastReceiver);
}
}
GPS_Service gps;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTelephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
mTelephonyManager.listen(new CustomPhoneStateListener(this), PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
start_btn = (Button) findViewById(R.id.button1);
stop_btn = (Button) findViewById(R.id.button2);
textview = (TextView) findViewById(R.id.textview);
if(!runtime_permissions()){
enable_buttons();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
// TODO Extract the data returned from the child Activity.
setSignalStrength(data.getStringExtra("signals"));
updateScrollText();
}
}
private void enable_buttons(){
start_btn.setEnabled(true);
stop_btn.setEnabled(false);
start_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(getApplicationContext(),GPS_Service.class);
startService(i);
if(!stop_btn.isEnabled()){
start_btn.setEnabled(false);
stop_btn.setEnabled(true);
}
}
});
stop_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(getApplicationContext(),GPS_Service.class);
stopService(i);
if(!start_btn.isEnabled()){
start_btn.setEnabled(true);
stop_btn.setEnabled(false);
}
}
});
}
private boolean runtime_permissions(){
if(Build.VERSION.SDK_INT >= 23
&&
ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&&
ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
&&
ContextCompat.checkSelfPermission(this,
Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(
new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.READ_PHONE_STATE},
100);
return true;
}
return false;
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == 100){
if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
enable_buttons();
}else{
runtime_permissions();
}
}
}
}
In your onResume() of your MainActivity, add following
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("location_update");
intentFilter.addAction("signal_update);
registerReceiver(broadcastReceiver, intentFilter);
And then use sendBroadcast in CustomPhoneStateListener instead of startActivity.
Intent i = new Intent("signal_update");
i.putExtra("signals","signals updated");
CustomPhoneStateListener.this.mContext.sendBroadcast(i);
You'll receive both signal as well as location update here:
public void onReceive(Context context, Intent intent) {
if("signal_update".equals(intent.getAction())) {
//update UI for signal update
} else if ("location_update".equals(intent.getAction())) {
// update UI for location update
}
}
I am trying to understand how this stuff works a little better.
So I learned about Runnables and Threads and ASyncTasks but apparently they have some serious drawbacks when it comes to configuration changes like rotating the screen.
Is it better to instead use IntentService for anything that should run in the background like SQL database commands, file-system procedures, Internet input/output processes, etc -- and then use LocalBroadcastReceiver to pass results back to the Activity?
Is it better to instead use IntentService for anything that should run in the background like SQL database commands, file-system procedures, Internet input/output processes, etc -- and then use LocalBroadcastReceiver to pass results back to the Activity?
A service is needed if your UI might move to the background while the work is going on, and you are concerned that your process might be terminated while the work is going on. I tend to only worry about this if the work might exceed a second or so. Otherwise, a plain thread suffices.
Using an event bus, like LocalBroadcastManager, is a reasonable approach to let other components know when your service/thread is done with its work. This sample app demonstrates this. Personally, I tend to use greenrobot's EventBus — this sample app is a clone of the first one, but using EventBus instead of LocalBroadcastManager.
Follow an example of a chat using one activity (chat activity) that run a class in service (realtime class). I use a mvc webapi to controll chat between chatters. When realtime receive a message "onConnected" or "ReceivedMessageServer" automatically send by LocalBroadcastManager to chat activity. This way in "onReceive" from BroadcastReceiver receives the message and runs other tasks.
a) ChatActivity.class
package br.com.yourapp;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.res.Configuration;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.util.TypedValue;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import java.util.Calendar;
import br.com.yourapp.model.MessageReceived;
import util.RealTime;
public class ChatActivity extends AppCompatActivity implements View.OnClickListener,
View.OnKeyListener , TextWatcher {
AppController obj;
private ProgressDialog pDialog;
MediaPlayer mp;
private ListView lstChatLog;
private ArrayAdapter<String> listAdapter;
private EditText txtChatMessage;
private TextView lblTyping;
private Button btnSendChat;
private boolean resultRequest = true;
private String errorMessage = "Internet is not working";
private AlertDialog alertDialog;
private AlertDialog.Builder alertBuilder;
String userType = "V";
String spaces = "\u0020\u0020\u0020\u0020";
Calendar time;
MessageReceived msg;
private RealTime realTime;
private final Context mContext = this;
private boolean mBound = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
pDialog = new ProgressDialog(this);
pDialog.setMessage("Loading...");
pDialog.setCancelable(false);
showProgressDialog();
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
obj = (AppController) getApplicationContext();
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
lblTyping = (TextView) findViewById(R.id.lblTyping);
txtChatMessage = (EditText) findViewById(R.id.txtChatMessage);
txtChatMessage.setOnKeyListener(this);
txtChatMessage.addTextChangedListener(this);
btnSendChat = (Button) findViewById(R.id.btnSendChat);
btnSendChat.setOnClickListener(this);
alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setTitle("Alert");
alertBuilder = new AlertDialog.Builder(this);
lstChatLog = (ListView) findViewById(R.id.lstChatLog);
listAdapter = new ArrayAdapter<String>(ChatActivity.this, android.R.layout.simple_list_item_1, android.R.id.text1) {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
TextView tv = (TextView) view.findViewById(android.R.id.text1);
tv.setHeight(20);
tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12);
return view;
}
};
Intent intent = new Intent();
intent.setClass(mContext, RealTime.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
IntentFilter filter = new IntentFilter("Connect");
filter.addAction("RecMsg");
LocalBroadcastManager.getInstance(ChatActivity.this).registerReceiver(mMessageReceiver, filter);
}
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().toString().equals("Connect")) {
msg = (MessageReceived) intent.getExtras().getParcelable("msg");
if (msg == null || msg.Message == null)
return;
listAdapter.add(msg.Destiny + "" + msg.CurrentTime + " : " + msg.Message);
lstChatLog.setAdapter(listAdapter);
realTime.SendToSpecific(msg.Sender, "Hi !", userType, obj.getRiderId(), obj.getDriverId());
hideProgressDialog();
}
else
if (intent.getAction().toString().equals("RecMsg")) {
msg = (MessageReceived) intent.getExtras().getParcelable("msg");
if (msg == null || msg.Message == null)
return;
if (msg.Message.equals("*0.+9=&!*#_&1|8%digi")) {
lblTyping.setVisibility(View.VISIBLE);
}
else
if (msg.Message.equals("*0.+9=&!*#_&1|8%"))
{
lblTyping.setVisibility(View.INVISIBLE);
}
else
{
lblTyping.setVisibility(View.INVISIBLE);
listAdapter.add(msg.Sender + "" + msg.CurrentTime + " : " + msg.Message);
lstChatLog.setAdapter(listAdapter);
mp = MediaPlayer.create(ChatActivity.this, R.raw.notify);
mp.setLooping(false);
mp.setVolume(100, 100);
mp.start();
}
}
}
};
private final ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
RealTime.LocalBinder binder = (RealTime.LocalBinder) service;
realTime = binder.getService();
mBound = true;
realTime.Connect(obj.getRiderName(), userType, obj.getRiderId(), obj.getLatitudeRider(), obj.getLongitudeRider(), obj.getDriverId(), obj.getVehicieId());
hideProgressDialog();
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
#Override
protected void onStop() {
if (mBound) {
unbindService(mConnection);
mBound = false;
}
super.onStop();
}
public void SendToSpecific(String sender, String message, String userType, long userId, long operatorId) {
realTime.SendToSpecific(sender, message, userType, userId,operatorId);
if (!message.equals("*0.+9=&!*#_&1|8%digi") && !message.equals("*0.+9=&!*#_&1|8%"))
{
time = Calendar.getInstance();
listAdapter.add(spaces + sender + " " + "(" + time.get(Calendar.HOUR) + ":" + time.get(Calendar.MINUTE) + ")" + " : " + message);
lstChatLog.setAdapter(listAdapter);
txtChatMessage.setText("");
}
}
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode==KeyEvent.KEYCODE_ENTER) {
if (txtChatMessage.getText().length() > 0)
{
InputMethodManager imm = (InputMethodManager) this.getSystemService(Context.
INPUT_METHOD_SERVICE);
if (this.getCurrentFocus() != null)
imm.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), 0);
SendToSpecific(obj.getRiderName(), txtChatMessage.getText().toString(), userType, obj.getRiderId(), obj.getDriverId());
}
}
return false;
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (txtChatMessage.getText().toString().length() > 0) {
if (txtChatMessage.getText().length() == 1) {
SendToSpecific(obj.getRiderName(), "*0.+9=&!*#_&1|8%digi", userType, obj.getRiderId(), obj.getDriverId());
}
} else {
SendToSpecific(obj.getRiderName(), "*0.+9=&!*#_&1|8%", userType, obj.getRiderId(), obj.getDriverId());
}
}
#Override
public void afterTextChanged(Editable s) {
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnSendChat:
if (txtChatMessage != null && txtChatMessage.getText().length() > 0) {
InputMethodManager imm = (InputMethodManager) this.getSystemService(Context.
INPUT_METHOD_SERVICE);
if (this.getCurrentFocus() != null)
imm.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), 0);
SendToSpecific(obj.getRiderName(), txtChatMessage.getText().toString(), userType, obj.getRiderId(), obj.getDriverId());
}
break;
}
}
private void showProgressDialog() {
if (!pDialog.isShowing())
pDialog.show();
}
private void hideProgressDialog() {
if (pDialog.isShowing())
pDialog.hide();
}
#Override
protected void onDestroy() {
try {
if (pDialog != null && pDialog.isShowing())
pDialog.dismiss();
} catch (Exception e) {
e.printStackTrace();
}
super.onDestroy();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.
INPUT_METHOD_SERVICE);
if (getCurrentFocus() != null)
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
mMessageReceiver.clearAbortBroadcast();
Intent i = new Intent(this, MenuPageActivity.class);
obj.setLastActivity("Chat");
startActivity(i);
return true;
}
public void ShowAlert() {
hideProgressDialog();
if (resultRequest)
errorMessage = "Internet is not working";
alertBuilder.setTitle("Alert");
alertBuilder.setMessage(errorMessage);
alertBuilder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
arg0.dismiss();
}
});
alertDialog = alertBuilder.create();
alertDialog.show();
errorMessage = "";
resultRequest = true;
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
}
b) Realtime.class
package util;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import java.util.concurrent.ExecutionException;
import br.com.yourapp.model.MessageReceived;
import microsoft.aspnet.signalr.client.Platform;
import microsoft.aspnet.signalr.client.SignalRFuture;
import microsoft.aspnet.signalr.client.http.android.AndroidPlatformComponent;
import microsoft.aspnet.signalr.client.hubs.HubConnection;
import microsoft.aspnet.signalr.client.hubs.HubProxy;
import microsoft.aspnet.signalr.client.hubs.SubscriptionHandler1;
import microsoft.aspnet.signalr.client.transport.ClientTransport;
import microsoft.aspnet.signalr.client.transport.ServerSentEventsTransport;
public class RealTime extends Service {
private HubConnection mHubConnection;
private HubProxy mHubProxy;
private Handler mHandler;
private final IBinder mBinder = new LocalBinder();
public RealTime() { }
#Override
public void onCreate() {
super.onCreate();
mHandler = new Handler(Looper.getMainLooper());
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
int result = super.onStartCommand(intent, flags, startId);
startSignalR();
return result;
}
#Override
public void onDestroy() {
mHubConnection.stop();
super.onDestroy();
}
#Override
public IBinder onBind(Intent intent) {
startSignalR();
return mBinder;
}
public class LocalBinder extends Binder {
public RealTime getService() {
return RealTime.this;
}
}
public void Connect(String userName, String userType, long userId, double latitude, double longitude, long driverId, long vehicleId) {
mHubProxy.invoke("Connect", userName, userType, userId, latitude, longitude, driverId, vehicleId);
}
public void SendMessageToGroup(String userName, String userGroup, String userType, long userId, double latitude, double longitude, long vehicleId, short option)
{
mHubProxy.invoke("SendMessageToGroup", userName, userGroup, userType, userId, latitude, longitude, vehicleId, option);
}
public void SendToSpecific(String sender, String message, String userType, long userId, long operatorId)
{
mHubProxy.invoke("SendToSpecific", sender, message, userType, userId, operatorId);
}
private void startSignalR() {
Platform.loadPlatformComponent(new AndroidPlatformComponent());
mHubConnection = new HubConnection("http://webapi.com");
mHubProxy = mHubConnection.createHubProxy("ChatHub");
ClientTransport clientTransport = new ServerSentEventsTransport(mHubConnection.getLogger());
SignalRFuture<Void> signalRFuture = mHubConnection.start(clientTransport);
try {
signalRFuture.get();
} catch (InterruptedException | ExecutionException e) {
Log.e("SimpleSignalR", e.toString());
return;
}
mHubProxy.on("onConnected",
new SubscriptionHandler1<MessageReceived>() {
#Override
public void run(final MessageReceived msg) {
mHandler.post(new Runnable() {
#Override
public void run() {
Intent intent = new Intent("Connect");
intent.putExtra("msg", msg);
LocalBroadcastManager.getInstance(RealTime.this).sendBroadcast(intent);
}
});
}
}
, MessageReceived.class);
}
}
mHubProxy.on("ReceivedMessageServer",
new SubscriptionHandler1<MessageReceived>() {
#Override
public void run(final MessageReceived msg) {
mHandler.post(new Runnable() {
#Override
public void run() {
Intent intent = new Intent("RecMsg");
intent.putExtra("msg", msg);
LocalBroadcastManager.getInstance(RealTime.this).sendBroadcast(intent);
}
});
}
}
, MessageReceived.class);
}
My professor has a program that I am trying to help hime upgrade, unfortunately I am extremely new to Android. It a program that is supposed to grab your Android's location and periodically send it to a server (about every 5 seconds). But after upgrading it to use API 21 (it was on 10-14), it will only return my location as 0.0. Does anyone know what might have caused this?
Here is the Main
import java.text.DecimalFormat;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.location.LocationManager;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity
{
protected Button panic;
protected Button track;
private TextView latText;
private TextView lngText;
private TextView addressText;
private boolean panicking;
private boolean tracking;
protected Context mContext;
private Timer locTimer;
private final String TAG = "MainActivity";
protected Sender send;
private int trackingOn;
private int trackingOff;
private int panicOn;
private int panicOff;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tracking = false;
panicking = false;
//colors
trackingOff = Color.rgb(100, 255, 100);
trackingOn = Color.rgb(255, 255, 100);
panicOff = Color.rgb(255, 50, 50);
panicOn = Color.rgb(255, 127, 0);
setupSender();
setupView();
//createGPS();
checkGPS();
//create GPS service
Intent trackIntent = new Intent(MainActivity.this, TrackingService.class);
startService(trackIntent);
createTimer();
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
#Override
public void onDestroy()
{
locTimer.cancel();
super.onDestroy();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if(keyCode == KeyEvent.KEYCODE_BACK)
{
Log.d(TAG, "Back pressed");
//create dialog to turn off GPS
//if not then ask the user to turn it on
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Would you like to turn off the GPS?");
builder.setCancelable(false);
//yes
builder.setPositiveButton("Disable GPS in device settings", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
Intent callGPSSettingIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(callGPSSettingIntent);
finish();
}
});
//no
builder.setNegativeButton("No", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
dialog.cancel();
finish();
}
});
AlertDialog gpsAlert = builder.create();
gpsAlert.show();
}
return super.onKeyDown(keyCode, event);
}
private void setupSender()
{
//get MAC address
WifiManager wifiMan = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInf = wifiMan.getConnectionInfo();
String macAddr = wifiInf.getMacAddress();
//get phone Number
TelephonyManager teleMan = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
String phoneNumber = teleMan.getLine1Number();
Log.d(TAG, "My mac: " + macAddr + " My number: " + phoneNumber);
send = new Sender(macAddr, phoneNumber);
}
private class SendTracking extends AsyncTask<String, String, String>
{
#Override
protected String doInBackground(String... arg0)
{
send.sendTrack(Values.lat, Values.lng, Values.myAddress, Values.acc);
return null;
}
}
private class SendPanic extends AsyncTask<String, String, String>
{
#Override
protected String doInBackground(String... arg0)
{
send.sendPanic(Values.lat, Values.lng, Values.myAddress, Values.acc);
return null;
}
}
private void setupView()
{
latText = (TextView)findViewById(R.id.lattitude);
lngText = (TextView)findViewById(R.id.longitude);
addressText = (TextView)findViewById(R.id.address);
// create tracking button
track = (Button)findViewById(R.id.trackMe);
track.setBackgroundColor(trackingOff);
track.setOnClickListener(new OnClickListener()
{
public void onClick(View arg0)
{
tracking = !tracking;
Log.w(TAG, "Tracking button pressed");
if(tracking)
{
track.setBackgroundColor(trackingOn);
track.setText(getResources().getString(R.string.stopTrack));
Values.interval = Values.TRACK_INTERVAL; //set it so it sends right away
}
else
{
new SendTracking().execute();
track.setBackgroundColor(trackingOff);
track.setText(getResources().getString(R.string.tracker));
}
}
});
// create panic button
panic = (Button) findViewById(R.id.panic);
panic.setBackgroundColor(panicOff);
panic.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View arg0)
{
Log.w(TAG, "Panic Pressed");
panicking = !panicking;
//send.sendPanic(Values.lat, Values.lng, Values.myAddress, Values.acc);
if(panicking)
{
panic.setBackgroundColor(panicOn);
panic.setText(getResources().getString(R.string.stopPanic));
Values.interval = Values.TRACK_INTERVAL; //set it so it sends right away
}
else
{
panic.setBackgroundColor(panicOff);
panic.setText(getResources().getString(R.string.panic));
}
}
});
}
private void createTimer()
{
//decimal formatter
final DecimalFormat format = new DecimalFormat("#.###");
// create runnable for timer
final Runnable updateLoc = new Runnable()
{
#Override
public void run()
{
Log.i(TAG, "Updating loc");
latText.setText("" + format.format(Values.lat));
lngText.setText("" + format.format(Values.lng));
addressText.setText(Values.myAddress);
//send to DB if tracking is on and enough time has passed since last update
if(tracking)
{
if (Values.interval >= Values.TRACK_INTERVAL)
{
new SendTracking().execute();
Values.interval = 0;
}
else
{
Values.interval++;
}
}
else if(panicking)
{
if (Values.interval >= Values.TRACK_INTERVAL)
{
new SendPanic().execute();
Values.interval = 0;
}
else
{
Values.interval++;
}
}
}
};
// create timer that will check for location
locTimer = new Timer("LocTimer");
locTimer.scheduleAtFixedRate(new TimerTask()
{
#Override
public void run()
{
runOnUiThread(updateLoc);
}
}, Values.UPDATE_TIMER / 2, Values.UPDATE_TIMER);
}
private void checkGPS()
{
LocationManager manager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
//check to see if GPS is enabled
if(!manager.isProviderEnabled(LocationManager.GPS_PROVIDER))
{
//if not then ask the user to turn it on
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("GPS is currently disabled. Please turn it on");
builder.setCancelable(false);
//yes
builder.setPositiveButton("Enabled GPS in device settings", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
Intent callGPSSettingIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(callGPSSettingIntent);
}
});
//no
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
dialog.cancel();
}
});
AlertDialog gpsAlert = builder.create();
gpsAlert.show();
}
}
}
And this is the Tracking Service
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import android.Manifest;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
public class TrackingService extends Service {
private LocationManager manager;
private LocationListener listener;
private final String TAG = "TrackingService";
public class LocalBinder extends Binder {
TrackingService getService() {
return TrackingService.this;
}
}
public IBinder onBind(Intent arg0) {
return new LocalBinder();
}
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
public void onStart(Intent intent, int startId) {
Log.d(TAG, "Starting service");
this.onStart(intent, startId);
}
public void onCreate() {
Log.d(TAG, "Creating service");
this.createGPS();
}
public void onDestroy() {
Log.d(TAG, "Killing service");
manager.removeUpdates(listener);
super.onDestroy();
}
private LocationManager createGPS() {
// create GPS service
manager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
//context
final Context context = this;
// make listener
listener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "GPS udpate");
Values.lat = location.getLatitude();
Values.lng = location.getLongitude();
Values.acc = location.getAccuracy();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Geocoder.isPresent()) {
// Since the geocoding API is synchronous and may take a while. You don't want to lock
// up the UI thread. Invoking reverse geocoding in an AsyncTask.
(new ReverseGeocodingTask(context)).execute(new Location[]{location});
}
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
// register listener
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, Values.UPDATE_TIMER, 10f, listener);
manager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, Values.UPDATE_TIMER, 10f, listener);
return manager;
}
// AsyncTask encapsulating the reverse-geocoding API. Since the geocoder API is blocked,
// we do not want to invoke it from the UI thread.
private class ReverseGeocodingTask extends AsyncTask<Location, Void, Void>
{
Context mContext;
public ReverseGeocodingTask(Context context)
{
super();
mContext = context;
}
#Override
protected Void doInBackground(Location... params)
{
Geocoder geocoder = new Geocoder(mContext, Locale.getDefault());
Location loc = params[0];
List<Address> addresses = null;
try
{
// Call the synchronous getFromLocation() method by passing in the lat/long values.
addresses = geocoder.getFromLocation(loc.getLatitude(), loc.getLongitude(), 1);
}
catch (IOException e)
{
e.printStackTrace();
// Update UI field with the exception.
//Message.obtain(mHandler, UPDATE_ADDRESS, e.toString()).sendToTarget();
Log.e("ReverseGeoCoder", "error: " + e.toString());
}
if (addresses != null && addresses.size() > 0)
{
Address address = addresses.get(0);
// Format the first line of address (if available), city, and country name.
String addressText = String.format("%s, %s, %s",
address.getMaxAddressLineIndex() > 0 ? address.getAddressLine(0) : "",
address.getLocality(),
address.getCountryName());
// Update the UI via a message handler.
//Message.obtain(mHandler, UPDATE_ADDRESS, addressText).sendToTarget();
Log.d("ReverseGeoCoder", "address: " + addressText);
Values.myAddress = addressText;
}
return null;
}
}
}
It worked just fine before, I've seen the tracking logs, but now it only returns 0.0.
RESOLVED
Singleton pattern was suggested. Not the most elegant way to solve the problem but it works. Here is the code I used. Just have to get the instance in the main and LocationService class to use. See answer for how you are suppose to do it.
import android.location.Location;
public class LocationSingleton {
private Location location;
private static LocationSingleton singleton = new LocationSingleton();
private LocationSingleton(){
}
public static LocationSingleton getInstance( ) {
return singleton;
}
protected void setLocation(Location newLocation) {
this.location = newLocation;
}
protected Location getLocation(){
return this.location;
}
}
Attempting to use a background service to handle Location updates. I create a service in Main that updates the data (working correctly I believe) but I also have a button in main that whenever pressed does some work with the location data. I can't figure out though how to pass the Location from the service back to main. I've tried passing Main to the service but that didn't work and always created the service using the constructor without main passed. I've also tried creating a method in the service that returns the location but that kept getting a null pointer exception. How does one go about doing this.
Service Class
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Geocoder;
import android.location.Location;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationListener;
import java.util.Locale;
public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
private String TAG = "LocationService";
private GoogleApiClient mGoogleApiClient;
private static final long INTERVAL = 1000 * 15;
private static final long FATEST_INTERVAL = 1000 * 30;
private LocationRequest mLocationRequest;
private Location mCurrentLocation;
private Geocoder geocoder;
AddressStringOperations addressOps;
TimerUpdate timerUpdate;
Context mainContext;
MainActivity act;
public LocationService(MainActivity act) {
this.mainContext = mainContext;
Log.e(TAG, "Correct Constructor");
}
public LocationService(){
Log.e(TAG, "Shouldn't use");
}
#Override
public void onCreate() {
super.onCreate();
Log.e(TAG, "onCreate");
this.geocoder = new Geocoder(this, Locale.getDefault());
addressOps = new AddressStringOperations(this.geocoder);
this.timerUpdate = new TimerUpdate(this, addressOps);
timerUpdate.startTimer();
mGoogleApiClient = new GoogleApiClient.Builder(LocationService.this)
.addApi(LocationServices.API).addConnectionCallbacks(LocationService.this)
.addOnConnectionFailedListener(LocationService.this).build();
mGoogleApiClient.connect();
createLocationRequest();
}
#Override
public void onDestroy(){
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId){
Log.e(TAG, "Service Started");
return super.onStartCommand(intent, flags, startId);
}
protected void createLocationRequest(){
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(INTERVAL);
mLocationRequest.setFastestInterval(FATEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
public Location getLocation(){
Log.e(TAG, "Latitude: "+ mCurrentLocation.getLatitude() + "\n" + "Longitude: " + mCurrentLocation.getLatitude());
return this.mCurrentLocation;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onConnected(Bundle bundle) {
Log.e(TAG, "Connection Successful");
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
#Override
public void onConnectionSuspended(int i) {
Log.e(TAG, "Connection Lost");
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.e(TAG, "Connection Failed");
}
#Override
public void onLocationChanged(Location location) {
Log.e(TAG, "Firing onLocationChanged.........");
//Log.e(TAG, "Latitude: "+ location.getLatitude() + "\n" + "Longitude: " + location.getLatitude());
timerUpdate.location = location;
mCurrentLocation = location;
}
}
Main Class
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import android.location.Geocoder;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import java.util.Locale;
public class MainActivity extends Activity {
private Button bLogout, bWebsite;
private ImageButton bLogData;
private TextView etLabel;
private UserLocalStore userLocalStore;
private static final String TAG = "MainActivity";
TimerUpdate timerUpdate;
Geocoder geocoder;
Location location;
AddressStringOperations addressOps;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e(TAG, "On Create . . . . .");
if(!isGooglePlayServicesAvailable()){
startActivity(new Intent(MainActivity.this, login.class));
Log.e(TAG, "No GooglePlayServices");
finish();
Toast.makeText(getApplicationContext(), "Please update GooglePlay Servies to use this Application", Toast.LENGTH_LONG).show();
}else{
userLocalStore = new UserLocalStore(this);
this.geocoder = new Geocoder(this, Locale.getDefault());
addressOps = new AddressStringOperations(this.geocoder);
this.timerUpdate = new TimerUpdate(this, addressOps, false);
if (authenticate() != true) {
startActivity(new Intent(MainActivity.this, login.class));
Log.e(TAG, "Authenticate is not true");
finish();
} else {
etLabel = (TextView) findViewById(R.id.etEmailLabel);
bLogout = (Button) findViewById(R.id.bLogout);
bLogData = (ImageButton) findViewById(R.id.DataLog);
bWebsite = (Button) findViewById(R.id.website);
LocationService service = new LocationService(MainActivity.this);
Intent start = new Intent(MainActivity.this, LocationService.class);
MainActivity.this.startService(start);
bLogData.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
String pressStatus = "3";
Log.e(TAG, "Latitude: "+ location.getLatitude() + "\n" + "Longitude: " + location.getLatitude());
timerUpdate.update(pressStatus);
}
});
bLogout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
userLocalStore.clearuserData();
userLocalStore.setUserLoggedIn(false);
startActivity(new Intent(MainActivity.this, login.class));
finish();
}
});
bWebsite.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("temp"));
startActivity(browserIntent);
}
});
}
}
}
public void setLocation(Location newLocation){
this.location = newLocation;
}
}
You can do that in multiple ways. You can create a Receiver and broadcast and intent from there or you can use an EventBus ( https://github.com/greenrobot/EventBus ).
In this case I think it's more appropriate the Service/Receiver model, you can find here an example: http://www.truiton.com/2014/09/android-service-broadcastreceiver-example/
If you need it only in one activity, consider to use an AsyncTask and handle the output in the postExecute method, it would be a lot easier.