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);
}
Related
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.
I am writing a text-to-speech android application. I am refactoring the code and trying to separate TextToSpeech class from an activity to a service so the UI can be updated without blocking, while the audio is playing in the background. However I am not able to wait for the TTS engine to initialize.
When I use
while(isInit==false)
Thread.sleep(1000);
the service never calls the onServiceConnected method.
If anybody knows how to wait for initialization of the TTS engine to complete, and avoid blocking the UI for too long (which causes the application to crash), help would be greatly appreciated!
Here is my service
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.speech.tts.TextToSpeech;
import android.speech.tts.UtteranceProgressListener;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import java.util.HashMap;
import java.util.Locale;
public class MyTTSService extends Service {
private static final String TAG = "Class-MyTTSService";
private TextToSpeech tts;
private boolean isInit = false;
private final IBinder myBinder = new MyBinder();
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "Creating TTS Service");
Context context = this.getApplicationContext();
this.tts = new TextToSpeech(context, onInitListener);
this.tts.setOnUtteranceProgressListener(utteranceProgressListener);
Log.d(TAG, "TTS Service Created");
// why is this blocking everything?
while(!isInitComplete()){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.d(TAG, e.toString());
}
}
}
public boolean isInitComplete(){
return isInit;
}
#Override
public void onDestroy() {
// Don't forget to shutdown tts!
if (tts != null) {
tts.stop();
tts.shutdown();
}
super.onDestroy();
}
public void waitToFinishSpeaking() {
while (tts.isSpeaking()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Log.d(TAG, e.toString());
}
}
}
public void speak(String text, AppCompatActivity appCompatActivity) {
Log.d(TAG, "Speak" + text);
appCompatActivity.setVolumeControlStream(AudioManager.STREAM_MUSIC);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
HashMap<String, String> param = new HashMap<>();
param.put(TextToSpeech.Engine.KEY_PARAM_STREAM, String.valueOf(AudioManager.STREAM_MUSIC));
tts.speak(text, TextToSpeech.QUEUE_ADD, null);
} else {
String utteranceId=this.hashCode() + "";
Bundle bundle = new Bundle();
bundle.putInt(TextToSpeech.Engine.KEY_PARAM_STREAM, AudioManager.STREAM_MUSIC);
tts.speak(text, TextToSpeech.QUEUE_ADD, null, null);
}
}
private UtteranceProgressListener utteranceProgressListener = new UtteranceProgressListener() {
#Override
public void onStart(String utteranceId) {
}
#Override
public void onDone(String utteranceId) {
}
#Override
public void onError(String utteranceId) {
Log.e(TAG, "Error while trying to synthesize sample text");
}
};
private TextToSpeech.OnInitListener onInitListener = new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
int result = tts.setLanguage(Locale.US);
if (result == TextToSpeech.LANG_MISSING_DATA
|| result == TextToSpeech.LANG_NOT_SUPPORTED) {
Log.e("TTS", "This Language is not supported");
} else {
//init success
isInit = true;
Log.d(TAG, "TTS Initialized.");
}
} else {
Log.e("TTS", "Initilization Failed!");
}
}
};
#Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "Binding TTS Service");
return myBinder;
}
public class MyBinder extends Binder {
MyTTSService getService() {
return MyTTSService.this;
}
}
#Override
public boolean onUnbind(Intent intent) {
return false;
}
}
And here is my activity
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.EditText;
import android.widget.TextView;
import java.util.ArrayList;
public class ReaderActivity extends AppCompatActivity {
private static final String TAG = "Class-ReaderActivity";
EditText textBox;
ArrayList<String> sentences = new ArrayList<String>();
MyTTSService tts;
boolean isBound = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reader);
textBox = (EditText) findViewById(R.id.readerTextArea);
Intent intentExtras = getIntent();
Bundle extrasBundle = intentExtras.getExtras();
sentences = extrasBundle.getStringArrayList("sentences");
textBox.setText(sentences.toString(), TextView.BufferType.NORMAL);
textBox.setKeyListener(null);
}
#Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, MyTTSService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
Log.d(TAG, "Waiting to bind to service");
}
public void readSentences(){
for(String sentence : sentences){
Log.d(TAG +"Sencence", sentence);
//updateUI(sentence);
tts.speak(sentence, this);
tts.waitToFinishSpeaking();
}
}
private ServiceConnection serviceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
MyTTSService.MyBinder binder = (MyTTSService.MyBinder) service;
tts = binder.getService();
isBound = true;
readSentences();
}
#Override
public void onServiceDisconnected(ComponentName name) {
isBound = false;
}
};
}
I found the solution. Remove the existing wait loop from MyTTSService.onCreate().
Place the following at the end of the onServiceConnected method
new Thread(new Runnable() {
public void run(){
readSentences();
}
}).start();
Then add a method to MyTTSService
public boolean isInit(){
return isInit;
}
In some circumstances the tts module may need to be reinitialised. Add the following to TextToSpeech.OnInitListener.OnInit in the cases where initialisation is unsuccessful.
isInit = false;
Then finally add the following to the readsentences method
while(!tts.isInit()){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.d(TAG, e.toString());
}
}
tts.speak(sentence, this);
With these changes the TTS module initialises, audio works, the Activity loads and the UI can be refreshed while audio is playing.
This should finally put the issue (which has been asked several times but never resolved) to bed for good.
hello i am new in signalR i am making one chating app with using signalR i take reference from SignalR integration in android studio here with the help of this i able to send the messages to the chat group but i am not able to receive messages i read lots of Q&A here but i am not able to solve this problem i paste here my code and please anyone tell me how do i receive message from the server.following is my code.
Activity main
package myapp.chatapp;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.Toast;
import com.google.gson.JsonElement;
import java.util.ArrayList;
import microsoft.aspnet.signalr.client.MessageReceivedHandler;
import microsoft.aspnet.signalr.client.Platform;
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.SubscriptionHandler2;
import microsoft.aspnet.signalr.client.transport.ClientTransport;
import microsoft.aspnet.signalr.client.transport.LongPollingTransport;
public class MainActivity extends AppCompatActivity implements SignalRService.Something {
private StringBuilder mLog;
private ListView mTestCaseList;
private Spinner mTestGroupSpinner;
private HubConnection mHubConnection;
private HubProxy mHubProxy;
private final Context mContext = this;
private SignalRService mService;
private SignalRService mMessageResive;
private boolean mBound = false;
ListView list_item;
EditText editText;
ArrayList<String> listItems;
ArrayAdapter<String> adapter;
ClientTransport transport;
private Handler mHandler; // to display Toast message
private Thread t;
#Override
public void onConfigurationChanged(Configuration newConfig) {
// don't restart the activity. Just process the configuration change
super.onConfigurationChanged(newConfig);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent();
intent.setClass(mContext, SignalRService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
editText = (EditText)findViewById(R.id.edit_message);
ImageButton btn = (ImageButton)findViewById(R.id.btn);
list_item = (ListView)findViewById(R.id.list_item);
listItems = new ArrayList<String>();
/*listItems.add("First Item - added on Activity Create");*/
/* adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, listItems);*/
adapter = new ArrayAdapter<String>(mContext,R.layout.custom_list, R.id.textView,listItems);
list_item.setAdapter(adapter);
final Handler handler = new Handler();
handler.postDelayed( new Runnable() {
#Override
public void run() {
adapter.notifyDataSetChanged();
handler.postDelayed( this, 1000 );
}
}, 1000 );
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
listItems.add(editText.getText().toString());
adapter.notifyDataSetChanged();
sendMessage(view);
}
});
}
#Override
protected void onStop() {
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
super.onStop();
}
public void sendMessage(View view) {
if (mBound) {
String message = editText.getText().toString();
String email = "kn#yopmail.com";
String name = "Kunal From Android";
String group ="1";
mService.sendMessage(name,email,group,message);
editText.setText("");
// Call a method from the SignalRService.
// However, if this call were something that might hang, then this request should
// occur in a separate thread to avoid slowing down the activity performance.
/*EditText editText = (EditText) findViewById(R.id.edit_message);
if (editText != null && editText.getText().length() > 0) {
}*/
}
}
public void setmMessageResive(JsonElement jsonElement)
{
listItems.add(10, String.valueOf(jsonElement));
}
/**
* Defines callbacks for service binding, passed to bindService()
*/
private final ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
// We've bound to SignalRService, cast the IBinder and get SignalRService instance
SignalRService.LocalBinder binder = (SignalRService.LocalBinder) iBinder;
mService = binder.getService();
mBound = true;
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
#Override
public void doSomething(String msg) {
listItems.add(msg);
}
}
Service code
package myapp.chatapp;
import android.app.Service;
import android.bluetooth.BluetoothClass;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
import com.google.gson.JsonElement;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.logging.Logger;
import microsoft.aspnet.signalr.client.Action;
import microsoft.aspnet.signalr.client.Credentials;
import microsoft.aspnet.signalr.client.LogLevel;
import microsoft.aspnet.signalr.client.MessageReceivedHandler;
import microsoft.aspnet.signalr.client.Platform;
import microsoft.aspnet.signalr.client.SignalRFuture;
import microsoft.aspnet.signalr.client.http.Request;
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.hubs.SubscriptionHandler2;
import microsoft.aspnet.signalr.client.hubs.SubscriptionHandler4;
import microsoft.aspnet.signalr.client.transport.ClientTransport;
import microsoft.aspnet.signalr.client.transport.LongPollingTransport;
import microsoft.aspnet.signalr.client.transport.ServerSentEventsTransport;
/**
* Created by NULLPLEX7 on 11/28/2017.
*/
public class SignalRService extends Service {
private HubConnection mHubConnection;
private HubProxy mHubProxy;
private Handler mHandler; // to display Toast message
private final IBinder mBinder = new LocalBinder(); // Binder given to clients
ClientTransport transport;
registerListener registerListener;
private MainActivity setmMessageResive;
public Something list;
public SignalRService() {
}
#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) {
// Return the communication channel to the service.
startSignalR();
return mBinder;
}
/**
* Class used for the client Binder. Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
public SignalRService getService() {
// Return this instance of SignalRService so clients can call public methods
return SignalRService.this;
}
}
/**
* method for clients (activities)
*/
public void sendMessage(String name, String email, String group, String msg ) {
String SERVER_METHOD_SEND = "BroadCastMessage";
mHubProxy.invoke(SERVER_METHOD_SEND, name,email,group,msg);
}
private void startSignalR() {
Platform.loadPlatformComponent(new AndroidPlatformComponent());
Credentials credentials = new Credentials() {
#Override
public void prepareRequest(Request request) {
request.addHeader("User-Name", "BNK");
}
};
String serverUrl = "myurlhere";
mHubConnection = new HubConnection(serverUrl);
mHubConnection.setCredentials(credentials);
String SERVER_HUB_CHAT = "ChatHub";
mHubProxy = mHubConnection.createHubProxy(SERVER_HUB_CHAT);
ClientTransport clientTransport = new ServerSentEventsTransport(mHubConnection.getLogger());
SignalRFuture<Void> signalRFuture = mHubConnection.start(clientTransport);
mHubProxy.subscribe(this);
transport = new LongPollingTransport(mHubConnection.getLogger());
mHubConnection.start(transport);
/* ****new codes here**** */
/* ****seems useless but should be here!**** */
mHubProxy.subscribe(new Object() {
#SuppressWarnings("unused")
public void newMessage(final String message, final String messageId, final String chatId,
final String senderUserId, final String fileUrl, final String replyToMessageId) {
}
});
try {
signalRFuture.get();
}catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
return;
}
mHubProxy.on("receiveGroupMessage",
new SubscriptionHandler4<String, String, String, String>() {
#Override
public void run(final String name,final String msg ,final String avtar,final String date ) {
final String finalMsg = name + " says " + msg;
/*final String finalMsg = msg;*/
// display Toast message
mHandler.post(new Runnable() {
#Override
public void run() {
list.doSomething(msg);
}
});
}
}
, String.class,String.class,String.class,String.class);
mHubConnection.received(new MessageReceivedHandler() {
#Override
public void onMessageReceived(final JsonElement json) {
Log.e("receiveGroupMessage ", json.toString());
mHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), ""+json, Toast.LENGTH_SHORT).show();
}
});
}
});
}
public interface Something
{
void doSomething(String msg);
}
}
i read on stack overflow that in onMessageReceived i get the server responses but i did not get any response here . I want when any one send message in group from web i want that message in my chat app someone suggest me that i need to create Event listener but i don't no how to create it . please tell me how do i get messages in my chat app.
mHubProxy.on("receiveGroupMessage",
new SubscriptionHandler4<String, String, String, String>() {
#Override
public void run(final String name,final String msg ,final String avtar,final String date ) {
final String finalMsg = name + " says " + msg;
/*final String finalMsg = msg;*/
// display Toast message
mHandler.post(new Runnable() {
#Override
public void run() {
list.doSomething(msg);
}
});
}
}
, String.class,String.class,String.class,String.class);
i thought that i got messages here but execution not go inside the Run.
Any Help is Welcome
First of all, I know there is so much questions are already asked about this voice recognition in background or service. I think I've checked all of them in 2 weeks :P. But I did not understand all these answers. I also used there code but it's not working.
What I want is when user clicks on a button to start voice recognition service then the service starts and even the android is locked the service listen instructions from the user.
Can somebody tell me how can I achieve this or any tutorials.
I'm working on this from 2 weeks. I have searched a lot on google and SO also.
==================Update==============================
I'm Calling a Service in MainActivity but the service is started and and also receive the message but the RecognitionListener class methods did not start. I'm using the code from this
Android Speech Recognition Continuous Service
Can somebody tell me what's going wrong in my code....
This is MainActivity
package com.android.jarvis.voicerecognitionservice;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import static com.android.jarvis.voicerecognitionservice.BuildConfig.DEBUG;
public class MainActivity extends AppCompatActivity {
static final String TAG = "Service";
private int mBindFlag;
private Messenger mServiceMessenger;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Intent service = new Intent(MainActivity, RecognitionService.class);
startService(new Intent(this, RecognitionService.class));
mBindFlag = Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH ? 0 : Context.BIND_ABOVE_CLIENT;
}
#Override
protected void onStart()
{
super.onStart();
bindService(new Intent(this, RecognitionService.class), mServiceConnection, mBindFlag);
}
#Override
protected void onStop()
{
super.onStop();
if (mServiceMessenger != null)
{
unbindService(mServiceConnection);
mServiceMessenger = null;
}
}
private final ServiceConnection mServiceConnection = new ServiceConnection()
{
#Override
public void onServiceConnected(ComponentName name, IBinder service)
{
if (DEBUG) {Log.d(TAG, "onServiceConnected");} //$NON-NLS-1$
mServiceMessenger = new Messenger(service);
Message msg = new Message();
msg.what = RecognitionService.MSG_RECOGNIZER_START_LISTENING;
try
{
mServiceMessenger.send(msg);
Log.d(TAG,"Message Sent");
}
catch (RemoteException e)
{
e.printStackTrace();
}
}
#Override
public void onServiceDisconnected(ComponentName name)
{
if (DEBUG) {
Log.d(TAG, "onServiceDisconnected");} //$NON-NLS-1$
mServiceMessenger = null;
}
}; //
}
This is Recognition Service
package com.android.jarvis.voicerecognitionservice;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.speech.RecognitionListener;
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import android.util.Log;
import android.widget.Toast;
import java.lang.ref.WeakReference;
import static com.android.jarvis.voicerecognitionservice.MainActivity.TAG;
public class RecognitionService extends Service {
static AudioManager mAudioManager;
protected SpeechRecognizer mSpeechRecognizer;
protected Intent mSpeechRecognizerIntent;
protected final Messenger mServerMessenger = new Messenger(new IncomingHandler(this));
static boolean mIsListening;
static volatile boolean mIsCountDownOn;
static boolean mIsStreamSolo;
static final int MSG_RECOGNIZER_START_LISTENING = 1;
static final int MSG_RECOGNIZER_CANCEL = 2;
#Override
public void onCreate()
{
super.onCreate();
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
mSpeechRecognizer.setRecognitionListener(new SpeechRecognitionListener());
mSpeechRecognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE,
this.getPackageName());
Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT).show();
}
protected static class IncomingHandler extends Handler
{
private WeakReference<RecognitionService> mtarget;
IncomingHandler(RecognitionService target)
{
mtarget = new WeakReference<RecognitionService>(target);
}
#Override
public void handleMessage(Message msg)
{
final RecognitionService target = mtarget.get();
switch (msg.what)
{
case MSG_RECOGNIZER_START_LISTENING:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
{
// turn off beep sound
// if (!mIsStreamSolo)
// {
// mAudioManager.setStreamSolo(AudioManager.STREAM_VOICE_CALL, true);
// mIsStreamSolo = true;
// }
}
if (!target.mIsListening)
{
target.mSpeechRecognizer.startListening(target.mSpeechRecognizerIntent);
target.mIsListening = true;
Log.d(TAG, "message start listening"); //$NON-NLS-1$
}
break;
case MSG_RECOGNIZER_CANCEL:
if (mIsStreamSolo)
{
mAudioManager.setStreamSolo(AudioManager.STREAM_VOICE_CALL, false);
mIsStreamSolo = false;
}
target.mSpeechRecognizer.cancel();
target.mIsListening = false;
Log.d(TAG, "message canceled recognizer"); //$NON-NLS-1$
break;
}
}
}
// Count down timer for Jelly Bean work around
protected CountDownTimer mNoSpeechCountDown = new CountDownTimer(5000, 5000)
{
#Override
public void onTick(long millisUntilFinished)
{
// TODO Auto-generated method stub
}
#Override
public void onFinish()
{
mIsCountDownOn = false;
Message message = Message.obtain(null, MSG_RECOGNIZER_CANCEL);
try
{
mServerMessenger.send(message);
message = Message.obtain(null, MSG_RECOGNIZER_START_LISTENING);
mServerMessenger.send(message);
}
catch (RemoteException e)
{
}
}
};
#Override
public void onDestroy()
{
super.onDestroy();
if (mIsCountDownOn)
{
mNoSpeechCountDown.cancel();
}
if (mSpeechRecognizer != null)
{
mSpeechRecognizer.destroy();
}
}
#Override
public IBinder onBind(Intent intent)
{
Log.d(TAG, "onBind"); //$NON-NLS-1$
return mServerMessenger.getBinder();
}
protected class SpeechRecognitionListener implements RecognitionListener
{
#Override
public void onBeginningOfSpeech()
{
// speech input will be processed, so there is no need for count down anymore
if (mIsCountDownOn)
{
mIsCountDownOn = false;
mNoSpeechCountDown.cancel();
}
Log.d(TAG, "onBeginingOfSpeech"); //$NON-NLS-1$
}
#Override
public void onBufferReceived(byte[] buffer)
{
}
#Override
public void onEndOfSpeech()
{
Log.d(TAG, "onEndOfSpeech"); //$NON-NLS-1$
}
#Override
public void onError(int error)
{
if (mIsCountDownOn)
{
mIsCountDownOn = false;
mNoSpeechCountDown.cancel();
}
mIsListening = false;
Message message = Message.obtain(null, MSG_RECOGNIZER_START_LISTENING);
try
{
mServerMessenger.send(message);
}
catch (RemoteException e)
{
}
Log.d(TAG, "error = " + error); //$NON-NLS-1$
}
#Override
public void onEvent(int eventType, Bundle params)
{
}
#Override
public void onPartialResults(Bundle partialResults)
{
}
#Override
public void onReadyForSpeech(Bundle params)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
{
mIsCountDownOn = true;
mNoSpeechCountDown.start();
}
Log.d(TAG, "onReadyForSpeech"); //$NON-NLS-1$
}
#Override
public void onResults(Bundle results)
{
Log.d(TAG, "onResults"); //$NON-NLS-1$
}
#Override
public void onRmsChanged(float rmsdB)
{
}
}
}
You should implement an RecognitionService.
https://developer.android.com/reference/android/speech/RecognitionService
There is an demo example from android:
https://android.googlesource.com/platform/development/+/master/samples/VoiceRecognitionService/
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.