I'm developing Google Fit API application and last 2 days I've been trying to store and retrieve data belongs to the BPM data type in different android applications. Meanwhile retrieving it returns zero points, although meanwhile inserting framework reports that everyting is inserted. I created OAuth keys for both applications, each of them has a subscription to this data type. Also I use enableServerQueries() for retrieval.
Datasource is being created as
daataSource=new DataSource.Builder().setName("measurementsSource").setDataType(DataType.TYPE_HEART_RATE_BPM).
setAppPackageName(getApplicationContext())
.setType(TYPE_RAW).build();
Does anyone has any ideas how to fetch data in a proper way?
Upd. According to the advice, I've added full code to add 1 point of custom DataType which I'd like to use. I've tried it number of times, but it still says 'ok' and no data could be available for getting back (for example, with API explorer).
package test.com.cloudydiscoverer;
import android.content.Intent;
import android.content.IntentSender;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.Scopes;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Scope;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.fitness.Fitness;
import com.google.android.gms.fitness.data.DataPoint;
import com.google.android.gms.fitness.data.DataSet;
import com.google.android.gms.fitness.data.DataSource;
import com.google.android.gms.fitness.data.DataType;
import com.google.android.gms.fitness.data.Field;
import com.google.android.gms.fitness.request.DataTypeCreateRequest;
import com.google.android.gms.fitness.result.DataTypeResult;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import static android.content.ContentValues.TAG;
import static com.google.android.gms.fitness.data.DataSource.TYPE_RAW;
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_OAUTH = 1;
private static boolean authInProgress = false;
protected GoogleApiClient googleApiClient = null;
private GoogleApiClient.ConnectionCallbacks connectionCallbacks = null;
private void buildFitnessClient() {
GoogleApiClient.Builder builder = new GoogleApiClient.Builder(this);
builder.addApi(Fitness.RECORDING_API);
builder.addApi(Fitness.SENSORS_API);
builder.addApi(Fitness.BLE_API);
builder.addApi(Fitness.SESSIONS_API);
builder.addApi(Fitness.HISTORY_API);
builder.addApi(Fitness.CONFIG_API);
builder.addScope(new Scope(Scopes.FITNESS_BODY_READ_WRITE)); //TODO; verify scopes
builder.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE));
builder.addScope(new Scope(Scopes.FITNESS_LOCATION_READ_WRITE));
builder.addScope(new Scope(Scopes.FITNESS_BODY_READ_WRITE));
googleApiClient = builder.build();
}
public boolean flag=false;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
connectionCallbacks = new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
/* try {
Thread.sleep(120000);
} catch (InterruptedException e) {
e.printStackTrace();
}
*/
DataTypeCreateRequest request = new DataTypeCreateRequest.Builder()
.setName("test.com.cloudydiscoverer.cloudy_s")
.addField("value", Field.FORMAT_INT32)
.build();
Fitness.ConfigApi.createCustomDataType(googleApiClient, request)
.setResultCallback(new ResultCallback<DataTypeResult>() {
#Override
public void onResult(#NonNull DataTypeResult dataTypeResult) {
if (!dataTypeResult.getStatus().isSuccess()) {
Log.i(TAG, "DataType creation/retrieval failed with result: " + dataTypeResult.getStatus().getStatusMessage());
} else {
Log.i(TAG, "created");
DataSource wSource=new DataSource.Builder().setName(dataTypeResult.getDataType().getName()+".source").setDataType(DataType.TYPE_HEART_RATE_BPM).
setType(TYPE_RAW).setAppPackageName("test.com.cloudydiscoverer").build();
/* DataSource wetSource = new DataSource.Builder()
.setDataType(dataTypeResult.getDataType())
.build();*/
DataPoint b = DataPoint.create(wSource);
b.setTimestamp(System.currentTimeMillis(), TimeUnit.MILLISECONDS);
b.setFloatValues(5.0f);
//b.getValue(dataTypeResult.getDataType().getFields().get(0)).setInt(42);
DataSet dataSet = DataSet.create(wSource);
dataSet.add(b);
Fitness.HistoryApi.insertData(googleApiClient, dataSet).setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(#NonNull Status status) {
Log.i(TAG, String.valueOf(status.isSuccess()));
}
}
);
}
}
});
}
#Override
public void onConnectionSuspended(int i) {
if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST) {
Toast.makeText(MainActivity.this, "Network is unavailable. " +
"Connection will be restored automatically.", Toast.LENGTH_SHORT).show();
} else if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
Toast.makeText(MainActivity.this, "Service has been disconnected. " +
"Connection will be restored automatically.", Toast.LENGTH_SHORT).show();
}
}
};
GoogleApiClient.OnConnectionFailedListener onConnectionFailedListener = new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed with result: " + result.getErrorCode());
if (!result.hasResolution()) {
return;
}
if (!authInProgress) {
try {
Toast.makeText(MainActivity.this, "You need to authorize.", Toast.LENGTH_SHORT).show();
authInProgress = true;
result.startResolutionForResult(MainActivity.this, REQUEST_OAUTH);
} catch (IntentSender.SendIntentException e) {
Toast.makeText(MainActivity.this, "Exception has been caught.", Toast.LENGTH_SHORT).show();
}
}
}
};
Log.i("1","1");
buildFitnessClient();
googleApiClient.registerConnectionCallbacks(connectionCallbacks);
googleApiClient.registerConnectionFailedListener(onConnectionFailedListener);
Log.i("2","2");
googleApiClient.connect();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_OAUTH) {
authInProgress = false;
if (resultCode == RESULT_OK) {
if ((!googleApiClient.isConnected()) || (!googleApiClient.isConnecting()))
googleApiClient.connect();
} else {
Log.i(TAG, "Nothing could be done.");
}
}
}
}
Related
I added achievements to my Google Play game following Google's tutorial. They unlock fine and if I display achievements in-game immediately they show up. If I quit the game and go to the Google Game's app they don't show up and they disappear from in-game also. Any ideas? I've tried multiple accounts. Thanks!
package com.b1stable.tth;
import java.io.File;
import java.io.FileFilter;
import java.util.Locale;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.nio.file.FileSystems;
import java.util.Vector;
import android.os.Bundle;
import android.os.Build;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.net.Uri;
import android.os.Vibrator;
import android.os.VibrationEffect;
import android.util.Log;
import android.view.Surface;
import android.view.Gravity;
import org.libsdl.app.SDLActivity;
import com.b1stable.tth.License_Viewer_Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.auth.api.signin.GoogleSignInResult;
import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.games.AchievementsClient;
import com.google.android.gms.games.AnnotatedData;
import com.google.android.gms.games.EventsClient;
import com.google.android.gms.games.Games;
import com.google.android.gms.games.GamesClient;
import com.google.android.gms.games.LeaderboardsClient;
import com.google.android.gms.games.Player;
import com.google.android.gms.games.PlayersClient;
import com.google.android.gms.games.event.Event;
import com.google.android.gms.games.event.EventBuffer;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.Task.*;
public class TTH_Activity extends SDLActivity
{
final static int LICENSE_REQUEST = 1;
native static void resume_after_showing_license();
native static void resume_after_showing_achievements();
native static void pause();
native static void resume();
// Client used to sign in with Google APIs
private GoogleSignInClient mGoogleSignInClient;
private AchievementsClient mAchievementsClient = null;
private boolean signin_failed = false;
// request codes we use when invoking an external activity
private static final int RC_UNUSED = 5001;
private static final int RC_SIGN_IN = 9001;
// This is so the screen is never cleared pure black, only shim::black (r:35, g:30, b:60)
static boolean paused = false;
private static final String TAG = "TTH";
#Override
public void onCreate(Bundle savedInstance)
{
super.onCreate(savedInstance);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == LICENSE_REQUEST) {
if (data != null) {
if (resultCode == RESULT_OK && data.getExtras().getString("MESSAGE").equals("OK")) {
show_license_result = 0;
}
else if (resultCode == RESULT_CANCELED && data.getExtras().getString("MESSAGE").equals("FAIL")) {
show_license_result = 1;
}
else {
show_license_result = 1;
}
}
else {
show_license_result = 1;
}
resume_after_showing_license();
}
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
if (result.isSuccess()) {
// The signed in account is stored in the result.
GoogleSignInAccount signedInAccount = result.getSignInAccount();
onConnected(signedInAccount);
}
else {
String message = result.getStatus().getStatusMessage();
if (message == null || message.isEmpty()) {
message = "An error occurred!";
}
new AlertDialog.Builder(this).setMessage(message).setNeutralButton(android.R.string.ok, null).show();
onDisconnected();
}
}
}
public void onStart() {
super.onStart();
}
#Override
public void onStop()
{
super.onStop();
pause();
}
#Override
public void onRestart()
{
super.onRestart();
resume();
}
#Override
public void onResume()
{
super.onResume();
signInSilently();
}
#Override
public void onPause()
{
super.onPause();
mAchievementsClient = null;
}
#Override
public void onPostResume()
{
super.onPostResume();
paused = true;
}
public void logString(String s)
{
Log.d("TTH", s);
}
public String getAppdataDir()
{
return getFilesDir().getAbsolutePath();
}
public String getSDCardDir()
{
File f = getExternalFilesDir(null);
if (f != null) {
return f.getAbsolutePath();
}
else {
return getFilesDir().getAbsolutePath();
}
}
static int show_license_result;
public void showLicense()
{
show_license_result = -1;
Intent intent = new Intent(this, License_Viewer_Activity.class);
startActivityForResult(intent, LICENSE_REQUEST);
}
public int getShowLicenseResult()
{
return show_license_result;
}
/*
public void openURL(String url)
{
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
}
*/
public void rumble(int milliseconds)
{
Vibrator v = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
if (v != null && v.hasVibrator()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
v.vibrate(VibrationEffect.createOneShot(milliseconds, VibrationEffect.DEFAULT_AMPLITUDE));
}
else {
v.vibrate(milliseconds);
}
}
}
public boolean has_touchscreen()
{
return getPackageManager().hasSystemFeature("android.hardware.touchscreen");
}
public boolean has_vibrator()
{
Vibrator v = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
if (v != null) {
return v.hasVibrator();
}
else {
return false;
}
}
public void start_draw()
{
if (paused) {
paused = false;
}
}
public String get_android_language()
{
return Locale.getDefault().getLanguage();
}
private static File[] list_dir_files = null;
public void list_dir_start(String path)
{
try {
int slash = path.lastIndexOf('/');
final String glob = path.substring(slash+1).replace("*", ".*"); // +1 works even if not found (-1+1 == 0)
String dir = path.substring(0, slash);
File f = new File(dir);
list_dir_files = f.listFiles(new FileFilter() {
public boolean accept(File f)
{
try {
if (f.getName().matches(glob)) {
return true;
}
else {
return false;
}
}
catch (Exception e) {
Log.d("TTH", "list_dir_start FileFilter throwing " + e.getMessage());
return false;
}
}
});
}
catch (Exception e) {
list_dir_files = null;
Log.d("TTH", "list_dir_start throwing " + e.getMessage());
}
}
public String list_dir_next()
{
if (list_dir_files == null) {
return "";
}
else if (list_dir_files.length == 0) {
list_dir_files = null;
return "";
}
else {
File f = list_dir_files[0];
String name = f.getName();
if (list_dir_files.length == 1) {
list_dir_files = null;
}
else {
File[] new_list = new File[list_dir_files.length-1];
for (int i = 1; i < list_dir_files.length; i++) {
new_list[i-1] = list_dir_files[i];
}
list_dir_files = new_list;
}
return name;
}
}
private static final String ARC_DEVICE_PATTERN = ".+_cheets|cheets_.+";
public boolean is_chromebook()
{
// Google uses this, so should work?
return Build.DEVICE != null && Build.DEVICE.matches(ARC_DEVICE_PATTERN);
}
private static final int RC_ACHIEVEMENT_UI = 9003;
public boolean show_achievements()
{
if (mAchievementsClient == null) {
return false;
}
mAchievementsClient.getAchievementsIntent().addOnSuccessListener(new OnSuccessListener<Intent>() {
#Override
public void onSuccess(Intent intent) {
startActivityForResult(intent, RC_ACHIEVEMENT_UI);
resume_after_showing_achievements();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(Exception e) {
resume_after_showing_achievements();
}
}).addOnCompleteListener(new OnCompleteListener<Intent>() {
#Override
public void onComplete(Task<Intent> task) {
resume_after_showing_achievements();
}
});
return true;
}
public void achieve(String id)
{
if (mAchievementsClient != null) {
mAchievementsClient.unlock(id);
}
}
private void startSignInIntent() {
GoogleSignInClient signInClient = GoogleSignIn.getClient(this, GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN);
Intent intent = signInClient.getSignInIntent();
startActivityForResult(intent, RC_SIGN_IN);
}
private void signInSilently() {
if (signin_failed == true || mAchievementsClient != null) {
return;
}
GoogleSignInOptions signInOptions = GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN;
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
if (GoogleSignIn.hasPermissions(account, signInOptions.getScopeArray())) {
// Already signed in.
// The signed in account is stored in the 'account' variable.
//GoogleSignInAccount signedInAccount = account;
onConnected(account);
}
else {
// Haven't been signed-in before. Try the silent sign-in first.
GoogleSignInClient signInClient = GoogleSignIn.getClient(this, signInOptions);
signInClient.silentSignIn().addOnCompleteListener(
this,
new OnCompleteListener<GoogleSignInAccount>() {
#Override
public void onComplete(#NonNull Task<GoogleSignInAccount> task) {
if (task.isSuccessful()) {
// The signed in account is stored in the task's result.
GoogleSignInAccount signedInAccount = task.getResult();
onConnected(signedInAccount);
}
else {
// Player will need to sign-in explicitly using via UI.
// See [sign-in best practices](http://developers.google.com/games/services/checklist) for guidance on how and when to implement Interactive Sign-in,
// and [Performing Interactive Sign-in](http://developers.google.com/games/services/android/signin#performing_interactive_sign-in) for details on how to implement
// Interactive Sign-in.
startSignInIntent();
}
}
}
);
}
}
public void start_google_play_games_services() {
/*
runOnUiThread(new Runnable() {
public void run() {
signInSilently();
}
});
*/
}
private void onConnected(GoogleSignInAccount googleSignInAccount) {
Log.d(TAG, "onConnected(): connected to Google APIs");
GamesClient gamesClient = Games.getGamesClient(this, googleSignInAccount);
gamesClient.setViewForPopups(findViewById(android.R.id.content));
gamesClient.setGravityForPopups(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
mAchievementsClient = Games.getAchievementsClient(this, googleSignInAccount);
}
private void onDisconnected() {
Log.d(TAG, "onDisconnected()");
mAchievementsClient = null;
signin_failed = true;
}
}
I'm follow the tutorial and implement the google place api to my file.
But I want to change it save to Firebase. Maybe save to a table "Location"
Anyone can guide me how to save it to firebase. The code I refer is from here:https://github.com/delaroy/AndroidLocationGeofencing
Thanks in advance and sorry for if there was lack of information Ii will added again.
Screenshot 1
Screenshot 2
package com.example.edward.neweventmanagementsystem;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.example.edward.neweventmanagementsystem.provider.PlaceContract;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import com.google.android.gms.common.GooglePlayServicesRepairableException;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.places.Place;
import com.google.android.gms.location.places.PlaceBuffer;
import com.google.android.gms.location.places.Places;
import com.google.android.gms.location.places.ui.PlacePicker;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
import java.util.List;
import static android.widget.Toast.LENGTH_SHORT;
public class ManageLocation extends AppCompatActivity implements
ConnectionCallbacks,
OnConnectionFailedListener {
// Constants
public static final String TAG = ManageLocation.class.getSimpleName();
private static final int PERMISSIONS_REQUEST_FINE_LOCATION = 111;
private static final int PLACE_PICKER_REQUEST = 1;
// Member variables
private PlaceListAdapter mAdapter;
private RecyclerView mRecyclerView;
private boolean mIsEnabled;
private GoogleApiClient mClient;
private Geofencing mGeofencing;
private DatabaseReference mDatabaseReference;
Context mContext;
PlaceBuffer mPlaces;
/**
* Called when the activity is starting
*
* #param savedInstanceState The Bundle that contains the data supplied in onSaveInstanceState
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage_location);
// Set up the recycler view
mRecyclerView = (RecyclerView) findViewById(R.id.places_list_recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mAdapter = new PlaceListAdapter(this, null);
mRecyclerView.setAdapter(mAdapter);
// Switch onOffSwitch = (Switch) findViewById(R.id.enable_switch);
// mIsEnabled = getPreferences(MODE_PRIVATE).getBoolean(getString(R.string.setting_enabled), false);
// onOffSwitch.setChecked(mIsEnabled);
// onOffSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
// #Override
// public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// SharedPreferences.Editor editor = getPreferences(MODE_PRIVATE).edit();
// editor.putBoolean(getString(R.string.setting_enabled), isChecked);
// mIsEnabled = isChecked;
// editor.commit();
// if (isChecked) mGeofencing.registerAllGeofences();
// else mGeofencing.unRegisterAllGeofences();
// }
//
// });
mClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.addApi(Places.GEO_DATA_API)
.enableAutoManage(this, this)
.build();
mGeofencing = new Geofencing(this, mClient);
}
/***
* Called when the Google API Client is successfully connected
*
* #param connectionHint Bundle of data provided to clients by Google Play services
*/
#Override
public void onConnected(#Nullable Bundle connectionHint) {
refreshPlacesData();
Log.i(TAG, "API Client Connection Successful!");
}
/***
* Called when the Google API Client is suspended
*
* #param cause cause The reason for the disconnection. Defined by constants CAUSE_*.
*/
#Override
public void onConnectionSuspended(int cause) {
Log.i(TAG, "API Client Connection Suspended!");
}
/***
* Called when the Google API Client failed to connect to Google Play Services
*
* #param result A ConnectionResult that can be used for resolving the error
*/
#Override
public void onConnectionFailed(#NonNull ConnectionResult result) {
Log.e(TAG, "API Client Connection Failed!");
}
public void refreshPlacesData() {
Uri uri = PlaceContract.PlaceEntry.CONTENT_URI;
Cursor data = getContentResolver().query(
uri,
null,
null,
null,
null);
if (data == null || data.getCount() == 0) return;
List<String> guids = new ArrayList<String>();
while (data.moveToNext()) {
guids.add(data.getString(data.getColumnIndex(PlaceContract.PlaceEntry.COLUMN_PLACE_ID)));
}
PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi.getPlaceById(mClient,
guids.toArray(new String[guids.size()]));
placeResult.setResultCallback(new ResultCallback<PlaceBuffer>() {
#Override
public void onResult(#NonNull PlaceBuffer places) {
mAdapter.swapPlaces(places);
mGeofencing.updateGeofencesList(places);
if (mIsEnabled) mGeofencing.registerAllGeofences();
}
});
}
public void onAddPlaceButtonClicked(View view) {
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, getString(R.string.need_location_permission_message), Toast.LENGTH_LONG).show();
return;
}
try {
PlacePicker.IntentBuilder builder = new PlacePicker.IntentBuilder();
Intent i = builder.build(this);
startActivityForResult(i, PLACE_PICKER_REQUEST);
} catch (GooglePlayServicesRepairableException e) {
Log.e(TAG, String.format("GooglePlayServices Not Available [%s]", e.getMessage()));
} catch (GooglePlayServicesNotAvailableException e) {
Log.e(TAG, String.format("GooglePlayServices Not Available [%s]", e.getMessage()));
} catch (Exception e) {
Log.e(TAG, String.format("PlacePicker Exception: %s", e.getMessage()));
}
}
/***
* Called when the Place Picker Activity returns back with a selected place (or after canceling)
*
* #param requestCode The request code passed when calling startActivityForResult
* #param resultCode The result code specified by the second activity
* #param data The Intent that carries the result data.
*/
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PLACE_PICKER_REQUEST && resultCode == RESULT_OK) {
final Place place = PlacePicker.getPlace(this, data);
if (place == null) {
Log.i(TAG, "No place selected");
return;
}
final String placeID = place.getId();
// Insert a new place into DB
// ContentValues contentValues = new ContentValues();
// contentValues.put(PlaceContract.PlaceEntry.COLUMN_PLACE_ID, placeID);
// getContentResolver().insert(PlaceContract.PlaceEntry.CONTENT_URI, contentValues);
//Place the data into Firebase
// Get live data information
refreshPlacesData();
}
}
public void onRingerPermissionsClicked(View view) {
Intent intent = new Intent(android.provider.Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS);
startActivity(intent);
}
public void onLocationPermissionClicked(View view) {
ActivityCompat.requestPermissions(ManageLocation.this,
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
PERMISSIONS_REQUEST_FINE_LOCATION);
}
}
private DatabaseReference mDatabase;
mDatabase = FirebaseDatabase.getInstance().getReference();
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PLACE_PICKER_REQUEST && resultCode == RESULT_OK) {
final Place place = PlacePicker.getPlace(this, data);
if (place == null) {
Log.i(TAG, "No place selected");
return;
}
final String placeID = place.getId();
//Place the data into Firebase
insertPlcaeIdinDb(placeID);
// Get live data information
refreshPlacesData();
}
}
private void insertPlcaeIdinDb(String placeID)
{
mDatabase.child("yourBranchNameinDb").setValue(placeID );
}
To understand what is
FirebaseDatabase.getInstance().getReference()
you can follow Firebase for android official documentation from there
I successfully integrated google drive in my android app. But could not download selected image file.
Here is my code. There is a problem Result call back method is never execute. Kindly help me. And also I used data.getData() method in onActivity result this method only return null. How I can find URI of image?
package com.example.syedfurqan.dropboxintegration;
import android.app.Activity;
import android.content.Intent;
import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;
import android.widget.Toast;
import com.dropbox.chooser.android.DbxChooser;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.drive.Drive;
import com.google.android.gms.drive.DriveApi;
import com.google.android.gms.drive.DriveContents;
import com.google.android.gms.drive.DriveFile;
import com.google.android.gms.drive.DriveId;
import com.google.android.gms.drive.DriveResource;
import com.google.android.gms.drive.Metadata;
import com.google.android.gms.drive.OpenFileActivityBuilder;
import java.io.InputStream;
public class BaseDemoActivity extends Activity implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "BaseDriveActivity";
protected static final int REQUEST_CODE_RESOLUTION = 1;
private static final int REQ_CODE_OPEN = 2;
private GoogleApiClient mGoogleApiClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_base_demo);
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addScope(Drive.SCOPE_APPFOLDER)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
mGoogleApiClient.connect();
}
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
switch (requestCode) {
case REQ_CODE_OPEN:
if (resultCode == RESULT_OK) {
DriveId mFileId = (DriveId) data
.getParcelableExtra(OpenFileActivityBuilder.EXTRA_RESPONSE_DRIVE_ID);
DriveFile selectedFile = mFileId.asDriveFile();
selectedFile.open(mGoogleApiClient, DriveFile.MODE_READ_ONLY, null)
.setResultCallback(idCallback);
} else {
finish();
}
break;
default:
super.onActivityResult(requestCode, resultCode, data);
}
}
#Override
protected void onPause() {
if (mGoogleApiClient != null) {
mGoogleApiClient.disconnect();
}
super.onPause();
}
//Picker
#Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "GoogleApiClient connected");
// Launch user interface and allow user to select file
try {
IntentSender i = Drive.DriveApi
.newOpenFileActivityBuilder()
.setMimeType(new String[]{"image/png", "image/jpeg"})
.build(mGoogleApiClient);
startIntentSenderForResult(i, REQ_CODE_OPEN, null, 0, 0, 0);
} catch (Exception e) {
}
}
final private ResultCallback<DriveApi.DriveContentsResult> idCallback = new ResultCallback<DriveApi.DriveContentsResult>() {
#Override
public void onResult(DriveApi.DriveContentsResult result) {
if (!result.getStatus().isSuccess()) {
// Handle an error
}
DriveContents driveContents = result.getDriveContents();
InputStream is = driveContents.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(is);
Values.setBitmap(bitmap);
}
};
#Override
public void onConnectionSuspended(int cause) {
Log.i(TAG, "GoogleApiClient connection suspended");
}
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "GoogleApiClient connection failed: " + result.toString());
if (!result.hasResolution()) {
// show the localized error dialog.
GoogleApiAvailability.getInstance().getErrorDialog(this, result.getErrorCode(), 0).show();
return;
}
try {
result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);
} catch (SendIntentException e) {
Log.e(TAG, "Exception while starting resolution activity", e);
}
}
/**
* Shows a toast message.
*/
public void showMessage(String message) {
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}
/**
* Getter for the {#code GoogleApiClient}.
*/
public GoogleApiClient getGoogleApiClient() {
return mGoogleApiClient;
}
}
I just used Android Google Drive default API classes for doing my task. And here is code:
//BaseDemoActivity
package com.example.syedfurqan.dropboxintegration;
import android.app.Activity;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.drive.Drive;
public abstract class BaseDemoActivity extends Activity implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "BaseDriveActivity";
protected static final int REQUEST_CODE_RESOLUTION = 1;
/**
* Google API client.
*/
private GoogleApiClient mGoogleApiClient;
#Override
protected void onResume() {
super.onResume();
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addScope(Drive.SCOPE_APPFOLDER) // required for App Folder sample
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
mGoogleApiClient.connect();
}
/**
* Handles resolution callbacks.
*/
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_RESOLUTION && resultCode == RESULT_OK) {
mGoogleApiClient.connect();
}
}
#Override
protected void onPause() {
if (mGoogleApiClient != null) {
mGoogleApiClient.disconnect();
}
super.onPause();
}
/**
* Called when {#code mGoogleApiClient} is connected.
*/
#Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "GoogleApiClient connected");
}
/**
* Called when {#code mGoogleApiClient} is disconnected.
*/
#Override
public void onConnectionSuspended(int cause) {
Log.i(TAG, "GoogleApiClient connection suspended");
}
/**
* Called when {#code mGoogleApiClient} is trying to connect but failed.
* Handle {#code result.getResolution()} if there is a resolution is
* available.
*/
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "GoogleApiClient connection failed: " + result.toString());
if (!result.hasResolution()) {
// show the localized error dialog.
GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), this, 0).show();
return;
}
try {
result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);
} catch (SendIntentException e) {
Log.e(TAG, "Exception while starting resolution activity", e);
}
}
/**
* Shows a toast message.
*/
public void showMessage(String message) {
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}
/**
* Getter for the {#code GoogleApiClient}.
*/
public GoogleApiClient getGoogleApiClient() {
return mGoogleApiClient;
}
}
//Retrieve Content
package com.example.syedfurqan.dropboxintegration;
import android.content.Intent;
import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.widget.ProgressBar;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.drive.Drive;
import com.google.android.gms.drive.DriveApi.DriveContentsResult;
import com.google.android.gms.drive.DriveContents;
import com.google.android.gms.drive.DriveFile;
import com.google.android.gms.drive.DriveFile.DownloadProgressListener;
import com.google.android.gms.drive.DriveId;
import com.google.android.gms.drive.OpenFileActivityBuilder;
import java.io.InputStream;
/**
* An activity to illustrate how to open contents and listen
* the download progress if the file is not already sync'ed.
*/
public class RetreiveContent extends BaseDemoActivity {
private static final String TAG = "RetrieveFileWithProgressDialogActivity";
/**
* Request code to handle the result from file opening activity.
*/
private static final int REQUEST_CODE_OPENER = 1;
/**
* Progress bar to show the current download progress of the file.
*/
private ProgressBar mProgressBar;
/**
* File that is selected with the open file activity.
*/
private DriveId mSelectedFileDriveId;
#Override
protected void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.layout.activity_progress);
mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
mProgressBar.setMax(100);
}
#Override
public void onConnected(Bundle connectionHint) {
super.onConnected(connectionHint);
// If there is a selected file, open its contents.
if (mSelectedFileDriveId != null) {
open();
return;
}
// Let the user pick an mp4 or a jpeg file if there are
// no files selected by the user.
IntentSender intentSender = Drive.DriveApi
.newOpenFileActivityBuilder()
.setMimeType(new String[]{"video/mp4", "image/png", "image/jpeg"})
.build(getGoogleApiClient());
try {
startIntentSenderForResult(intentSender, REQUEST_CODE_OPENER, null, 0, 0, 0);
} catch (SendIntentException e) {
// Log.w(TAG, "Unable to send intent", e);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_OPENER && resultCode == RESULT_OK) {
mSelectedFileDriveId = (DriveId) data.getParcelableExtra(
OpenFileActivityBuilder.EXTRA_RESPONSE_DRIVE_ID);
// open();
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
private void open() {
// Reset progress dialog back to zero as we're
// initiating an opening request.
mProgressBar.setProgress(0);
DownloadProgressListener listener = new DownloadProgressListener() {
#Override
public void onProgress(long bytesDownloaded, long bytesExpected) {
// Update progress dialog with the latest progress.
int progress = (int) (bytesDownloaded * 100 / bytesExpected);
Log.d(TAG, String.format("Loading progress: %d percent", progress));
mProgressBar.setProgress(progress);
}
};
Drive.DriveApi.getFile(getGoogleApiClient(), mSelectedFileDriveId)
.open(getGoogleApiClient(), DriveFile.MODE_READ_ONLY, listener)
.setResultCallback(driveContentsCallback);
mSelectedFileDriveId = null;
}
private ResultCallback<DriveContentsResult> driveContentsCallback =
new ResultCallback<DriveContentsResult>() {
#Override
public void onResult(DriveContentsResult result) {
if (!result.getStatus().isSuccess()) {
showMessage("Error while opening the file contents");
return;
}
DriveContents driveContents = result.getDriveContents();
InputStream is = driveContents.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(is);
Values.setBitmap(bitmap);
//showMessage("File contents opened");
RetreiveContent.this.finish();
}
};
}
UPDATE - edited code to display my broadcast idea. Using the method causes a !!! FAILED BINDER TRANSACTION !!! and no location data to be displayed by toast.
I was wondering if there was an elegant way to separate google fused location services away from activities. My warning class currently implements location services but I have another activity that takes photos. When a photo is taken I want to associate a location with the image. My current idea is to just use my broadcast receiver in my Bluetooth warning class to listen for a broadcast my camera will send and associate it then with a location. I'm not a fan of the idea because it doesn't separate functionality very well so was hoping for some suggestions or patterns. Code for classes below.
CAMERA CLASS
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class CameraOperations extends AppCompatActivity {
public final static String ACTION_PICTURE_RECEIVED = "ACTION_PICTURE_RECEIVED";
public final static String TRANSFER_DATA = "bitmap";
ImageView mImageView;
String photoPath;
int REQUEST_IMAGE_CAPTURE = 1;
File photoFile = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera_view);
mImageView = (ImageView) findViewById(R.id.imageView);
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
Toast.makeText(CameraOperations.this, "No Camera", Toast.LENGTH_SHORT).show();
} else {
dispatchTakePictureIntent();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK){
if(data == null){
Toast.makeText(this, "Data is null", Toast.LENGTH_SHORT);
Bitmap pictureMap = BitmapFactory.decodeFile(photoFile.getAbsolutePath());
mImageView.setImageBitmap(pictureMap);
broadcastUpdate(ACTION_PICTURE_RECEIVED, pictureMap);
}else {
Toast.makeText(this, "Error Occurred", Toast.LENGTH_SHORT).show();
}
}
}
private void broadcastUpdate(final String action, Bitmap picture) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
picture.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] bytes = stream.toByteArray();
Intent intent = new Intent(action);
intent.putExtra(TRANSFER_DATA, bytes);
sendBroadcast(intent);
intent = new Intent(CameraOperations.this, Warning.class);
startActivity(intent);
finish();
}
private File createImageFile() throws IOException {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(imageFileName, ".jpg", storageDir);
photoPath = "file:" + image.getAbsolutePath();
return image;
}
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
try{
photoFile = createImageFile();
}catch(IOException e){
e.printStackTrace();
}
if(photoFile != null){
Uri photoUri = Uri.fromFile(photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
}
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
BLUETOOTH WARNING CLASS
import android.Manifest;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
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.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.location.Location;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
public class Warning extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private final static String TAG = Warning.class.getSimpleName();
private String mDeviceAddress;
private HandleConnectionService mBluetoothLeService;
private boolean quitService;
private final int PLAY_SERVICES_REQUEST_TIME = 1000;
private Location mLastLocation;
private GoogleApiClient mGoogleClient;
private boolean requestingLocationUpdates = false;
private LocationRequest locationRequest;
private int UPDATE_INTERVAL = 10000; // 10 seconds
private int FASTEST_INTERVAL = 5000; // 5 seconds
private int DISTANCEMOVED = 10; //In meters
private final ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
mBluetoothLeService = ((HandleConnectionService.LocalBinder) service).getService();
if (!mBluetoothLeService.initialize()) {
Log.e(TAG, "Unable to initialize Bluetooth");
finish();
}
mBluetoothLeService.connect(mDeviceAddress);
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
mBluetoothLeService = null;
}
};
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (HandleConnectionService.ACTION_GATT_DISCONNECTED.equals(action)) {
if (!quitService) {
mBluetoothLeService.connect(mDeviceAddress);
Log.w(TAG, "Attempting to reconnect");
}
Log.w(TAG, "Disconnected, activity closing");
} else if (HandleConnectionService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
getGattService(mBluetoothLeService.getSupportedGattService());
} else if (HandleConnectionService.ACTION_DATA_AVAILABLE.equals(action)) {
checkWarning(intent.getByteArrayExtra(HandleConnectionService.EXTRA_DATA));
}else if(CameraOperations.ACTION_PICTURE_RECEIVED.equals(action)){
byte[] bytes = intent.getByteArrayExtra("bitmap");
Bitmap picture = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
findLocation();
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
setSupportActionBar(myToolbar);
if (checkGoogleServices()) {
buildGoogleApiClient();
}
quitService = false;
Intent intent = getIntent();
mDeviceAddress = intent.getStringExtra(Device.EXTRA_DEVICE_ADDRESS);
Intent gattServiceIntent = new Intent(this, HandleConnectionService.class);
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
}
#Override
protected void onResume() {
super.onResume();
registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.mainmenu, menu);
MenuItem connect = menu.findItem(R.id.connect);
connect.setVisible(false);
MenuItem disconnect = menu.findItem(R.id.disconnect);
disconnect.setVisible(true);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
Intent intent;
switch (item.getItemId()) {
case R.id.home:
new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Return Home")
.setMessage("Returning home will disconnect you, continue?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
quitService = true;
mBluetoothLeService.disconnect();
mBluetoothLeService.close();
Intent intent = new Intent(Warning.this, Main.class);
startActivity(intent);
}
})
.setNegativeButton("No", null)
.show();
return true;
case R.id.connect:
Toast.makeText(this, "Connect Pressed", Toast.LENGTH_SHORT).show();
return true;
case R.id.disconnect:
disconnectOperation();
intent = new Intent(Warning.this, Main.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
return true;
case R.id.profiles:
Toast.makeText(this, "Profiles Pressed", Toast.LENGTH_SHORT).show();
return true;
case R.id.camera:
Toast.makeText(this, "Camera Pressed", Toast.LENGTH_SHORT).show();
intent = new Intent(Warning.this, CameraOperations.class);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
quitService = true;
mBluetoothLeService.disconnect();
mBluetoothLeService.close();
Intent intent = new Intent(Warning.this, Main.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
return true;
}
return super.onKeyDown(keyCode, event);
}
#Override
protected void onDestroy() {
super.onDestroy();
mBluetoothLeService.disconnect();
mBluetoothLeService.close();
System.exit(0);
}
public boolean disconnectOperation(){
this.quitService = true;
mBluetoothLeService.disconnect();
mBluetoothLeService.close();
return true;
}
private void checkWarning(byte[] byteArray) {
if (byteArray != null) {
for (int i = 0; i < byteArray.length; i++) {
if (byteArray[i] == 48) {
findLocation();
}
}
}
}
private void getGattService(BluetoothGattService gattService) {
if (gattService == null) {
return;
}
BluetoothGattCharacteristic characteristicRx = gattService.getCharacteristic(HandleConnectionService.UUID_BLE_SHIELD_RX);
mBluetoothLeService.setCharacteristicNotification(characteristicRx, true);
mBluetoothLeService.readCharacteristic(characteristicRx);
}
private static IntentFilter makeGattUpdateIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(HandleConnectionService.ACTION_GATT_CONNECTED);
intentFilter.addAction(HandleConnectionService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(HandleConnectionService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(HandleConnectionService.ACTION_DATA_AVAILABLE);
intentFilter.addAction(CameraOperations.ACTION_PICTURE_RECEIVED);
return intentFilter;
}
private boolean checkGoogleServices() {
GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
int available = googleAPI.isGooglePlayServicesAvailable(this);
if (available != ConnectionResult.SUCCESS) {
if (googleAPI.isUserResolvableError(available)) {
googleAPI.getErrorDialog(this, available, PLAY_SERVICES_REQUEST_TIME).show();
}
return false;
}
return true;
}
public void findLocation() {
int REQUEST_CODE_ASK_PERMISSIONS = 123;
double latitude = 0.0;
double longitude = 0.0;
if(Build.VERSION.SDK_INT >= 23){
boolean fineLocationAccess = ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
boolean courseLocationAccess = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
boolean accessGranted = fineLocationAccess && courseLocationAccess;
if (accessGranted) {
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleClient);
if(mLastLocation != null) {
latitude = mLastLocation.getLatitude();
longitude = mLastLocation.getLongitude();
Toast.makeText(this, "latitude: " + latitude + " longitude: " + longitude, Toast.LENGTH_LONG).show();
}else{
Log.i("Warning", "Unable to get Location");
}
}else{
Log.i("Connection", "Request permission");
}
}else{
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleClient);
if(mLastLocation != null) {
latitude = mLastLocation.getLatitude();
longitude = mLastLocation.getLongitude();
Toast.makeText(this, "latitude: " + latitude + " longitude: " + longitude, Toast.LENGTH_LONG).show();
}else{
Log.i("Warning", "Unable to get Location");
}
}
}
public void buildGoogleApiClient() {
mGoogleClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
#Override
public void onConnected(Bundle bundle) {
Log.w("Connected", " : " + mGoogleClient.isConnected());
}
#Override
public void onConnectionSuspended(int i) {
Toast.makeText(this, "Location Services Stopped", Toast.LENGTH_SHORT).show();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Toast.makeText(this, "Location Services Connection Fail", Toast.LENGTH_SHORT).show();
}
#Override
protected void onStart() {
super.onStart();
if (mGoogleClient != null) {
mGoogleClient.connect();
}
}
}
I think your original idea is actually pretty sound as long as you construct it a certain way. The activity that is knowledgeable about the location information can update and store that location independent of any other activity. This would probably be ideal to have as a service actually that runs every x amount of time, or when the location changes.
Inside of that same class you can have a generic broadcast receiver that handles request for that location information. You can make this as generic as you want in terms of allowing other applications/activities you make also being to leverage it, as long as the location data is returned in a way that is usable to each requester.
From within your activity that takes photos (and eventually any activity you desire), when you take a photo, you can send a broadcast requesting that location information, with some default or null info if none is returned. One of the complexities is knowing how long to wait for this location info before completing. In this scenario the location activity is the 'generalized' one in that multiple activities can request location data if you construct it correctly.
Another potentially robust approach is to make the photo taking activity the generalized one. One way to do this is that when you take a photo, you can have your photo activity send broadcast to the location activity that contains the photos filepath/uri/identifying information, but you don't wait for a response. Instead, you make the location activity listen for this broadcast, and write to the photos meta data with the location using the provided identifying info to find said photo. In this way your photo taking app isn't stuck waiting for the location activity to finish (or event start if it ever does).
Good luck, sounds like a fun project.
In one section of my android application, user can import CSV files into the application. To do so, users must allow the app to have access to their Google drive. I accomplish this by using the Google Drive API Sign in, and allow users to only be able to choose CSV files.When in debug mode, the below code works perfectly. However after release of the app the users are never logged in.
in debug mode:
https://www.youtube.com/watch?v=aFj_fn13x2c&feature=youtu.be
released version: https://www.youtube.com/watch?v=pq2POP43waM
Permissions:
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.util.Patterns;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.common.api.GoogleApiActivity;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.Scope;
import com.google.android.gms.drive.Drive;
import com.google.android.gms.drive.DriveClient;
import com.google.android.gms.drive.DriveContents;
import com.google.android.gms.drive.DriveFile;
import com.google.android.gms.drive.DriveId;
import com.google.android.gms.drive.DriveResourceClient;
import com.google.android.gms.drive.Metadata;
import com.google.android.gms.drive.OpenFileActivityBuilder;
import com.google.android.gms.drive.OpenFileActivityOptions;
import com.google.android.gms.drive.query.Filters;
import com.google.android.gms.drive.query.SearchableField;
import com.google.android.gms.tasks.Continuation;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.TaskCompletionSource;
import com.google.android.gms.tasks.Tasks;
import com.google.gson.Gson;
import com.project.danielo.eventer.Custom_Classes.AddAndEditMethods;
import com.project.danielo.eventer.Custom_Classes.CSVExporter;
import com.project.danielo.eventer.Custom_Classes.CustomDateParser;
import com.project.danielo.eventer.Custom_Classes.CustomRegex;
import com.project.danielo.eventer.StaticVariables;
import com.project.danielo.eventer.adapter.CustomEventObject;
import com.project.danielo.eventer.dialog_fragments.NotificationSettings;
import com.project.danielo.eventer.notification_package.CustomNotification;
import com.project.danielo.eventer.sqllite.DBHandler;
import com.project.danielo.eventer.R;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.io.StringWriter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import static android.app.Activity.RESULT_OK;
public class SettingsFragments extends Fragment {
public SettingsFragments(){
}
private View settingsView;
Button
btnImportEvents, btnDriveSettings;
ProgressBar progressBar;
GoogleApiClient apiClient;
private static final String TAG = "Google drive activity";
private static final int REQUEST_CODE_OPENER = 15;
private static final int REQUEST_CODE_SIGN_IN = 16;
private static final int REQUEST_CODE_OPEN_ITEM = 1;
private DriveId driveId;
private DriveClient driveClient;
private OpenFileActivityOptions openFileActivityOptions;
private DriveResourceClient resourceClient;
private TaskCompletionSource<DriveId> mOpenItemTaskSource;
private DriveContents driveContents;
private Metadata metadata;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
signIn();
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
settingsView = inflater.inflate(R.layout.layout_for_settings_fragment, null, false);
btnImportEvents = (Button)settingsView.findViewById(R.id.btn_import_events);
btnDriveSettings = (Button)settingsView.findViewById(R.id.btn_google_drive_settings);
progressBar = (ProgressBar)settingsView.findViewById(R.id.settings_progress_bar);
/*Upon this button click, the app checks if user is logged
* before giving user access to Google Drive account
*/
btnImportEvents.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!isConnectedToTheInternet()) {
openPleaseConnectToInternet();
}else{
if(!isUserSignedInToGoogleDriveAccount()){
openSignInGoogleDriveAccountDialog();
}else{
openFileChooser();
}
}
}
});
/*Upon this button click, the app logs user of current Google Drive account
* and opens choose account dialog
*/
btnDriveSettings.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!isConnectedToTheInternet()) {
openPleaseConnectToInternet();
}else{
progressBar.setVisibility(View.VISIBLE);
/*
/user is signed in, so we must initialize sign in client and sign out to reopen Google Drive Account chooser
*/
GoogleSignInOptions signInOptions =
new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestScopes(Drive.SCOPE_FILE)
.requestScopes(Drive.SCOPE_APPFOLDER)
.build();
GoogleSignInClient signInClient = GoogleSignIn.getClient(getContext(),signInOptions);
signInClient.signOut();
signIn();
}
}
});
return settingsView;
}
/***********************START OF IMPORT EVENTS METHODS**************************/
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
progressBar.setVisibility(View.INVISIBLE);
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_CODE_SIGN_IN:
if (resultCode != RESULT_OK) {
// Sign-in may fail or be cancelled by the user. For this sample, sign-in is
// required and is fatal. For apps where sign-in is optional, handle
// appropriately
return;
}
Task<GoogleSignInAccount> getAccountTask =
GoogleSignIn.getSignedInAccountFromIntent(data);
if (getAccountTask.isSuccessful()) {
initializeDriveClient(getAccountTask.getResult());
}
break;
case REQUEST_CODE_OPENER:
if (resultCode == RESULT_OK) {
driveId = (DriveId) data.getParcelableExtra(
OpenFileActivityBuilder.EXTRA_RESPONSE_DRIVE_ID);
loadCurrentFile();
}
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
//Google drive sign in
private void signIn(){
Set<Scope> requiredScopes = new HashSet<>(2);
requiredScopes.add(Drive.SCOPE_FILE);
requiredScopes.add(Drive.SCOPE_APPFOLDER);
GoogleSignInAccount signInAccount = GoogleSignIn.getLastSignedInAccount(getContext());
if (signInAccount != null && signInAccount.getGrantedScopes().containsAll(requiredScopes)) {
initializeDriveClient(signInAccount);
} else {
GoogleSignInOptions signInOptions =
new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestScopes(Drive.SCOPE_FILE)
.requestScopes(Drive.SCOPE_APPFOLDER)
.build();
GoogleSignInClient signInClient = GoogleSignIn.getClient(getContext(), signInOptions);
startActivityForResult(signInClient.getSignInIntent(), REQUEST_CODE_SIGN_IN);
}
}
//list files in drive
private void openFileChooser(){
progressBar.setVisibility(View.VISIBLE);
OpenFileActivityOptions openOptions =
new OpenFileActivityOptions.Builder()
.setSelectionFilter(Filters.eq(SearchableField.MIME_TYPE, "text/csv"))
// .setMimeType(mimeTypes)
.setActivityTitle("Choose a CSV file")
.build();
driveClient.newOpenFileActivityIntentSender(openOptions)
.addOnSuccessListener(new OnSuccessListener<IntentSender>() {
#Override
public void onSuccess(IntentSender intentSender) {
try {
startIntentSenderForResult(
intentSender,
REQUEST_CODE_OPENER,
/* fillInIntent= */ null,
/* flagsMask= */ 0,
/* flagsValues= */ 0,
/* extraFlags= */ 0,
null);
;
} catch (IntentSender.SendIntentException e) {
Log.w(TAG, "Unable to send intent.", e);
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.e(TAG, "Unable to create OpenFileActivityIntent.", e);
}
});
}
private void initializeDriveClient(GoogleSignInAccount signInAccount) {
driveClient = Drive.getDriveClient(getContext(), signInAccount);
resourceClient = Drive.getDriveResourceClient(getContext(), signInAccount);
if(progressBar != null) {
progressBar.setVisibility(View.INVISIBLE);
}
}
/**
* Retrieves the currently selected Drive file's metadata and contents.
*/
private void loadCurrentFile() {
progressBar.setVisibility(View.VISIBLE);
Log.d(TAG, "Retrieving...");
final DriveFile file = driveId.asDriveFile();
// Retrieve and store the file metadata and contents.
resourceClient.getMetadata(file)
.continueWithTask(new Continuation<Metadata, Task<DriveContents>>() {
#Override
public Task<DriveContents> then(#NonNull Task<Metadata> task) {
if (task.isSuccessful()) {
metadata = task.getResult();
return resourceClient.openFile(file, DriveFile.MODE_READ_ONLY);
} else {
return Tasks.forException(task.getException());
}
}
}).addOnSuccessListener(new OnSuccessListener<DriveContents>() {
#Override
public void onSuccess(DriveContents contents) {
driveContents = contents;
refreshUiFromCurrentFile();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.e(TAG, "Unable to retrieve file metadata and contents.", e);
}
});
}
//converting inputstream to string
private void refreshUiFromCurrentFile() {
Log.d(TAG, "Refreshing...");
String contents = "";
try {
StringWriter writer = new StringWriter();
IOUtils.copy(driveContents.getInputStream(), writer);
contents = writer.toString();
} catch (IOException e) {
e.printStackTrace();
}
if(contents.trim().isEmpty()){
return;
}
}
private boolean isConnectedToTheInternet(){
ConnectivityManager cm =
(ConnectivityManager)getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
boolean isConnected = false;
try{
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
isConnected = activeNetwork != null &&
activeNetwork.isConnectedOrConnecting();
}catch (SecurityException e){
e.printStackTrace();
}
return isConnected;
}
private boolean isUserSignedInToGoogleDriveAccount(){
GoogleSignInAccount signInAccount = GoogleSignIn.getLastSignedInAccount(getContext());
if(signInAccount == null){
return false;
}
return true;
}
private void openSignInGoogleDriveAccountDialog(){
AlertDialog alertDialog = new AlertDialog.Builder(getContext()).create();
alertDialog.setTitle("No google account selected");
alertDialog.setMessage("Please sign in to Google Drive Account by pressing Google Drive Settings button");
alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alertDialog.show();
}
private void openPleaseConnectToInternet(){
AlertDialog alertDialog = new AlertDialog.Builder(getContext()).create();
alertDialog.setTitle("!Internet Connection needed");
alertDialog.setMessage("Please Connect to the internet");
alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alertDialog.show();
}
}
Okay, i figured the problem. To use google drive API, one has to set OAuth 2.0 credentials. I set the credentials for the debug version of my application, so the API worked as needed. The problem occurred when I tried to use the same credentials for the release version. This is a problem because you need SHA-1 key to setup the O-Auth 2.0 credentials. The debug and release versions have different SHA-1 keys.