Google Fit can't be read in background? - android

I am trying to read Google Fit data in my app. I have written the code and it works great. I created an AlarmMangaer and put the fit data read in there but it seems like even though the alarm is being called, the fit data is not read unless the app is open and in the foreground. Here is the code I have:
public class MainActivity extends AppCompatActivity implements OnDataPointListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final int REQUEST_OAUTH = 1;
private static final String TAG = "FITTEST";
AlarmManager alarmMgr;
PendingIntent pendingIntent;
private static final String AUTH_PENDING = "auth_state_pending";
private boolean authInProgress = false;
public static GoogleApiClient mClient = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
authInProgress = savedInstanceState.getBoolean(AUTH_PENDING);
}
buildFitnessClient();
}
private void buildFitnessClient() {
// Create the Google API Client
mClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.HISTORY_API)
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
.addConnectionCallbacks(this)
.enableAutoManage(this, 0, this)
.build();
}
#Override
protected void onStart() {
super.onStart();
// Connect to the Fitness API
Log.i(TAG, "Connecting...");
mClient.connect();
}
#Override
protected void onStop() {
super.onStop();
if (mClient.isConnected()) {
mClient.disconnect();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_OAUTH) {
authInProgress = false;
if (resultCode == RESULT_OK) {
// Make sure the app is not already connected or attempting to connect
if (!mClient.isConnecting() && !mClient.isConnected()) {
mClient.connect();
}
}
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
private void registerFitnessDataListener(DataSource dataSource, DataType dataType) {
SensorRequest request = new SensorRequest.Builder()
.setDataSource( dataSource )
.setDataType( dataType )
.setSamplingRate( 3, TimeUnit.SECONDS )
.build();
Fitness.SensorsApi.add( mClient, request, (OnDataPointListener) this)
.setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
if (status.isSuccess()) {
Log.e( "GoogleFit", "SensorApi successfully added" );
}
}
});
}
#Override
public void onDataPoint(DataPoint dataPoint) {
for( final Field field : dataPoint.getDataType().getFields() ) {
final Value value = dataPoint.getValue( field );
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "Field: " + field.getName() + " Value: " + value, Toast.LENGTH_SHORT).show();
}
});
}
}
#Override
public void onConnected(#Nullable Bundle bundle) {
Toast.makeText(this, "OnConnected", Toast.LENGTH_SHORT).show();
Intent alarmIntent = new Intent(this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);
startAlarmManager();
}
public void startAlarmManager() {
Intent dialogIntent = new Intent(getBaseContext(), AlarmReceiver.class);
alarmMgr = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
pendingIntent = PendingIntent.getBroadcast(this, 0, dialogIntent,PendingIntent.FLAG_CANCEL_CURRENT);
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(), 10000, pendingIntent);
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
Here is the Alarm Service:
public class AlarmReceiver extends BroadcastReceiver {
String steps = "";
private GoogleApiClient mGoogleApiClient = MainActivity.mClient;
private Context mContext;
#Override
public void onReceive(Context context, Intent intent) {
this.mContext = context;
Log.d("ALARM", "JR Alarm Service running");
sendNotification("JR Fitness Alarm!!");
new ViewTodaysStepCountTask().execute();
}
private void displayStepDataForToday() {
if (mGoogleApiClient != null ) {
DailyTotalResult result = Fitness.HistoryApi.readDailyTotal(mGoogleApiClient, DataType.TYPE_STEP_COUNT_DELTA).await(1, TimeUnit.MINUTES);
showDataSet(result.getTotal());
} else {
Toast.makeText(mContext, "Google Client Empty", Toast.LENGTH_SHORT).show();
}
}
private void showDataSet(DataSet dataSet) {
Log.e("History", "Data returned for Data type: " + dataSet.getDataType().getName());
DateFormat dateFormat = DateFormat.getDateInstance();
DateFormat timeFormat = DateFormat.getTimeInstance();
for (DataPoint dp : dataSet.getDataPoints()) {
for(Field field : dp.getDataType().getFields()) {
if (field.getName().equals("steps")) {
String steps = dp.getValue(field).toString();
if (! steps.isEmpty()) {
Log.e("Alarm Receiver History", "\tField: " + field.getName() +
" Value: " + dp.getValue(field));
Log.e ("Alarm", "Steps Count: " + steps);
ServerIntf serverIntf = new ServerIntf();
serverIntf.SendStepCount(mContext, steps);
}
}
}
}
}
private class ViewTodaysStepCountTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... params) {
displayStepDataForToday();
return null;
}
protected void onPostExecute(Long result) {
Log.e ("STEPS", "Steps returned");
}
}
public void sendNotification(String text) {
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(mContext)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentTitle("My notification")
.setContentText("Hello World! " + text );
NotificationManager mNotificationManager =
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(002, mBuilder.build());
}
}

Your google api client is most likely null because you are referencing your client as a static variable, but it is most likely null or disconnected by the time the alarm manager starts your service. You need to start your client in the service and use that live client. Here is where you need to look to make the fix:
private GoogleApiClient mGoogleApiClient = MainActivity.mClient;

Related

i want to call an api function continously 24*7 with the timer of 1 minute in background , it works fine in intial time ,after 15 minutes it stops

please help i am new to Android , I want to call this API background continuously 24*7(all time),
but this code runs few minutes and then it stops working, is there any other solution to work this code continuously(non-stop) background with timer?. here I'm using foreground service but no use.
SmsForegroundService.class
public class SmsForegroundService extends Service{
Context mContext;
private BroadcastReceiver receiver;
private static final String SENT = "SMS_SENT";
private static final String TAG = "TEST123";
private APIInterface apiInterface;
public static Handler handler;
public static Runnable myRunnable;
private SMSReceiver smsReceiver;
private AppPreferences appPreferences;
private IntentFilter mIntentFilter;
String responseTimer = "1";
private int j = 1 ;
private Runnable runnable;
private static final String TAGs = SmsForegroundService.class.getSimpleName();
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate: ");
handler = new Handler();
appPreferences = new AppPreferences(this);
apiInterface = APIClient.getClient().create(APIInterface.class);
handler = new Handler();
runnable = new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "Service is still running",
Toast.LENGTH_LONG).show();
callKeepAliveNotifyApi();
}
};
handler.postDelayed(runnable, 0);
}
#Override
public void onDestroy() {
Log.d(TAG, "onDestroy: service destroyed");
super.onDestroy();
handler.removeCallbacks(myRunnable);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG ,"service running");
final String CHANNEL_ID = "foreground Service ID";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID,
CHANNEL_ID,
NotificationManager.IMPORTANCE_HIGH
);
getSystemService(NotificationManager.class).createNotificationChannel(channel);
Notification.Builder notification = new Notification.Builder(this,CHANNEL_ID)
.setContentText("Service is running")
.setContentTitle("Service is enabled")
.setSmallIcon(R.drawable.alert);
startForeground(1001, notification.build());
}
return START_STICKY;
}
private void callKeepAliveNotifyApi() {
try{
String token = appPreferences.getRegisterToken();
System.out.println("token "+token);
Call<KeepAliveResponse> response = apiInterface.KeepAliveNotification(token);
response.enqueue(new Callback<KeepAliveResponse>() {
#RequiresApi(api = Build.VERSION_CODES.P)
#Override
public void onResponse(#NonNull Call<KeepAliveResponse> call, #NonNull Response<KeepAliveResponse> response) {
if (response.code() == 200) {
KeepAliveResponse resObj = response.body();
assert resObj != null;
if(resObj.getStatus().equals("success"))
{
Toast.makeText(getApplicationContext(), "keep-alive " + j, Toast.LENGTH_SHORT).show();
System.out.println( "delay : " + j);
j++;
appPreferences.setTimer(resObj.getTimeInterval());
int correctTimer = Integer.parseInt(appPreferences.getTimer());
correctTimer = correctTimer * 60000;
handler.postDelayed(runnable, correctTimer);
System.out.println("timer :"+appPreferences.getTimer());
}else {
Toast.makeText(getApplicationContext(), resObj.getStatusMessage(), Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(getApplicationContext(), "response error", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(#NonNull Call<KeepAliveResponse> call, #NonNull Throwable t)
{
Log.d("Response", "fail");
call.clone().enqueue(this);
}
});
System.out.println( "sdsd" +appPreferences.getTimer());
}
catch(Exception e)
{
e.printStackTrace();
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind: ");
return null;
}
}
in Mainactivity.class here I added code to call that foreground service class.
public class MainActivity extends AppCompatActivity {
private LinearLayout notification,settings,exitApp;
private ImageView backButton,logoutButton;
private TextView ScreenTitle;
private AppPreferences appPreferences;
private Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
appPreferences = new AppPreferences(this);
Intent serviceIntent = new Intent(this, SmsForegroundService.class);
ContextCompat.startForegroundService(this,serviceIntent);
}
inside Manifest file added this foreground class.
<service
android:name="com.xyz.app.services.SmsForegroundService"
android:enabled="true"
android:exported="false" />

How to save state of a progressbar when app is killed?

I am building a simple downloader app, with a pause/resume button. When I click on pause button and kill the app the download progress isn't shown anymore, after I open the app again. I want to save the download progress state even if the app is killed. Can anyone help me with this? I'm building the app using download manager pro library from github.
here's the code:
Activity Class:
public class MainActivity extends AppCompatActivity {
String[] permissions = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
public static final int REQUEST_ID_MULTIPLE_PERMISSIONS = 100;
EditText edt_url;
Button btn_download;
TextView fileNametv, ProgressbarTv;
private MyDownloadService mService;
ProgressBar progressBar;
String filename, url;
/* UrlFileNameListener listener;*/
Integer progress;
MyReceiver receiver;
public static MainActivity instance;
/* RecyclerView recyclerView;
List<Model> downloadList;
LinearLayoutManager manager;
DownloadAdapter adapter;
// ImageView pausebtn;
int position;*/
File myDirectory;
Boolean mBound = false;
Button pause_btn;
int tasktoken;
/* Model model;
Parcelable mListState;
private final String KEY_RECYCLER_STATE = "recycler_state";
private final String KEY_LIST_STATE = "list_state";*/
private ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mBound = true;
MyDownloadService.LocalBinder localBinder = (MyDownloadService.LocalBinder) iBinder;
mService = localBinder.getService();
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
mBound = false;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* if(savedInstanceState!=null){
mListState = savedInstanceState.getParcelable(KEY_RECYCLER_STATE);
downloadList =savedInstanceState.getParcelableArrayList(KEY_LIST_STATE);
} */
setContentView(R.layout.activity_main);
edt_url = findViewById(R.id.edt_url);
btn_download = findViewById(R.id.btn_download);
pause_btn = findViewById(R.id.pause_resume);
/*recyclerView = findViewById(R.id.recycler_view);
downloadList = new ArrayList<>();
manager = new LinearLayoutManager(this);
adapter = new DownloadAdapter(downloadList, this);
recyclerView.setLayoutManager(manager);
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
manager.getOrientation());
recyclerView.addItemDecoration(dividerItemDecoration);
recyclerView.setAdapter(adapter);*/
fileNametv = findViewById(R.id.download_file_name);
ProgressbarTv = findViewById(R.id.progress_tv);
progressBar = findViewById(R.id.download_progress);
// pausebtn = findViewById(R.id.pause_resume);
instance = this;
/* if (progress!= null && filename != null) {
savedInstanceState.putInt("progress", progress);
savedInstanceState.putString("filename",filename);
// savedInstanceState.putString("filename", model.getFileName());
// savedInstanceState.putParcelable("list",mListState);
}*/
receiver = new MyReceiver();
btn_download.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getDownloadProcess();
}
});
pause_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mService.pauseDownload(tasktoken);
}
});
LocalBroadcastManager.getInstance(this)
.registerReceiver(receiver,
new IntentFilter("download"));
if (checkAndRequestPermissions()) {
myDirectory = new File(Environment.getExternalStorageDirectory() + "/" + "RITSDownloads2");
if (!myDirectory.exists()) {
myDirectory.mkdir();
}
}
}
#Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this,MyDownloadService.class);
bindService(intent,mServiceConnection,Context.BIND_AUTO_CREATE);
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("progress", progress);
outState.putString("filename",filename);
/* mListState = manager.onSaveInstanceState();
outState.putParcelable(KEY_RECYCLER_STATE,mListState);
outState.putParcelableArrayList(KEY_LIST_STATE, (ArrayList<? extends Parcelable>) adapter.getDownloadList());*/
}
#Override
protected void onPause() {
super.onPause();
//mListState = manager.onSaveInstanceState();
}
#Override
protected void onResume() {
super.onResume();
// manager.onRestoreInstanceState(mListState);
}
#Override
public void onBackPressed() {
progress = progressBar.getProgress();
super.onBackPressed();
}
/* #Override
public void onRestoreInstanceState(Bundle savedInstanceState, PersistableBundle persistentState) {
super.onRestoreInstanceState(savedInstanceState, persistentState);
manager.onRestoreInstanceState(mListState);
savedInstanceState.getParcelable(KEY_RECYCLER_STATE);
savedInstanceState.getParcelableArrayList(KEY_LIST_STATE);
}
*/
private void getDownloadProcess() {
url = edt_url.getText().toString();
filename = URLUtil.guessFileName(url, null, null);
//listener.setUrl(url,filename);
edt_url.setText("");
/* model = new Model();
model.setFileName(filename);
downloadList.add(model);
adapter.notifyDataSetChanged();*/
fileNametv.setText(filename);
Intent intent = new Intent(MainActivity.this, MyDownloadService.class);
intent.putExtra("filename", filename);
intent.putExtra("url", url);
intent.setAction(DownloadActions.ACTION.Download_ACTION);
startService(intent);
}
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
progress = intent.getIntExtra("progress", 1);
ReportStructure reportStructure = MyDownloadService.downloadManagerPro.singleDownloadStatus(intent.getIntExtra("tasktoken",1));
tasktoken = intent.getIntExtra("tasktoken",1);
// model.setProgress(progress);
/*int position = downloadList.indexOf(model);
DownloadAdapter.DownloadHolder holder = getDownloadHolder(position);
holder.progressBar.setProgress(progress);*/
progressBar.setProgress(progress);
}
}
/* public DownloadAdapter.DownloadHolder getDownloadHolder(int position) {
return (DownloadAdapter.DownloadHolder) recyclerView.findViewHolderForLayoutPosition(position);
}
*/
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
savedInstanceState.getInt("progress");
savedInstanceState.getString("filename");
/* Log.d("savedInstancestate",savedInstanceState.toString());
//savedInstanceState.getInt("position");
if(savedInstanceState!=null){
List<Model> downloadList = savedInstanceState.getParcelableArrayList(KEY_LIST_STATE);
adapter = new DownloadAdapter(downloadList,this);
}
*/
}
private boolean checkAndRequestPermissions() {
if (ContextCompat.checkSelfPermission(this, permissions[0]) != PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(this, permissions[1]) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, permissions, REQUEST_ID_MULTIPLE_PERMISSIONS);
return false;
} else {
return true;
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String permissions[], #NonNull int[] grantResults) {
String TAG = "LOG_PERMISSION";
Log.d(TAG, "Permission callback called-------");
switch (requestCode) {
case REQUEST_ID_MULTIPLE_PERMISSIONS: {
Map<String, Integer> perms = new HashMap<>();
// Initialize the map with both permissions
perms.put(this.permissions[0], PackageManager.PERMISSION_GRANTED);
perms.put(this.permissions[1], PackageManager.PERMISSION_GRANTED);
// Fill with actual results from user
if (grantResults.length > 0) {
for (int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
// Check for both permissions
if (perms.get(this.permissions[0]) == PackageManager.PERMISSION_GRANTED
&& perms.get(this.permissions[1]) == PackageManager.PERMISSION_GRANTED
) {
Log.d(TAG, "Phone state and storage permissions granted");
// process the normal flow
//else any one or both the permissions are not granted
//TODO Do your stuff here after permissions granted
} else {
Log.d(TAG, "Some permissions are not granted ask again ");
//permissions is denied (this is the first time, when "never ask again" is not checked) so ask again explaining the usage of permissions
// //shouldShowRequestPermissionRationale will return true
//show the dialog or snackbar saying its necessary and try again otherwise proceed with setup.
if (ActivityCompat.shouldShowRequestPermissionRationale(this, this.permissions[0]) ||
ActivityCompat.shouldShowRequestPermissionRationale(this, this.permissions[1])) {
showDialogOK("Phone state and storage permissions required for this app",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
checkAndRequestPermissions();
break;
case DialogInterface.BUTTON_NEGATIVE:
// proceed with logic by disabling the related features or quit the app.
break;
}
}
});
}
//permissions is denied (and never ask again is checked)
//shouldShowRequestPermissionRationale will return false
else {
Toast.makeText(this, "Go to settings and enable permissions", Toast.LENGTH_LONG)
.show();
//proceed with logic by disabling the related features or quit the app.
}
}
}
}
}
}
private void showDialogOK(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(this)
.setMessage(message)
.setPositiveButton("OK", okListener)
.setNegativeButton("Cancel", okListener)
.create()
.show();
}
}
Service Class:
public class MyDownloadService extends Service implements DownloadManagerListener {
private static final String LOG_TAG = "tag";
public static DownloadManagerPro downloadManagerPro;
File myDirectory;
int taskToken;
String name;
Intent notificationIntent;
Notification notification;
PendingIntent pendingIntent;
private IBinder binder = new LocalBinder();
#Nullable
#Override
public IBinder onBind(Intent intent) {
return binder;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getAction().equals(DownloadActions.ACTION.Download_ACTION)) {
Log.d(LOG_TAG, "Received Start Foreground Intent");
}
name = intent.getStringExtra("filename");
final String url = intent.getStringExtra("url");
Log.d(LOG_TAG, name);
Log.d(LOG_TAG, url);
downloadManagerPro = new DownloadManagerPro(this.getApplicationContext());
downloadManagerPro.init("RITSDownloads2/", 16, this);
myDirectory = new File(Environment.getExternalStorageDirectory() + "/" + "RITSDownloads2");
if (!myDirectory.exists()) {
myDirectory.mkdir();
}
taskToken = downloadManagerPro.addTask(name, url, 16, true, true);
Log.d(LOG_TAG, String.valueOf(taskToken));
try {
downloadManagerPro.startDownload(taskToken);
notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setAction(DownloadActions.ACTION.Download_ACTION);
pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
notification = new NotificationCompat.Builder(this)
.setContentTitle("Downloading")
.setTicker("Rits Download")
.setContentText(name)
.setSmallIcon(android.R.drawable.stat_sys_download)
.setContentIntent(pendingIntent)
.setOngoing(true)
.build();
startForeground(DownloadActions.NOTIFICATION_ID.FOREGROUND_SERVICE,
notification);
// stopForeground(true);
// stopSelf();
} catch (IOException e) {
e.printStackTrace();
}
return START_STICKY;
}
#Override
public void OnDownloadStarted(long taskId) {
Log.d(LOG_TAG, "DownloadStarted");
}
#Override
public void OnDownloadPaused(long taskId) {
}
#Override
public void onDownloadProcess(long taskId, double percent, long downloadedLength) {
final int progress = (int) percent;
final int taskToken = (int) taskId;
// int position = positions.get(taskToken);
notification = new NotificationCompat.Builder(this)
.setContentTitle("Downloading")
.setTicker("Rits Download")
.setContentText(name)
.setSmallIcon(android.R.drawable.stat_sys_download)
.setContentIntent(pendingIntent)
.setOngoing(true)
.setColor(ContextCompat.getColor(this, R.color.colorPrimary))
.setProgress(100, progress, false)
.build();
startForeground(DownloadActions.NOTIFICATION_ID.FOREGROUND_SERVICE,
notification);
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("progress", progress);
intent.setAction("download");
intent.putExtra("tasktoken",taskToken);
ReportStructure structure = downloadManagerPro.singleDownloadStatus(taskToken);
String name =structure.name;
intent.putExtra("name",name);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
}
#Override
public void OnDownloadFinished(long taskId) {
}
#Override
public void OnDownloadRebuildStart(long taskId) {
}
#Override
public void OnDownloadRebuildFinished(long taskId) {
}
public void pauseDownload(int taskToken){
ReportStructure reportStructure = downloadManagerPro.singleDownloadStatus(taskToken);
if(reportStructure.state == TaskStates.DOWNLOADING){
downloadManagerPro.pauseDownload(taskToken);
} else if(reportStructure.state == TaskStates.PAUSED){
try {
downloadManagerPro.startDownload(taskToken);
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void OnDownloadCompleted(long taskId) {
Log.d(LOG_TAG, "Download Complete");
/* MainActivity.instance.pausebtn.post(new Runnable() {
#Override
public void run() {
MainActivity.instance.pausebtn.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_done));
}
});*/
notification = new NotificationCompat.Builder(this)
.setContentTitle("Download Complete")
.setTicker("Rits Download")
.setContentText(name)
.setSmallIcon(R.drawable.ic_action_done)
.setContentIntent(pendingIntent)
.setOngoing(true)
.setColor(ContextCompat.getColor(this, R.color.colorPrimary))
.build();
startForeground(DownloadActions.NOTIFICATION_ID.FOREGROUND_SERVICE,
notification);
}
#Override
public void connectionLost(long taskId) {
}
#Override
public void onTaskRemoved(Intent rootIntent) {
/* Intent restartService = new Intent(getApplicationContext(),this.getClass());
restartService.setPackage(getPackageName());
PendingIntent restartPendingIntent =PendingIntent.getService(getApplicationContext(), 1,restartService, PendingIntent.FLAG_ONE_SHOT);
AlarmManager myAlarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
myAlarmService.set(
AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 1000,
restartPendingIntent);*/
}
public class LocalBinder extends Binder{
public MyDownloadService getService(){
return MyDownloadService.this;
}
}
}
I don't know how you want to save the state but I do know that an activity has a onStop() method that you can override.
The onStop() method runs when the app is killed so I would imagine you would want to do your "saving" in this method.
As for saving something I believe you would want to use the SharedPreferences class. You can find more information about that here.
You can find the lifecycle of an activity here
hope this helps
Save the progress on SharedPreferences onDestroy() and retrieve it from there when activity is created.
Cache:
#Override
protected void onDestroy() {
super.onDestroy();
SharedPreferences sharedPreferences = getSharedPreferences("space_name", MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt("progress", progress).apply();
}
And retrieve:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SharedPreferences sharedPreferences = getSharedPreferences("space_name", MODE_PRIVATE);
progress = sharedPreferences.getInt("progress", 0); // 0 default value in case is empty
}

My Android ActivityRecognition implementation is too slow

I used Google ActivityRecognitionApi for tracking whether i am walking or not.
But It seems too slow. What's the problem?
It doesn't related to internet connectivity.
[Walking.java]
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_walking);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(ActivityRecognition.API).addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
mGoogleApiClient.connect();
}
#Override
public void onConnected(Bundle bundle) {
Intent intent = new Intent(this, ActivityRecognitionService.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
ActivityRecognition.ActivityRecognitionApi.requestActivityUpdates(mGoogleApiClient, 1000, pendingIntent);
}
#Override
public void onConnectionSuspended(int i) {
Toast.makeText(Walking.this, "Hello1", Toast.LENGTH_SHORT).show();
Log.e("Connection Failed : ", "Connection Failed");
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Toast.makeText(Walking.this, "Hello2", Toast.LENGTH_SHORT).show();
Log.e("Connection Failed : ", "Connection Failed");
}
[ActivityRecognitionService.java]
import java.util.List;
public class ActivityRecognitionService extends IntentService {
public static final String ACTION_IntentService = "com.example.android.skywalker.RESPONSE";
public static final String ACTIVITY_RESULT = "RESULT";
public Intent localIntent;
public ActivityRecognitionService() {
super("ActivityRecognitionService");
}
public ActivityRecognitionService(String name) {
super(name);
}
#Override
protected void onHandleIntent(Intent intent) {
if(ActivityRecognitionResult.hasResult(intent)) {
ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
handleDetectedActivities(result.getProbableActivities());
}
}
private void handleDetectedActivities(List<DetectedActivity> probableActivities) {
int Flag = 0;
for(DetectedActivity activity : probableActivities) {
if(activity.getType() == DetectedActivity.ON_FOOT) {
Flag = 1;
if (activity.getConfidence() >= 50) Log.e("YES", "YES");
break;
}
}
//Intent intent = new Intent(ActivityRecognitionService.this, Walking.class);
if (Flag == 0) {
//localIntent = new Intent(Walking.BROADCAST_ACTION).putExtra(Walking.RESPONSE_STATUS, "YES");
Log.e("NO", "NO");
}
}
}
I don't think there is any problem with your code, it looks exactly the same as mine.
The normal rate for detection is 3 seconds -> 6 seconds if your "detectionIntervalMillis" value = 0.
But when you switch between 2 different activities (for example: from walking -> in the car....) it will take more, maybe 20s to 40s.

Why Google Awareness Fence doesn't work on a Samsung device?

When i try track a start walking or a stoping walking in a Samsung device, the Awareness doesn't recognise and doesn't update the current state.
Activity:
public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "awareness_poc";
private GoogleApiClient googleApiClient;
private PendingIntent requestPendingIntent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(FenceReceiver.FENCE_RECEIVER_ACTION);
requestPendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, intent, 0);
}
#Override
protected void onStart() {
super.onStart();
googleApiClient = new GoogleApiClient.Builder(this, this, this)
.addApi(Awareness.API)
.build();
googleApiClient.connect();
}
public void removeFences(View view) {
FenceUpdateRequest request = new FenceUpdateRequest.Builder()
.removeFence(WALKING_START_KEY)
.removeFence(WALKING_STOP_KEY)
.build();
Awareness.FenceApi.updateFences(googleApiClient, request)
.setResultCallback(new ResultCallbacks<Status>() {
#Override
public void onSuccess(#NonNull Status status) {
Log.i(TAG, "Fences successfully removed.");
}
#Override
public void onFailure(#NonNull Status status) {
Log.i(TAG, "Fences could NOT be removed.");
}
});
}
#Override
public void onConnected(#Nullable Bundle bundle) {
AwarenessFence walkingStartFence = DetectedActivityFence.starting(DetectedActivityFence.WALKING);
AwarenessFence walkingStopFence = DetectedActivityFence.stopping(DetectedActivityFence.WALKING);
FenceUpdateRequest request = new FenceUpdateRequest.Builder()
.addFence(WALKING_START_KEY, walkingStartFence, requestPendingIntent)
.addFence(WALKING_STOP_KEY, walkingStopFence, requestPendingIntent)
.build();
Awareness.FenceApi.updateFences(googleApiClient, request)
.setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(#NonNull Status status) {
if (status.isSuccess()) {
Log.i(TAG, "Fence was successfully registered.");
} else {
Log.e(TAG, "Fence could not be registered: " + status);
}
}
});
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
}
BroadcastReceiver
ublic class FenceReceiver extends BroadcastReceiver {
public static final String FENCE_RECEIVER_ACTION =
"com.iwsbrazil.lab.awarenesspoc.FENCE_RECEIVER_ACTION";
public static final String WALKING_START_KEY = "walking_start";
public static final String WALKING_STOP_KEY = "walking_stop";
#Override
public void onReceive(Context context, Intent intent) {
FenceState fenceState = FenceState.extract(intent);
if (fenceState.getCurrentState() == FenceState.TRUE) {
if (TextUtils.equals(fenceState.getFenceKey(), WALKING_START_KEY)) {
sendNotification(context, "You Started Walking", 1);
} else if (TextUtils.equals(fenceState.getFenceKey(), WALKING_STOP_KEY)) {
sendNotification(context, "You Stopped Walking", 2);
}
}
}
private void sendNotification(Context context, String text, int id) {
NotificationCompat.Builder builder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Awareness")
.setContentText(text)
.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS);
NotificationManager manager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(id, builder.build());
}
}

GoogleFit wasn't able to connect, so the request failed-Android

I have the following code where it does two main things.
It connects to google play services.
Inside the onConnected() method a service is started, by calling the startService(...) method.
When I run the program I get the following log message.
Connected!!!
Fit wasn't able to connect, so the request failed.
GoogleFitService destroyed.
Here is my code:
public class MainActivity extends ActionBarActivity {
public final static String TAG = "GoogleFitService";
private static final int REQUEST_OAUTH = 1;
private static final String AUTH_PENDING = "auth_state_pending";
private boolean authInProgress = false;
private GoogleApiClient mClient = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buildFitnessClient();
}
private void buildFitnessClient() {
// Create the Google API Client
mClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.API)
.addConnectionCallbacks(
new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected!!!");
// Now you can make calls to the Fitness APIs.
// Put application specific code here.
Intent service = new Intent(MainActivity.this,
GoogleFitService.class);
service.putExtra(GoogleFitService.SERVICE_REQUEST_TYPE,
GoogleFitService.TYPE_REQUEST_CONNECTION);
startService(service);
}
#Override
public void onConnectionSuspended(int i) {
if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST) {
Log.i(TAG, "Connection lost. Cause: Network Lost.");
} else if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
Log.i(TAG, "Connection lost. Reason: Service Disconnected");
}
}
}
)
.addOnConnectionFailedListener(
new GoogleApiClient.OnConnectionFailedListener() {
// Called whenever the API client fails to connect.
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed. Cause: " + result.toString());
if (!result.hasResolution()) {
// Show the localized error dialog
GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), MainActivity.this, 0).show();
return;
}
if (!authInProgress) {
try {
Log.i(TAG, "Attempting to resolve failed connection");
authInProgress = true;
result.startResolutionForResult(MainActivity.this, REQUEST_OAUTH);
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "Exception while starting resolution activity", e);
}
}
}
}
)
.build();
}
#Override
protected void onStart() {
super.onStart();
// Connect to the Fitness API
Log.i(TAG, "Connecting...");
mClient.connect();
Intent service = new Intent(this, GoogleFitService.class);
service.putExtra(GoogleFitService.SERVICE_REQUEST_TYPE, GoogleFitService.TYPE_REQUEST_CONNECTION);
startService(service);
}
#Override
protected void onStop() {
super.onStop();
if (mClient.isConnected()) {
mClient.disconnect();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_OAUTH) {
authInProgress = false;
if (resultCode == RESULT_OK) {
// Make sure the app is not already connected or attempting to connect
if (!mClient.isConnecting() && !mClient.isConnected()) {
mClient.connect();
}
}
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(AUTH_PENDING, authInProgress);
}
}
And the second class is basically an Intent service. Maybe the mistake is here.
public class GoogleFitService extends IntentService {
public static final String TAG = "GoogleFitService";
private GoogleApiClient mGoogleApiFitnessClient;
private boolean mTryingToConnect = false;
public static final String SERVICE_REQUEST_TYPE = "requestType";
public static final int TYPE_GET_STEP_TODAY_DATA = 1;
public static final int TYPE_REQUEST_CONNECTION = 2;
public static final String HISTORY_INTENT = "fitHistory";
public static final String HISTORY_EXTRA_STEPS_TODAY = "stepsToday";
public static final String FIT_NOTIFY_INTENT = "fitStatusUpdateIntent";
public static final String FIT_EXTRA_CONNECTION_MESSAGE =
"fitFirstConnection";
public static final String FIT_EXTRA_NOTIFY_FAILED_STATUS_CODE =
"fitExtraFailedStatusCode";
public static final String FIT_EXTRA_NOTIFY_FAILED_INTENT =
"fitExtraFailedIntent";
#Override
public void onDestroy() {
Log.d(TAG, "GoogleFitService destroyed");
if (mGoogleApiFitnessClient.isConnected()) {
Log.d(TAG, "Disconecting Google Fit.");
mGoogleApiFitnessClient.disconnect();
}
super.onDestroy();
}
#Override
public void onCreate() {
super.onCreate();
buildFitnessClient();
Log.d(TAG, "GoogleFitService created");
}
public GoogleFitService() {
super("GoogleFitService");
}
#Override
protected void onHandleIntent(Intent intent) {
//Get the request type
int type = intent.getIntExtra(SERVICE_REQUEST_TYPE, 1);
//block until google fit connects. Give up after 10 seconds.
if (!mGoogleApiFitnessClient.isConnected()) {
mTryingToConnect = true;
mGoogleApiFitnessClient.connect();
//Wait until the service either connects or fails to connect
while (mTryingToConnect) {
try {
Thread.sleep(100, 0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
if (mGoogleApiFitnessClient.isConnected()) {
if (type == TYPE_GET_STEP_TODAY_DATA) {
Log.d(TAG, "Requesting steps from Google Fit");
getStepsToday();
Log.d(TAG, "Fit update complete. Allowing Android to destroy
the service.");
} else if (type == TYPE_REQUEST_CONNECTION) {
}
} else {
//Not connected
Log.w(TAG, "Fit wasn't able to connect, so the request failed.");
}
}
private void getStepsToday() {
Calendar cal = Calendar.getInstance();
Date now = new Date();
cal.setTime(now);
long endTime = cal.getTimeInMillis();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
long startTime = cal.getTimeInMillis();
final DataReadRequest readRequest = new DataReadRequest.Builder()
.read(DataType.TYPE_STEP_COUNT_DELTA)
.setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
.build();
DataReadResult dataReadResult =
Fitness.HistoryApi.readData(mGoogleApiFitnessClient,
readRequest).await(1, TimeUnit.MINUTES);
DataSet stepData =
dataReadResult.getDataSet(DataType.TYPE_STEP_COUNT_DELTA);
int totalSteps = 0;
for (DataPoint dp : stepData.getDataPoints()) {
for (Field field : dp.getDataType().getFields()) {
int steps = dp.getValue(field).asInt();
totalSteps += steps;
}
}
publishTodaysStepData(totalSteps);
}
private void publishTodaysStepData(int totalSteps) {
Intent intent = new Intent(HISTORY_INTENT);
// You can also include some extra data.
intent.putExtra(HISTORY_EXTRA_STEPS_TODAY, totalSteps);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
private void buildFitnessClient() {
// Create the Google API Client
mGoogleApiFitnessClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.API)
.addScope(new Scope(Scopes.FITNESS_BODY_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_LOCATION_READ_WRITE))
.addConnectionCallbacks(
new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Google Fit connected.");
mTryingToConnect = false;
Log.d(TAG, "Notifying the UI that we're
connected.");
notifyUiFitConnected();
}
#Override
public void onConnectionSuspended(int i) {
// If your connection to the sensor gets lost at
some point,
mTryingToConnect = false;
if (i ==
GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST) {
Log.i(TAG, "Google Fit Connection lost.
Cause:Network Lost.");
} else if (i ==
GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
Log.i(TAG, "Google Fit Connection lost.
Reason:Service Disconnected ");
}
}
}
)
.addOnConnectionFailedListener(
new GoogleApiClient.OnConnectionFailedListener() {
// Called whenever the API client fails to connect.
#Override
public void onConnectionFailed(ConnectionResult
result) {
mTryingToConnect = false;
notifyUiFailedConnection(result);
}
}
)
.build();
}
private void notifyUiFitConnected() {
Intent intent = new Intent(FIT_NOTIFY_INTENT);
intent.putExtra(FIT_EXTRA_CONNECTION_MESSAGE,
FIT_EXTRA_CONNECTION_MESSAGE);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
private void notifyUiFailedConnection(ConnectionResult result) {
Intent intent = new Intent(FIT_NOTIFY_INTENT);
intent.putExtra(FIT_EXTRA_NOTIFY_FAILED_STATUS_CODE,
result.getErrorCode());
intent.putExtra(FIT_EXTRA_NOTIFY_FAILED_INTENT, result.getResolution());
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
Any ideas what might went wrong? Thanks, Theo.
You need to access those detail from fit only when it connected .And Try this
public void buildFitnessClient() {
fitnessClient = new GoogleApiClient.Builder(context)
.addApi(Fitness.HISTORY_API)
.addApi(Fitness.SESSIONS_API)
.addApi(Fitness.RECORDING_API)
.addScope(new Scope(Scopes.FITNESS_BODY_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_LOCATION_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_NUTRITION_READ_WRITE))
.addConnectionCallbacks(
new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
ReferenceWrapper.getInstance(context).setApiClient(fitnessClient);
((OnClientConnectListener) context).onclientConnected();
}
#Override
public void onConnectionSuspended(int i) {
}
})
.addOnConnectionFailedListener(
new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(
ConnectionResult result) {
if (!result.hasResolution()) {
GooglePlayServicesUtil.getErrorDialog(
result.getErrorCode(), context, 0)
.show();
return;
}
if (!authInProgress) {
try {
authInProgress = true;
result.startResolutionForResult(
context,
KeyConstant.REQUEST_OAUTH);
} catch (IntentSender.SendIntentException e) {
}
}
}
}).build();
}
And at first you need to register your application on google api console . Generate an outh2 client id from there and enable fitness api . Search for fitness Api in api Dashboard , and enable it.. And override OnActivityresult
in your Activity .
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == KeyConstant.REQUEST_OAUTH) {
fitnessHelper.setAuthInProgress(false);
if (resultCode == Activity.RESULT_OK) {
if (!fitnessHelper.isConnecting() && !fitnessHelper.isConnected()) {
fitnessHelper.connect();
}
}
}
}

Categories

Resources