trying to implement attendance in android using geofence with php - java

I'm making an attendance system in android where employee should be able to put attendance only if he is in office premises through his mobile fingerprint scanner and I want to retrieve data like employee_name, location, date, time and save it in php I coded for geofencing but don't know how to proceed further below is code for geofencing
I searched all over the internet but didn't find a proper solution please anyone help me I really need this.....
MyGeoFenCIN.java
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.util.Log;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.Result;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.location.Geofence;
import com.google.android.gms.location.GeofencingRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.places.Place;
import com.google.android.gms.location.places.PlaceBuffer;
import java.util.ArrayList;
import java.util.List;
public class Geofencing implements ResultCallback {
// Constants
public static final String TAG = Geofencing.class.getSimpleName();
private static final float GEOFENCE_RADIUS = 1606; // 50 meters
private static final long GEOFENCE_TIMEOUT = 24 * 60 * 60 * 1000; // 24 hours
private List<Geofence> mGeofenceList;
private PendingIntent mGeofencePendingIntent;
private GoogleApiClient mGoogleApiClient;
private Context mContext;
public Geofencing(Context context, GoogleApiClient client) {
mContext = context;
mGoogleApiClient = client;
mGeofencePendingIntent = null;
mGeofenceList = new ArrayList<>();
}
/***
* Registers the list of Geofences specified in mGeofenceList with Google Place Services
* Uses {#code #mGoogleApiClient} to connect to Google Place Services
* Uses {#link #getGeofencingRequest} to get the list of Geofences to be registered
* Uses {#link #getGeofencePendingIntent} to get the pending intent to launch the IntentService
* when the Geofence is triggered
* Triggers {#link #onResult} when the geofences have been registered successfully
*/
public void registerAllGeofences() {
// Check that the API client is connected and that the list has Geofences in it
if (mGoogleApiClient == null || !mGoogleApiClient.isConnected() ||
mGeofenceList == null || mGeofenceList.size() == 0) {
return;
}
try {
LocationServices.GeofencingApi.addGeofences(
mGoogleApiClient,
getGeofencingRequest(),
getGeofencePendingIntent()
).setResultCallback(this);
} catch (SecurityException securityException) {
// Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission.
Log.e(TAG, securityException.getMessage());
}
}
/***
* Unregisters all the Geofences created by this app from Google Place Services
* Uses {#code #mGoogleApiClient} to connect to Google Place Services
* Uses {#link #getGeofencePendingIntent} to get the pending intent passed when
* registering the Geofences in the first place
* Triggers {#link #onResult} when the geofences have been unregistered successfully
*/
public void unRegisterAllGeofences() {
if (mGoogleApiClient == null || !mGoogleApiClient.isConnected()) {
return;
}
try {
LocationServices.GeofencingApi.removeGeofences(
mGoogleApiClient,
// This is the same pending intent that was used in registerGeofences
getGeofencePendingIntent()
).setResultCallback(this);
} catch (SecurityException securityException) {
// Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission.
Log.e(TAG, securityException.getMessage());
}
}
/***
* Updates the local ArrayList of Geofences using data from the passed in list
* Uses the Place ID defined by the API as the Geofence object Id
*
* #param places the PlaceBuffer result of the getPlaceById call
*/
public void updateGeofencesList(PlaceBuffer places) {
mGeofenceList = new ArrayList<>();
if (places == null || places.getCount() == 0) return;
for (Place place : places) {
// Read the place information from the DB cursor
String placeUID = place.getId();
double placeLat = place.getLatLng().latitude;
double placeLng = place.getLatLng().longitude;
// Build a Geofence object
Geofence geofence = new Geofence.Builder()
.setRequestId(placeUID)
.setExpirationDuration(GEOFENCE_TIMEOUT)
.setCircularRegion(placeLat, placeLng, GEOFENCE_RADIUS)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)
.build();
// Add it to the list
mGeofenceList.add(geofence);
}
}
/***
* Creates a GeofencingRequest object using the mGeofenceList ArrayList of Geofences
* Used by {#code #registerGeofences}
*
* #return the GeofencingRequest object
*/
private GeofencingRequest getGeofencingRequest() {
GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
builder.addGeofences(mGeofenceList);
return builder.build();
}
/***
* Creates a PendingIntent object using the GeofenceTransitionsIntentService class
* Used by {#code #registerGeofences}
*
* #return the PendingIntent object
*/
private PendingIntent getGeofencePendingIntent() {
// Reuse the PendingIntent if we already have it.
if (mGeofencePendingIntent != null) {
return mGeofencePendingIntent;
}
Intent intent = new Intent(mContext, GeofenceTransitionsIntentService.class);
mGeofencePendingIntent = PendingIntent.getService(mContext, 0, intent, PendingIntent.
FLAG_UPDATE_CURRENT);
return mGeofencePendingIntent;
}
#Override
public void onResult(#NonNull Result result) {
Log.e(TAG, String.format("Error adding/removing geofence : %s",
result.getStatus().toString()));
}
}
GeofenceTransitionsIntentService.java
import android.app.AlarmManager;
import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.net.Uri;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.location.Geofence;
import com.google.android.gms.location.GeofencingEvent;
import com.google.android.gms.location.places.GeoDataClient;
import com.google.android.gms.location.places.Place;
import com.google.android.gms.location.places.PlaceBuffer;
import com.google.android.gms.location.places.PlaceBufferResponse;
import com.google.android.gms.location.places.Places;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
/**
* Listener for geofence transition changes.
*
* Receives geofence transition events from Location Services in the form of an Intent containing
* the transition type and geofence id(s) that triggered the transition. Creates a notification
* as the output.
*/
public class GeofenceTransitionsIntentService extends IntentService {
private static final String TAG = "GeofenceTransitionsIS";
private GeoDataClient mGeoDataClient;
String geofenceTransitionString;
/**
* This constructor is required, and calls the super IntentService(String)
* constructor with the name for a worker thread.
*/
public GeofenceTransitionsIntentService() {
// Use the TAG to name the worker thread.
super(TAG);
}
/**
* Handles incoming intents.
* #param intent sent by Location Services. This Intent is provided to Location
* Services (inside a PendingIntent) when addGeofences() is called.
*/
#Override
protected void onHandleIntent(Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
//String errorMessage = GeofenceErrorMessages.getErrorString(this,
// geofencingEvent.getErrorCode());
//Log.e(TAG, errorMessage);
return;
}
// Get the transition type.
int geofenceTransition = geofencingEvent.getGeofenceTransition();
// Test that the reported transition was of interest.
if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {
// Get the geofences that were triggered. A single event can trigger multiple geofences.
List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
// Get the transition details as a String.
String geofenceTransitionDetails = getGeofenceTransitionDetails(geofenceTransition,
triggeringGeofences);
mGeoDataClient = Places.getGeoDataClient(this, null);
mGeoDataClient.getPlaceById(geofenceTransitionDetails).addOnCompleteListener(new OnCompleteListener<PlaceBufferResponse>() {
#Override
public void onComplete(#NonNull Task<PlaceBufferResponse> task) {
if (task.isSuccessful()) {
PlaceBufferResponse places = task.getResult();
Place myPlace = places.get(0);
Log.i(TAG, "Place found: " + myPlace.getName());
CharSequence name = myPlace.getName();
String placeName = name.toString();
places.release();
Calendar currentTime = Calendar.getInstance();
SimpleDateFormat df = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss");
String formattedDate = df.format(currentTime.getTime());
sendNotification(geofenceTransitionString + ": " + placeName + " " + formattedDate);
} else {
Log.e(TAG, "Place not found.");
}
}
});
Log.i(TAG, geofenceTransitionDetails);
} else {
// Log the error.
Log.e(TAG, getString(R.string.geofence_transition_invalid_type,
geofenceTransition));
}
}
/**
* Gets transition details and returns them as a formatted string.
*
* #param geofenceTransition The ID of the geofence transition.
* #param triggeringGeofences The geofence(s) triggered.
* #return The transition details formatted as String.
*/
private String getGeofenceTransitionDetails(
int geofenceTransition,
List<Geofence> triggeringGeofences) {
geofenceTransitionString = getTransitionString(geofenceTransition);
// Get the Ids of each geofence that was triggered.
ArrayList<String> triggeringGeofencesIdsList = new ArrayList<>();
for (Geofence geofence : triggeringGeofences) {
triggeringGeofencesIdsList.add(geofence.getRequestId());
}
String triggeringGeofencesIdsString = TextUtils.join(", ", triggeringGeofencesIdsList);
return triggeringGeofencesIdsString;
}
/**
* Posts a notification in the notification bar when a transition is detected.
* If the user clicks the notification, control goes to the MainActivity.
*/
private void sendNotification(String notificationDetails) {
// Create an explicit content Intent that starts the main Activity.
Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);
// Construct a task stack.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Add the main Activity to the task stack as the parent.
stackBuilder.addParentStack(MainActivity.class);
// Push the content Intent onto the stack.
stackBuilder.addNextIntent(notificationIntent);
// Get a PendingIntent containing the entire back stack.
PendingIntent notificationPendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
// Get a notification builder that's compatible with platform versions >= 4
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// Define the notification settings.
builder.setSmallIcon(R.mipmap.ic_launcher)
// In a real app, you may want to use a library like Volley
// to decode the Bitmap.
.setLargeIcon(BitmapFactory.decodeResource(getResources(),
R.mipmap.ic_launcher))
.setColor(Color.RED)
.setContentTitle(notificationDetails)
.setContentText(getString(R.string.geofence_transition_notification_text))
.setContentIntent(notificationPendingIntent);
// Dismiss notification once the user touches it.
builder.setAutoCancel(true);
// Get an instance of the Notification manager
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Issue the notification
mNotificationManager.notify(0, builder.build());
}
/**
* Maps geofence transition types to their human-readable equivalents.
*
* #param transitionType A transition type constant defined in Geofence
* #return A String indicating the type of transition
*/
private String getTransitionString(int transitionType) {
switch (transitionType) {
case Geofence.GEOFENCE_TRANSITION_ENTER:
return getString(R.string.geofence_transition_entered);
case Geofence.GEOFENCE_TRANSITION_EXIT:
return getString(R.string.geofence_transition_exited);
default:
return getString(R.string.unknown_geofence_transition);
}
}
}
So here I don't know how to make a condition that employee can put attendance only if he is in office premises and after attendance storing data in php I have seen apps on play store doing the same but I don't know how to do this
MyPlaceAdapter.java
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.locationgeo.R;
import com.google.android.gms.location.places.PlaceBuffer;
public class PlaceListAdapter extends RecyclerView.Adapter<PlaceListAdapter.PlaceViewHolder> {
private Context mContext;
private PlaceBuffer mPlaces;
public PlaceListAdapter(Context context, PlaceBuffer places) {
this.mContext = context;
this.mPlaces = places;
}
#Override
public PlaceViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Get the RecyclerView item layout
LayoutInflater inflater = LayoutInflater.from(mContext);
View view = inflater.inflate(R.layout.item_place_card, parent, false);
return new PlaceViewHolder(view);
}
#Override
public void onBindViewHolder(PlaceViewHolder holder, int position) {
String placeName = mPlaces.get(position).getName().toString();
String placeAddress = mPlaces.get(position).getAddress().toString();
holder.nameTextView.setText(placeName);
holder.addressTextView.setText(placeAddress);
}
public void swapPlaces(PlaceBuffer newPlaces){
mPlaces = newPlaces;
if (mPlaces != null) {
// Force the RecyclerView to refresh
this.notifyDataSetChanged();
}
}
#Override
public int getItemCount() {
if(mPlaces==null) return 0;
return mPlaces.getCount();
}
/**
* PlaceViewHolder class for the recycler view item
*/
class PlaceViewHolder extends RecyclerView.ViewHolder {
TextView nameTextView;
TextView addressTextView;
public PlaceViewHolder(View itemView) {
super(itemView);
nameTextView = (TextView) itemView.findViewById(R.id.name_text_view);
addressTextView = (TextView) itemView.findViewById(R.id.address_text_view);
}
}
}
PlaceProvider.java
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.support.annotation.NonNull;
public class PlaceContentProvider extends ContentProvider {
public static final int PLACES = 100;
public static final int PLACE_WITH_ID = 101;
// Declare a static variable for the Uri matcher that you construct
private static final UriMatcher sUriMatcher = buildUriMatcher();
private static final String TAG = PlaceContentProvider.class.getName();
// Define a static buildUriMatcher method that associates URI's with their int match
public static UriMatcher buildUriMatcher() {
// Initialize a UriMatcher
UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
// Add URI matches
uriMatcher.addURI(PlaceContract.AUTHORITY, PlaceContract.PATH_PLACES, PLACES);
uriMatcher.addURI(PlaceContract.AUTHORITY, PlaceContract.PATH_PLACES + "/#", PLACE_WITH_ID);
return uriMatcher;
}
// Member variable for a PlaceDbHelper that's initialized in the onCreate() method
private PlaceDbHelper mPlaceDbHelper;
#Override
public boolean onCreate() {
Context context = getContext();
mPlaceDbHelper = new PlaceDbHelper(context);
return true;
}
/***
* Handles requests to insert a single new row of data
*
* #param uri
* #param values
* #return
*/
#Override
public Uri insert(#NonNull Uri uri, ContentValues values) {
final SQLiteDatabase db = mPlaceDbHelper.getWritableDatabase();
// Write URI matching code to identify the match for the places directory
int match = sUriMatcher.match(uri);
Uri returnUri; // URI to be returned
switch (match) {
case PLACES:
// Insert new values into the database
long id = db.insert(PlaceContract.PlaceEntry.TABLE_NAME, null, values);
if (id > 0) {
returnUri = ContentUris.withAppendedId(PlaceContract.PlaceEntry.CONTENT_URI, id);
} else {
throw new android.database.SQLException("Failed to insert row into " + uri);
}
break;
// Default case throws an UnsupportedOperationException
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
// Notify the resolver if the uri has been changed, and return the newly inserted URI
getContext().getContentResolver().notifyChange(uri, null);
// Return constructed uri (this points to the newly inserted row of data)
return returnUri;
}
#Override
public Cursor query(#NonNull Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// Get access to underlying database (read-only for query)
final SQLiteDatabase db = mPlaceDbHelper.getReadableDatabase();
// Write URI match code and set a variable to return a Cursor
int match = sUriMatcher.match(uri);
Cursor retCursor;
switch (match) {
// Query for the places directory
case PLACES:
retCursor = db.query(PlaceContract.PlaceEntry.TABLE_NAME,
projection,
selection,
selectionArgs,
null,
null,
sortOrder);
break;
// Default exception
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
// Set a notification URI on the Cursor and return that Cursor
retCursor.setNotificationUri(getContext().getContentResolver(), uri);
// Return the desired Cursor
return retCursor;
}
#Override
public int delete(#NonNull Uri uri, String selection, String[] selectionArgs) {
// Get access to the database and write URI matching code to recognize a single item
final SQLiteDatabase db = mPlaceDbHelper.getWritableDatabase();
int match = sUriMatcher.match(uri);
// Keep track of the number of deleted places
int placesDeleted; // starts as 0
switch (match) {
// Handle the single item case, recognized by the ID included in the URI path
case PLACE_WITH_ID:
// Get the place ID from the URI path
String id = uri.getPathSegments().get(1);
// Use selections/selectionArgs to filter for this ID
placesDeleted = db.delete(PlaceContract.PlaceEntry.TABLE_NAME, "_id=?", new String[]{id});
break;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
// Notify the resolver of a change and return the number of items deleted
if (placesDeleted != 0) {
// A place (or more) was deleted, set notification
getContext().getContentResolver().notifyChange(uri, null);
}
// Return the number of places deleted
return placesDeleted;
}
#Override
public int update(#NonNull Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// Get access to underlying database
final SQLiteDatabase db = mPlaceDbHelper.getWritableDatabase();
int match = sUriMatcher.match(uri);
// Keep track of the number of updated places
int placesUpdated;
switch (match) {
case PLACE_WITH_ID:
// Get the place ID from the URI path
String id = uri.getPathSegments().get(1);
// Use selections/selectionArgs to filter for this ID
placesUpdated = db.update(PlaceContract.PlaceEntry.TABLE_NAME, values, "_id=?", new String[]{id});
break;
// Default exception
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
// Notify the resolver of a change and return the number of items updated
if (placesUpdated != 0) {
// A place (or more) was updated, set notification
getContext().getContentResolver().notifyChange(uri, null);
}
// Return the number of places deleted
return placesUpdated;
}
#Override
public String getType(#NonNull Uri uri) {
throw new UnsupportedOperationException("Not yet implemented");
}
}

I am assuming that you are trying to make an app that employees would use to clock in/out by:
A) scanning their fingerprint (with the app),
and B) clicking a button "IN" or "OUT" (with the same app) ??
If so, then you don't need geofencing. Geofencing is for situations where you want something to happen automatically when a user enters a designated area.
Your situation, on the other hand, only requires that your app be aware of the phone's location when the user clicks IN/OUT.
When the user clicks IN/OUT, you would just upload the latitude and longitude, time, ID etc. and the server would determine whether the latitude or longitude is within the boundary (you can do that like this).
If they are not in the boundary, then the server would return an error... or it could be quiet about it.
You will also have to guard against fake locations.

Related

Null reference for object class? TrafficService class?

I have tried to make the Network Speed in Status bar in android. I have managed to remove the error but app get crashes. I tried to implement it in my sample project.
So far I have reomve the error from TrafficeService class. I want to call it from MainActivity but it showing error in android studio as null refrence.
MainActivity.java
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
public class MainActivity extends AppCompatActivity {
private boolean isBounded;
private TrafficService backgroundService;
private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceDisconnected(ComponentName name) {
isBounded = false;
backgroundService = null;
}
public void onServiceConnected(ComponentName name, IBinder service) {
isBounded = true;
TrafficService.LocalBinder mLocalBinder = (TrafficService.LocalBinder) service;
backgroundService = mLocalBinder.getServerInstance();
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent serviceIntent = new Intent(getApplicationContext(), TrafficService.class);
startService(serviceIntent);
bindService(serviceIntent, mConnection, BIND_AUTO_CREATE);
backgroundService.showNotification();
}
#Override
protected void onStop() {
super.onStop();
if (isBounded) {
unbindService(mConnection);
isBounded = false;
}
}
}
TrafficService.java from the enter link description here
package com.example.myapplication;
import android.annotation.SuppressLint;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.TrafficStats;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.PowerManager;
import android.preference.PreferenceManager;
//import android.support.v4.app.NotificationCompat;
import android.telephony.TelephonyManager;
import android.text.format.Formatter;
import android.util.Log;
import androidx.core.app.NotificationCompat;
/**
* Main service class that monitors the network speed and updates the notification every second
*/
public class TrafficService extends Service {
/**
* The constant defining the identifier of the notification that is to be shown
*/
private static final int ID = 9000;
/**
* The identifier if the component that open from the settings activity
*/
private static final String CMP = "com.android.settings.Settings$DataUsageSummaryActivity";
/**
* The instance of the handler that updates the notification
*/
private static NotificationHandler hndNotifier;
/**
* The instance of the manager of the connectivity services
*/
private static ConnectivityManager mgrConnectivity;
/**
* The instance of the manager of the notification services
*/
private static NotificationManager mgrNotifications;
/**
* The instance of the manager of the wireless services
*/
private static WifiManager mgrWireless;
/**
* The instance of the manager of the telephony services
*/
private static TelephonyManager mgrTelephony;
/**
* The instance of the notification builder to rebuild the notification
*/
private static NotificationCompat.Builder notBuilder;
/**
* The instance of the binder class used by the activity
*/
private final IBinder mBinder = new LocalBinder();
/**
* The instance of the broadcast receiver to handle intents
*/
private BroadcastReceiver recScreen;
/**
* The instance of the broadcast receiver to handle power saver mode intents
*/
//private final BroadcastReceiver recSaver = new PowerReceiver();
/**
* Initializes the service by getting instances of service managers and mainly setting up the
* receiver to receive all the necessary intents that this service is supposed to handle.
*/
#Override
public void onCreate() {
Log.i("HardwareService", "Creating the hardware service");
super.onCreate();
final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
Intent ittSettings = new Intent();
ittSettings.setComponent(new ComponentName("com.android.settings", CMP));
PendingIntent pitSettings = PendingIntent.getActivity(this, 0, ittSettings, 0);
notBuilder = new NotificationCompat.Builder(this);
notBuilder.setSmallIcon(R.drawable.wkb000);
notBuilder.setContentIntent(pitSettings);
notBuilder.setOngoing(true);
notBuilder.setWhen(0);
notBuilder.setOnlyAlertOnce(true);
notBuilder.setPriority(Integer.MAX_VALUE);
notBuilder.setCategory(NotificationCompat.CATEGORY_SERVICE);
notBuilder.setLocalOnly(true);
setColor(settings.getInt("color", Color.TRANSPARENT));
visibilityPublic(settings.getBoolean("lockscreen", true));
Log.d("HardwareService", "Setting up the service manager and the broadcast receiver");
mgrConnectivity = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
mgrNotifications = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mgrWireless = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
mgrTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
hndNotifier = new NotificationHandler(getApplicationContext());
if (settings.getBoolean("enabled", true)) {
Log.d("HardwareService", "Screen on; showing the notification");
hndNotifier.sendEmptyMessage(1);
}
recScreen = new BroadcastReceiver() {
/**
* Handles the screen-on and the screen off intents to enable or disable the notification.
* We don't want to show the notification if the screen is off.
*/
#Override
public void onReceive(Context ctcContext, Intent ittIntent) {
if (ittIntent.getAction().equalsIgnoreCase(Intent.ACTION_SCREEN_OFF)) {
Log.d("TrafficService", "Screen off; hiding the notification");
hndNotifier.removeMessages(1);
mgrNotifications.cancel(ID);
} else if (ittIntent.getAction().equalsIgnoreCase(Intent.ACTION_SCREEN_ON)) {
Log.d("TrafficService", "Screen on; showing the notification");
connectivityUpdate();
} else if (ittIntent.getAction().equalsIgnoreCase(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
if (ittIntent.getBooleanExtra("state", false)) {
Log.d("TrafficService", "Airplane mode; hiding the notification");
hndNotifier.removeMessages(1);
hndNotifier.sendEmptyMessage(1);
} else {
Log.d("TrafficService", "Airplane mode; showing the notification");
connectivityUpdate();
}
} else {
Log.d("TrafficService", "Connectivity change; updating the notification");
connectivityUpdate();
}
}
};
IntentFilter ittScreen = new IntentFilter();
ittScreen.addAction(Intent.ACTION_SCREEN_ON);
ittScreen.addAction(Intent.ACTION_SCREEN_OFF);
ittScreen.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
ittScreen.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(recScreen, ittScreen);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
IntentFilter ittSaver = new IntentFilter();
ittScreen.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
//registerReceiver(recSaver, ittSaver);
}
}
/**
* Updates the notification with the new connectivity information. This method determines the type
* of connectivity and updates the notification with the network type and name. If there is no
* information about the active network, this will suppress the notification.
*/
private void connectivityUpdate() {
NetworkInfo nifNetwork = mgrConnectivity.getActiveNetworkInfo();
if (nifNetwork != null && nifNetwork.isConnectedOrConnecting()) {
Log.d("TrafficService", "Network connected; showing the notification");
if (nifNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
Log.d("TrafficService", "Connected to a wireless network");
WifiInfo wifInfo = mgrWireless.getConnectionInfo();
if (wifInfo != null && !wifInfo.getSSID().trim().isEmpty()) {
Log.d("TrafficService", wifInfo.getSSID());
notBuilder.setContentTitle(getString(R.string.wireless));
notBuilder.setContentText(wifInfo.getSSID().replaceAll("^\"|\"$", ""));
showNotification();
} else {
Log.d("TrafficService", "Unknown network without SSID");
hideNotification();
}
} else {
Log.d("TrafficService", "Connected to a cellular network");
if (!mgrTelephony.getNetworkOperatorName().trim().isEmpty()) {
Log.d("TrafficService", mgrTelephony.getNetworkOperatorName());
notBuilder.setContentTitle(getString(R.string.cellular));
notBuilder.setContentText(mgrTelephony.getNetworkOperatorName());
showNotification();
} else {
Log.d("TrafficService", "Unknown network without IMSI");
hideNotification();
}
}
} else {
Log.d("TrafficService", "Network disconnected; hiding the notification");
hideNotification();
}
}
/**
* Called when the service is being stopped. It doesn't do much except clear the message queue of
* the handler, hides the notification and unregisters the receivers.
*/
#Override
public void onDestroy() {
Log.d("HardwareService", "Stopping the hardware service");
unregisterReceiver(recScreen);
//unregisterReceiver(recSaver);
hndNotifier.removeMessages(1);
mgrNotifications.cancel(ID);
}
/**
* Helper method that shows the notification by sending the handler a message and building the
* notification. This is invoked when the preference is toggled.
*/
public void showNotification() {
Log.d("HardwareService", "Showing the notification");
mgrNotifications.notify(ID, notBuilder.build());
hndNotifier.removeMessages(1);
hndNotifier.sendEmptyMessage(1);
}
/**
* Helper method that hides the notification by clearing the handler messages and cancelling the
* notification. This is invoked when the preference is toggled.
*/
public void hideNotification() {
Log.d("HardwareService", "Hiding the notification");
mgrNotifications.cancel(ID);
hndNotifier.removeMessages(1);
}
/**
* Helper method that toggles the visibility of the notification on the locksreen depending on the
* value of the preference in the activity
*
* #param visibility A boolean value indicating whether the notification should be visible on the
* lockscreen
*/
public void visibilityPublic(Boolean visibility) {
if (visibility) {
notBuilder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
} else {
notBuilder.setVisibility(NotificationCompat.VISIBILITY_SECRET);
}
}
/**
* Helper method that sets the background color of the notification icon by parsing the RGB value
* into an int.
*
* #param color The internal int representation of the RGB color to set as the background colour
*/
public void setColor(Integer color) {
notBuilder.setColor(color);
}
/**
* Binder method to allow the settings activity to bind to the service so the notification can be
* configured and updated while the activity is being toggles.
*
* #see android.app.Service#onBind(android.content.Intent)
*/
#Override
public IBinder onBind(Intent intReason) {
return mBinder;
}
/**
* The handler class that runs every second to update the notification with the network speed. It
* also runs every minute to save the amount of data-transferred to the preferences.
*/
private static class NotificationHandler extends Handler {
/**
* The instance of the context of the parent service
*/
private final Context ctxContext;
/**
* The value of the amount of data transferred in the previous invocation of the method
*/
private long lngPrevious = 0L;
/**
* Simple constructor to initialize the initial value of the previous
*/
#SuppressLint("CommitPrefEdits")
public NotificationHandler(Context ctxContext) {
this.ctxContext = ctxContext;
}
/**
* Handler method that updates the notification icon with the current speed. It is a very
* hackish method. We have icons for 1 KB/s to 999 KB/s and 1.0 MB/s to 99.9 MB/s. Every time
* the method is invoked, we get the amount of data transferred. By subtracting this value with
* the previous value, we get the delta. Since this method is invoked every second, this delta
* value indicates the b/s. However, we need to convert this value into KB/s for values under 1
* MB/s and we need to convert the value to MB/s for values over 1 MB/s. Since all our icon
* images are numbered sequentially we can assume that the R class generated will contain the
* integer references of the drawables in the sequential order.
*/
#Override
public void handleMessage(Message msgMessage) {
TrafficService.hndNotifier.sendEmptyMessageDelayed(1, 1000L);
long lngCurrent = TrafficStats.getTotalRxBytes() + TrafficStats.getTotalTxBytes();
int lngSpeed = (int) (lngCurrent - lngPrevious);
lngPrevious = lngCurrent;
try {
if (lngSpeed < 1024) {
TrafficService.notBuilder.setSmallIcon(R.drawable.wkb000);
updateIcon(R.drawable.wkb000);
} else if (lngSpeed < 1048576L) {
TrafficService.notBuilder.setSmallIcon(R.drawable.wkb000 + (int) (lngSpeed / 1024L));
updateIcon(R.drawable.wkb000 + (int) (lngSpeed / 1024L));
if (lngSpeed > 1022976) {
TrafficService.notBuilder.setSmallIcon(R.drawable.wkb000 + 1000);
updateIcon(R.drawable.wkb000 + 1000);
}
} else if (lngSpeed <= 10485760) {
TrafficService.notBuilder.setSmallIcon(990 + R.drawable.wkb000
+ (int) (0.5D + (double) (10F * ((float) lngSpeed / 1048576F))));
updateIcon(990 + R.drawable.wkb000
+ (int) (0.5D + (double) (10F * ((float) lngSpeed / 1048576F))));
} else if (lngSpeed <= 103809024) {
TrafficService.notBuilder.setSmallIcon(1080 + R.drawable.wkb000
+ (int) (0.5D + (double) ((float) lngSpeed / 1048576F)));
updateIcon(1080 + R.drawable.wkb000
+ (int) (0.5D + (double) ((float) lngSpeed / 1048576F)));
} else {
TrafficService.notBuilder.setSmallIcon(1180 + R.drawable.wkb000);
updateIcon(1180 + R.drawable.wkb000);
}
Long lngTotal = TrafficStats.getTotalRxBytes() + TrafficStats.getTotalTxBytes();
String strTotal = Formatter.formatFileSize(this.ctxContext, lngTotal);
TrafficService.notBuilder.setContentInfo(strTotal);
TrafficService.mgrNotifications.notify(ID, TrafficService.notBuilder.build());
} catch (Exception e) {
Log.e("NotificationHandler", "Error creating notification for speed " + lngSpeed);
}
}
private void updateIcon(int value) {
if(Build.VERSION.SDK_INT != Build.VERSION_CODES.N) {
return;
}
Bitmap bmpIcon = BitmapFactory.decodeResource(this.ctxContext.getResources(), value);
TrafficService.notBuilder.setLargeIcon(bmpIcon);
}
}
/**
* Custom binder class used for allowing the preference activity to bind to this service so that it
* may be configured on the fly
*/
public class LocalBinder extends Binder {
public TrafficService getServerInstance() {
return TrafficService.this;
}
}
}
errors in IDE
2020-02-09 04:48:42.868 12167-12167/com.example.myapplication E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.myapplication, PID: 12167
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.myapplication/com.example.myapplication.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.myapplication.TrafficService.showNotification()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.myapplication.TrafficService.showNotification()' on a null object reference
at com.example.myapplication.MainActivity.onCreate(MainActivity.java:37)
at android.app.Activity.performCreate(Activity.java:7802)
at android.app.Activity.performCreate(Activity.java:7791)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409) 
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016) 
at android.os.Handler.dispatchMessage(Handler.java:107) 
at android.os.Looper.loop(Looper.java:214) 
at android.app.ActivityThread.main(ActivityThread.java:7356) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 

SQLite Database not being created in Android Studio when the project is run on a new machine or if the Database folder is deleted

I have built an application where using fusedlocation provider I get the location and based on the location on I display a report card of a particular location from an SQLiteDatabase.
The database worked fine initially but then when I ran the same android project on another machine it wasn't creating the database. Once the database folder was being created by Android in Device File Explorer -> Data -> Data -> Package Name -> Databases. I was manually loading the following Database file by right clicking on the the Database folder and clicking upload.
Database file link: https://drive.google.com/file/d/197MHiLl8nvFZ5eHStrBR9WfeYvQTtDKm/view?usp=sharing
To try to understand what the issue is I deleted the database folder from my project on my own machine as well and now the Database folder isn't created on my machine as well.
Before you mark this as a duplicate I have already tried the methods from the following questions but it still didn't work.
Android SQLite database table not being created
sqlite database not created
https://alvinalexander.com/android/sqliteopenhelper-does-not-call-oncreate-failing-database
Please find my code below:
DatabaseHelper.java
package edu.cpsc6150.co2ut;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DatabaseHelper extends SQLiteOpenHelper {
public static String DATABASE_NAME = "states";
public static final int DATABASE_VERSION = 1;
public static final String TABLE_NAME = "States_Report";
public static final String KEY_ID = "id";
public static final String STATE_NAME = "name";
public static final String STATE_GRADE = "grade";
public static final String EXTREME_HEAT = "heat";
public static final String DROUGHT = "Drought";
public static final String WILDFIRES = "wildfires";
public static final String INLAND_FLOODING = "inlandflooding";
public static final String COASTAL_FLOODING = "coastalflooding";
public static final String CREATE_TABLE_STUDENTS = "CREATE TABLE "
+ TABLE_NAME + "(" + KEY_ID
+ " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ STATE_NAME + " TEXT,"
+ STATE_GRADE + " TEXT,"
+ EXTREME_HEAT + " TEXT,"
+ DROUGHT + " TEXT,"
+ WILDFIRES + " TEXT,"
+ INLAND_FLOODING + " TEXT,"
+ COASTAL_FLOODING + " TEXT)";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
//Log.d("table", CREATE_TABLE_STUDENTS);
} //end DatabaseHelper constructor
/**
* Functionality: Creates tables
* PreConditions: needs table names and column names
* PostConditions: Table is created
*/
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_TABLE_STUDENTS);
} //end onCreate method
/**
* Functionality: Drop existing table and create new table if table already exists
* PreConditions: Database name, oldversion number and newVersion number are required to create a new table
* PostConditions: Old table should be dropped and new table should be created
*/
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS '" + TABLE_NAME + "'");
onCreate(db);
} //end onUpgrade method
/*
public long addStudentDetail(String state, String grade, String heat, String drought, String wildfires, String iflooding, String cflooding) {
SQLiteDatabase db = this.getWritableDatabase();
// Creating content values
ContentValues values = new ContentValues();
values.put(STATE_NAME, state);
values.put(STATE_GRADE, grade);
values.put(EXTREME_HEAT, heat);
values.put(DROUGHT, drought);
values.put(WILDFIRES, wildfires);
values.put(INLAND_FLOODING, iflooding);
values.put(COASTAL_FLOODING, cflooding);
// insert row in students table
long insert = db.insert(TABLE_NAME, null, values);
return insert;
}*/
/**
* Functionality: Get data from database and Update UI
* PreConditions: requires existing populated database
* PostConditions: Update reportcard in the UI from the database
*/
public String[] getData(String state) {
/*SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery( "select * from States_Report where name = '"+state+"'", null );
return res;*/
String State = state;
String[] name = new String[7];
String password;
//SQLiteDatabase db = getWritableDatabase();
SQLiteDatabase db = this.getReadableDatabase();
String[] columns = {DatabaseHelper.STATE_NAME,DatabaseHelper.STATE_GRADE,DatabaseHelper.EXTREME_HEAT,DatabaseHelper.DROUGHT,DatabaseHelper.WILDFIRES,DatabaseHelper.INLAND_FLOODING,DatabaseHelper.COASTAL_FLOODING};
Cursor cursor =db.query(DatabaseHelper.TABLE_NAME,columns,"name = '"+state+"' ",null,null,null,null);
StringBuffer buffer= new StringBuffer();
while (cursor.moveToNext())
{
name[0] =cursor.getString(cursor.getColumnIndex(DatabaseHelper.STATE_NAME));
name[1] =cursor.getString(cursor.getColumnIndex(DatabaseHelper.STATE_GRADE));
name[2] =cursor.getString(cursor.getColumnIndex(DatabaseHelper.EXTREME_HEAT));
name[3] =cursor.getString(cursor.getColumnIndex(DatabaseHelper.DROUGHT));
name[4] =cursor.getString(cursor.getColumnIndex(DatabaseHelper.WILDFIRES));
name[5] =cursor.getString(cursor.getColumnIndex(DatabaseHelper.INLAND_FLOODING));
name[6] =cursor.getString(cursor.getColumnIndex(DatabaseHelper.COASTAL_FLOODING));
}
return name;
} //end getData method
} //end DatabaseHelper class
ReportCardActivity.java (Which is like the MainActivity.java for this particular feature)
package edu.cpsc6150.co2ut;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.database.sqlite.SQLiteDatabase;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.net.Uri;
import android.os.Bundle;
import android.os.Looper;
import android.provider.Settings;
import android.util.Log;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.ResolvableApiException;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResponse;
import com.google.android.gms.location.LocationSettingsStatusCodes;
import com.google.android.gms.location.SettingsClient;
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.karumi.dexter.Dexter;
import com.karumi.dexter.PermissionToken;
import com.karumi.dexter.listener.PermissionDeniedResponse;
import com.karumi.dexter.listener.PermissionGrantedResponse;
import com.karumi.dexter.listener.PermissionRequest;
import com.karumi.dexter.listener.single.PermissionListener;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class ReportCardActivity extends AppCompatActivity {
private static final String TAG = ReportCardActivity.class.getSimpleName();
#BindView(R.id.location_result)
TextView txtLocationResult;
#BindView(R.id.btn_start_location_updates)
Button btnStartUpdates;
private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = 5000;
private static final int REQUEST_CHECK_SETTINGS = 100;
private FusedLocationProviderClient mFusedLocationClient;
private SettingsClient mSettingsClient;
private LocationRequest mLocationRequest;
private LocationSettingsRequest mLocationSettingsRequest;
private LocationCallback mLocationCallback;
private Location mCurrentLocation;
private Boolean mRequestingLocationUpdates;
private DatabaseHelper databaseHelper;
private TextView statedisplay, gradedisplay, heat, drought, wildfires, inlandFlooding,coastalFlooding;
/**
* Functionality: Instantiates the DatabaseHelper class and other UI Components like textviews
* PreConditions: DatabaseHelper and textviews must be declared
* PostConditions: Textviews are assigned and DatabaseHelper initialized
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_report_card);
ButterKnife.bind(this);
databaseHelper = new DatabaseHelper(this);
SQLiteDatabase db = new DatabaseHelper(this).getReadableDatabase();
statedisplay = (TextView) findViewById(R.id.statedisplay);
gradedisplay = (TextView) findViewById(R.id.gradedisplay);
heat = (TextView) findViewById(R.id.heat);
drought = (TextView) findViewById(R.id.drought);
wildfires = (TextView) findViewById(R.id.wildfires);
inlandFlooding = (TextView) findViewById(R.id.inlandFlooding);
coastalFlooding = (TextView) findViewById(R.id.coastalFlooding);
// initialize the necessary libraries
init();
// restore the values from saved instance state
restoreValuesFromBundle(savedInstanceState);
} //end onCreate method
/**
* Functionality: Initializes the necessary libraries to get location updates
* PreConditions: Library's required for the location updates must be declared
* PostConditions: All necessary Libraries are intialized
*/
private void init() {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
mSettingsClient = LocationServices.getSettingsClient(this);
mLocationCallback = new LocationCallback() {
/**
* Functionality: Updates Last location on receiving location updates
* PreConditions: Needs to receive locationResult as a parameter
* PostConditions: Return updated last location to the UI
*/
#Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
// location is received
mCurrentLocation = locationResult.getLastLocation();
updateLocationUI();
}
};
mRequestingLocationUpdates = false;
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
mLocationSettingsRequest = builder.build();
} //end init method
/**
* Functionality: Restores the savedState of the activity
* PreConditions: Needs the instance state to be saved
* PostConditions: Retrieve the saved state and update the UI
*/
private void restoreValuesFromBundle(Bundle savedInstanceState) {
if (savedInstanceState != null) {
if (savedInstanceState.containsKey("is_requesting_updates")) {
mRequestingLocationUpdates = savedInstanceState.getBoolean("is_requesting_updates");
}
if (savedInstanceState.containsKey("last_known_location")) {
mCurrentLocation = savedInstanceState.getParcelable("last_known_location");
}
}
updateLocationUI();
} //end restoreValuesFromBundle method
/**
* Functionality: Update the UI displaying the location data
* PreConditions: Requires the current location
* PostConditions: Updates the UI with the current location and the states report card from the database
*/
String state;
private void updateLocationUI() {
if (mCurrentLocation != null) {
Geocoder gcd = new Geocoder(this, Locale.getDefault());
try{
List<Address> addresses = gcd.getFromLocation(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude(), 1);
if (addresses.size() > 0) {
state = addresses.get(0).getAdminArea();
String output[] = databaseHelper.getData(state);
statedisplay.setText(" State: "+output[0]);
gradedisplay.setText(" Average: "+output[1]);
heat.setText(" Extreme Heat: "+output[2]);
drought.setText(" Drought: "+output[3]);
wildfires.setText(" Wildfires: "+output[4]);
inlandFlooding.setText(" Inland Flooding: "+output[5]);
coastalFlooding.setText(" Coastal Flooding: "+output[6]);
/*Cursor rs = databaseHelper.getData(state);
if (rs.moveToFirst()){
// do the work
String username = rs.getString(1);
String password = rs.getString(2);
//String nam = rs.getString(rs.getColumnIndex(DatabaseHelper.STATE_NAME));
//String phon = rs.getString(rs.getColumnIndex(DatabaseHelper.STATE_GRADE));
statedisplay.setText(username);
gradedisplay.setText(password);
}*/
//arrayList = databaseHelper.getAllStudentsList();
//tvnames.setText("");
/*for (int i = 0; i < arrayList.size(); i++){
tvnames.setText(tvnames.getText().toString()+", "+arrayList.get(i));
}*/
}
else {
// do your stuff
}
} catch (IOException e1) {
e1.printStackTrace();
} //end try-catch block
txtLocationResult.setText(
getString(R.string.welcome_message,state)
);
// location last updated time
}
} //end updateLocationUI method
/**
* Functionality: Saves the Activities current state
* PreConditions: Needs the values of mCurrentLocation and mRequestingLocationUpdates
* PostConditions: The Instance state should be saved to the Bundle
*/
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("is_requesting_updates", mRequestingLocationUpdates);
outState.putParcelable("last_known_location", mCurrentLocation);
} //end onSaveInstanceState method
/**
* Functionality: Starting location updates
* PreConditions: Check whether location settings are satisfied
* PostConditions: Location updates will be requested
*/
private void startLocationUpdates() {
mSettingsClient
.checkLocationSettings(mLocationSettingsRequest)
.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
#SuppressLint("MissingPermission")
#Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
Log.i(TAG, "All location settings are satisfied.");
Toast.makeText(getApplicationContext(), "Started location updates!", Toast.LENGTH_SHORT).show();
//noinspection MissingPermission
mFusedLocationClient.requestLocationUpdates(mLocationRequest,
mLocationCallback, Looper.myLooper());
updateLocationUI();
} //end onSuccess method
})
.addOnFailureListener(this, new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
int statusCode = ((ApiException) e).getStatusCode();
switch (statusCode) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
Log.i(TAG, "Location settings are not satisfied. Attempting to upgrade " +
"location settings ");
try {
// Show the dialog by calling startResolutionForResult(), and check the
// result in onActivityResult().
ResolvableApiException rae = (ResolvableApiException) e;
rae.startResolutionForResult(ReportCardActivity.this, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException sie) {
Log.i(TAG, "PendingIntent unable to execute request.");
} //end try-catch block
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
String errorMessage = "Location settings are inadequate, and cannot be " +
"fixed here. Fix in Settings.";
Log.e(TAG, errorMessage);
Toast.makeText(ReportCardActivity.this, errorMessage, Toast.LENGTH_LONG).show();
} //end switch statement
updateLocationUI();
} //end onFailure method
});
} //end startLocationUpdates method
/**
* Functionality: OnClick will start receiving location updates
* PreConditions: Permissions must be granted
* PostConditions: Location Updates started
*/
#OnClick(R.id.btn_start_location_updates)
public void startLocationButtonClick() {
// Requesting ACCESS_FINE_LOCATION using Dexter library
Dexter.withActivity(this)
.withPermission(Manifest.permission.ACCESS_FINE_LOCATION)
.withListener(new PermissionListener() {
#Override
public void onPermissionGranted(PermissionGrantedResponse response) {
mRequestingLocationUpdates = true;
startLocationUpdates();
} //end onPermissionGranted method
#Override
public void onPermissionDenied(PermissionDeniedResponse response) {
if (response.isPermanentlyDenied()) {
// open device settings when the permission is
// denied permanently
openSettings();
}
} //end onPermuissionDenied method
#Override
public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {
token.continuePermissionRequest();
} //end onPermissionRationaleShouldBeShown method
}).check();
} //end startLocationButtonClick method
/**
* Functionality: Stop or pause location updates when the app pauses
* PreConditions: FusedLocationClient must be intialized
* PostConditions: Stop Location updates
*/
public void stopLocationUpdates() {
// Removing location updates
mFusedLocationClient
.removeLocationUpdates(mLocationCallback)
.addOnCompleteListener(this, new OnCompleteListener<Void>() {
/**
* Functionality:
* PreConditions:
* PostConditions:
*/
#Override
public void onComplete(#NonNull Task<Void> task) {
Toast.makeText(getApplicationContext(), "Location updates stopped!", Toast.LENGTH_SHORT).show();
}
});
} //end stopLocationUpdates method
/**
* Functionality: Check whether user has granted permissions or not
* PreConditions: Needs requestCode, resultCode and data as parameters
* PostConditions: Log the ActivityResult as an error log
*/
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
// Check for the integer request code originally supplied to startResolutionForResult().
case REQUEST_CHECK_SETTINGS:
switch (resultCode) {
case Activity.RESULT_OK:
Log.e(TAG, "User agreed to make required location settings changes.");
// Nothing to do. startLocationupdates() gets called in onResume again.
break;
case Activity.RESULT_CANCELED:
Log.e(TAG, "User chose not to make required location settings changes.");
mRequestingLocationUpdates = false;
break;
} //end switch statement
break;
} //end switch statement
} //end onActivityResult method
/**
* Functionality: Open settings if permissions is denied
* PreConditions: Settings URI
* PostConditions: Open Application details settings page
*/
private void openSettings() {
Intent intent = new Intent();
intent.setAction(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package",
BuildConfig.APPLICATION_ID, null);
intent.setData(uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} //end openSettings method
/**
* Functionality: Check for permissions again onResume
* PreConditions: App must be paused or stopped before this function is called
* PostConditions: onResume the locationupdates must be resume and the UI must be updated
*/
#Override
public void onResume() {
super.onResume();
// Resuming location updates depending on button state and
// allowed permissions
if (mRequestingLocationUpdates && checkPermissions()) {
startLocationUpdates();
}
updateLocationUI();
} //end onResume()
/**
* Functionality: Checks if permission to access location is granted
* PreConditions: Permission must be mentioned in the manifest file
* PostConditions: Return permission granted if Uses-Permission is mentioned in the activity file
*/
private boolean checkPermissions() {
int permissionState = ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION);
return permissionState == PackageManager.PERMISSION_GRANTED;
} //end checkPermissions method
/**
* Functionality: Stops location updates when the application is paused
* PreConditions: Application must be paused
* PostConditions: Location updates must be stopped
*/
#Override
protected void onPause() {
super.onPause();
if (mRequestingLocationUpdates) {
// pausing location updates
stopLocationUpdates();
}
} //end onPause method
} //end ReportCardActivity class
Let me know if you need any more information regarding the code or dependencies.
I believe that the database is being created BUT you don't appear to be populating it.
Using your Databasehelper (with addStudentDetail uncommented as the only change) then using :-
public class MainActivity extends AppCompatActivity {
DatabaseHelper mDBHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDBHelper = new DatabaseHelper(this);
mDBHelper.addStudentDetail("STATE1","GRADE1","HIGH","YES","NO","NO","NO");
mDBHelper.addStudentDetail("STATE1","GRADE2","HIGH","YES","NO","NO","NO");
mDBHelper.addStudentDetail("STATE1","GRADE3","HIGH","YES","NO","NO","NO");
mDBHelper.addStudentDetail("STATE1","GRADE4","HIGH","YES","NO","NO","NO");
for (String s: mDBHelper.getData("STATE1")){
Log.d("INFO",s);
}
}
}
results in :-
12-05 16:38:19.211 3764-3764/? D/INFO: STATE1
12-05 16:38:19.211 3764-3764/? D/INFO: GRADE4
12-05 16:38:19.211 3764-3764/? D/INFO: HIGH
12-05 16:38:19.211 3764-3764/? D/INFO: YES
12-05 16:38:19.211 3764-3764/? D/INFO: NO
12-05 16:38:19.211 3764-3764/? D/INFO: NO
12-05 16:38:19.211 3764-3764/? D/INFO: NO
I can't see anywhere in your code where you are adding data to the database. rather you just try to get data using String output[] = databaseHelper.getData(state);, which will retrieve nothing as there is no data.
Below I have attached a solution where you just need to add two lines of code to the ReportCardActivity.java code. The two lines of code to be added are commented as "//add this line" and have a line of astrix (*) before and after it.
private Boolean mRequestingLocationUpdates;
DatabaseHelper databaseHelper;
*********************************************************
SQLiteDatabase database; //add this line
*********************************************************
private TextView statedisplay, gradedisplay, heat, drought, wildfires, inlandFlooding,coastalFlooding;
/**
* Functionality: Instantiates the DatabaseHelper class and other UI Components like textviews
* PreConditions: DatabaseHelper and textviews must be declared
* PostConditions: Textviews are assigned and DatabaseHelper initialized
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_report_card);
ButterKnife.bind(this);
databaseHelper = new DatabaseHelper(this);
*********************************************************
database = databaseHelper.getWritableDatabase(); //add this line
*********************************************************
statedisplay = (TextView) findViewById(R.id.statedisplay);
gradedisplay = (TextView) findViewById(R.id.gradedisplay);
heat = (TextView) findViewById(R.id.heat);
drought = (TextView) findViewById(R.id.drought);
wildfires = (TextView) findViewById(R.id.wildfires);
inlandFlooding = (TextView) findViewById(R.id.inlandFlooding);
coastalFlooding = (TextView) findViewById(R.id.coastalFlooding);
// initialize the necessary libraries
init();
// restore the values from saved instance state
restoreValuesFromBundle(savedInstanceState);
} //end onCreate method
One you paste the code run the application. This should create the database directory in the Device File Explorer -> Data -> Data -> Package Name directory.
The database folder might not be visible immediately. You may have to restart android studio after you run the app once.
When you restart android studio and go to Device File Explorer -> Data -> Data -> Package Name directory the databases directory should be created.
Once it is created right click on the databases folder and click upload then upload the database file you have provided in the link.

Google-API Start Activity as Service or hide Activity

I've got a problem with my Google-API Activity. I used the sample code from Google and changed some lines to fill on create an static int with my total mail count. So far so good, this works fine. Every time I have to update my mail_count value I execute the following code:
Intent intent2 = new Intent(getBaseContext(), MainActivity.class);
intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startService(intent2);
This works fine, but the problem is that every time I start the activity it'll show up for some seconds. I really know that's the point of activities, but I didn't get how to use the GOOGLE-API Activity in my project to communicate in Background with the API and don't show up every time (after User has confirmed the access).
Here's my Google-API Activity Code (MainActivity):
.widgetNew;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.googleapis.extensions.android.gms.auth.GooglePlayServicesAvailabilityIOException;
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.ExponentialBackOff;
import com.google.api.services.gmail.GmailScopes;
import com.google.api.services.gmail.model.*;
import android.Manifest;
import android.accounts.AccountManager;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RemoteViews;
import android.widget.TextView;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import pub.devrel.easypermissions.AfterPermissionGranted;
import pub.devrel.easypermissions.EasyPermissions;
public class MainActivity extends Activity
implements EasyPermissions.PermissionCallbacks {
GoogleAccountCredential mCredential;
private TextView mOutputText;
private Button mCallApiButton;
//ProgressDialog mProgress;
static final int REQUEST_ACCOUNT_PICKER = 1000;
static final int REQUEST_AUTHORIZATION = 1001;
static final int REQUEST_GOOGLE_PLAY_SERVICES = 1002;
static final int REQUEST_PERMISSION_GET_ACCOUNTS = 1003;
static int EMAIL_COUNT = 0;
private static final String BUTTON_TEXT = "Call Gmail API";
private static final String PREF_ACCOUNT_NAME = "accountName";
private static final String[] SCOPES = { GmailScopes.GMAIL_LABELS, GmailScopes.GMAIL_READONLY , GmailScopes.MAIL_GOOGLE_COM};
/**
* Create the main activity.
* #param savedInstanceState previously saved instance data.
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// LinearLayout activityLayout = new LinearLayout(this);
// LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
// LinearLayout.LayoutParams.MATCH_PARENT,
// LinearLayout.LayoutParams.MATCH_PARENT);
// activityLayout.setLayoutParams(lp);
// activityLayout.setOrientation(LinearLayout.VERTICAL);
// activityLayout.setPadding(16, 16, 16, 16);
// ViewGroup.LayoutParams tlp = new ViewGroup.LayoutParams(
// ViewGroup.LayoutParams.WRAP_CONTENT,
// ViewGroup.LayoutParams.WRAP_CONTENT);
// mCallApiButton = new Button(this);
// mCallApiButton.setText(BUTTON_TEXT);
// mCallApiButton.setOnClickListener(new View.OnClickListener() {
// #Override
// public void onClick(View v) {
// mCallApiButton.setEnabled(false);
// mOutputText.setText("");
// mCallApiButton.setEnabled(true);
// }
// });
//activityLayout.addView(mCallApiButton);
// mOutputText = new TextView(this);
//mOutputText.setLayoutParams(tlp);
// mOutputText.setPadding(16, 16, 16, 16);
// mOutputText.setVerticalScrollBarEnabled(true);
// mOutputText.setMovementMethod(new ScrollingMovementMethod());
// mOutputText.setText(
// "Click the \'" + BUTTON_TEXT +"\' button to test the API.");
//activityLayout.addView(mOutputText);
// mProgress = new ProgressDialog(this);
// mProgress.setMessage("Calling Gmail API ...");
//setContentView(activityLayout);
// Initialize credentials and service object.
mCredential = GoogleAccountCredential.usingOAuth2(
getApplicationContext(), Arrays.asList(SCOPES))
.setBackOff(new ExponentialBackOff());
getResultsFromApi();
finish();
}
/**
* Attempt to call the API, after verifying that all the preconditions are
* satisfied. The preconditions are: Google Play Services installed, an
* account was selected and the device currently has online access. If any
* of the preconditions are not satisfied, the app will prompt the user as
* appropriate.
*/
private void getResultsFromApi() {
if (! isGooglePlayServicesAvailable()) {
acquireGooglePlayServices();
} else if (mCredential.getSelectedAccountName() == null) {
chooseAccount();
} else if (! isDeviceOnline()) {
//mOutputText.setText("No network connection available.");
} else {
new MakeRequestTask(mCredential).execute();
}
}
/**
* Attempts to set the account used with the API credentials. If an account
* name was previously saved it will use that one; otherwise an account
* picker dialog will be shown to the user. Note that the setting the
* account to use with the credentials object requires the app to have the
* GET_ACCOUNTS permission, which is requested here if it is not already
* present. The AfterPermissionGranted annotation indicates that this
* function will be rerun automatically whenever the GET_ACCOUNTS permission
* is granted.
*/
#AfterPermissionGranted(REQUEST_PERMISSION_GET_ACCOUNTS)
private void chooseAccount() {
if (EasyPermissions.hasPermissions(
this, Manifest.permission.GET_ACCOUNTS)) {
String accountName = getPreferences(Context.MODE_PRIVATE)
.getString(PREF_ACCOUNT_NAME, null);
if (accountName != null) {
mCredential.setSelectedAccountName(accountName);
getResultsFromApi();
} else {
// Start a dialog from which the user can choose an account
startActivityForResult(
mCredential.newChooseAccountIntent(),
REQUEST_ACCOUNT_PICKER);
}
} else {
// Request the GET_ACCOUNTS permission via a user dialog
EasyPermissions.requestPermissions(
this,
"This app needs to access your Google account (via Contacts).",
REQUEST_PERMISSION_GET_ACCOUNTS,
Manifest.permission.GET_ACCOUNTS);
}
}
/**
* Called when an activity launched here (specifically, AccountPicker
* and authorization) exits, giving you the requestCode you started it with,
* the resultCode it returned, and any additional data from it.
* #param requestCode code indicating which activity result is incoming.
* #param resultCode code indicating the result of the incoming
* activity result.
* #param data Intent (containing result data) returned by incoming
* activity result.
*/
#Override
protected void onActivityResult(
int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode) {
case REQUEST_GOOGLE_PLAY_SERVICES:
if (resultCode != RESULT_OK) {
//mOutputText.setText(
// "This app requires Google Play Services. Please install " +
// "Google Play Services on your device and relaunch this app.");
} else {
getResultsFromApi();
}
break;
case REQUEST_ACCOUNT_PICKER:
if (resultCode == RESULT_OK && data != null &&
data.getExtras() != null) {
String accountName =
data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
if (accountName != null) {
SharedPreferences settings =
getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putString(PREF_ACCOUNT_NAME, accountName);
editor.apply();
mCredential.setSelectedAccountName(accountName);
getResultsFromApi();
}
}
break;
case REQUEST_AUTHORIZATION:
if (resultCode == RESULT_OK) {
getResultsFromApi();
}
break;
}
}
/**
* Respond to requests for permissions at runtime for API 23 and above.
* #param requestCode The request code passed in
* requestPermissions(android.app.Activity, String, int, String[])
* #param permissions The requested permissions. Never null.
* #param grantResults The grant results for the corresponding permissions
* which is either PERMISSION_GRANTED or PERMISSION_DENIED. Never null.
*/
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String[] permissions,
#NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
EasyPermissions.onRequestPermissionsResult(
requestCode, permissions, grantResults, this);
}
/**
* Callback for when a permission is granted using the EasyPermissions
* library.
* #param requestCode The request code associated with the requested
* permission
* #param list The requested permission list. Never null.
*/
#Override
public void onPermissionsGranted(int requestCode, List<String> list) {
// Do nothing.
}
/**
* Callback for when a permission is denied using the EasyPermissions
* library.
* #param requestCode The request code associated with the requested
* permission
* #param list The requested permission list. Never null.
*/
#Override
public void onPermissionsDenied(int requestCode, List<String> list) {
// Do nothing.
}
/**
* Checks whether the device currently has a network connection.
* #return true if the device has a network connection, false otherwise.
*/
private boolean isDeviceOnline() {
ConnectivityManager connMgr =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
return (networkInfo != null && networkInfo.isConnected());
}
/**
* Check that Google Play services APK is installed and up to date.
* #return true if Google Play Services is available and up to
* date on this device; false otherwise.
*/
private boolean isGooglePlayServicesAvailable() {
GoogleApiAvailability apiAvailability =
GoogleApiAvailability.getInstance();
final int connectionStatusCode =
apiAvailability.isGooglePlayServicesAvailable(this);
return connectionStatusCode == ConnectionResult.SUCCESS;
}
/**
* Attempt to resolve a missing, out-of-date, invalid or disabled Google
* Play Services installation via a user dialog, if possible.
*/
private void acquireGooglePlayServices() {
GoogleApiAvailability apiAvailability =
GoogleApiAvailability.getInstance();
final int connectionStatusCode =
apiAvailability.isGooglePlayServicesAvailable(this);
if (apiAvailability.isUserResolvableError(connectionStatusCode)) {
showGooglePlayServicesAvailabilityErrorDialog(connectionStatusCode);
}
}
/**
* Display an error dialog showing that Google Play Services is missing
* or out of date.
* #param connectionStatusCode code describing the presence (or lack of)
* Google Play Services on this device.
*/
void showGooglePlayServicesAvailabilityErrorDialog(
final int connectionStatusCode) {
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
Dialog dialog = apiAvailability.getErrorDialog(
MainActivity.this,
connectionStatusCode,
REQUEST_GOOGLE_PLAY_SERVICES);
dialog.show();
}
/**
* An asynchronous task that handles the Gmail API call.
* Placing the API calls in their own task ensures the UI stays responsive.
*/
private class MakeRequestTask extends AsyncTask<Void, Void, List<String>> {
private com.google.api.services.gmail.Gmail mService = null;
private Exception mLastError = null;
public MakeRequestTask(GoogleAccountCredential credential) {
HttpTransport transport = AndroidHttp.newCompatibleTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
mService = new com.google.api.services.gmail.Gmail.Builder(
transport, jsonFactory, credential)
.setApplicationName("Gmail API Android Quickstart")
.build();
}
/**
* Background task to call Gmail API.
* #param params no parameters needed for this task.
*/
#Override
protected List<String> doInBackground(Void... params) {
try {
return getDataFromApi();
} catch (Exception e) {
mLastError = e;
cancel(true);
return null;
}
}
/**
* Fetch a list of Gmail labels attached to the specified account.
* #return List of Strings labels.
* #throws IOException
*/
private List<String> getDataFromApi() throws IOException {
// Get the labels in the user's account.
String user = "me";
List<String> labels = new ArrayList<String>();
Profile profile = mService.users().getProfile("me").execute();
labels.add("E-Mails: " + profile.getMessagesTotal());
EMAIL_COUNT = profile.getMessagesTotal();
//tv.setText("TEST");
return labels;
}
#Override
protected void onPreExecute() {
// mOutputText.setText("");
// mProgress.show();
}
#Override
protected void onPostExecute(List<String> output) {
//mProgress.hide();
if (output == null || output.size() == 0) {
// mOutputText.setText("No results returned.");
} else {
//output.add(0, "Data retrieved using the Gmail API:");
//mOutputText.setText(TextUtils.join("\n", output));
finish();
}
}
#Override
protected void onCancelled() {
// mProgress.hide();
if (mLastError != null) {
if (mLastError instanceof GooglePlayServicesAvailabilityIOException) {
showGooglePlayServicesAvailabilityErrorDialog(
((GooglePlayServicesAvailabilityIOException) mLastError)
.getConnectionStatusCode());
} else if (mLastError instanceof UserRecoverableAuthIOException) {
startActivityForResult(
((UserRecoverableAuthIOException) mLastError).getIntent(),
MainActivity.REQUEST_AUTHORIZATION);
} else {
// mOutputText.setText("The following error occurred:\n"
// + mLastError.getMessage());
}
} else {
// mOutputText.setText("Request cancelled.");
}
}
}
}

Searching a Google Spreadsheet with Android App

I was wondering how I could find an integer in a cell of a Google Spreadsheet, for Android Studio (java).
I was using the Android Sheets API's Quickstart as an entire guideline/reference, because my coding isn't really great, so I was hoping if anyone could give me direct help on this.
Heres my code:
package com.package.Test;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.googleapis.extensions.android.gms.auth.GooglePlayServicesAvailabilityIOException;
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.ExponentialBackOff;
import com.google.api.services.sheets.v4.SheetsScopes;
import com.google.api.services.sheets.v4.model.*;
import android.Manifest;
import android.accounts.AccountManager;
import android.app.ActionBar;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.InputFilter;
import android.text.InputType;
import android.text.TextUtils;
import android.text.method.ScrollingMovementMethod;
import android.view.*;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import pub.devrel.easypermissions.AfterPermissionGranted;
import pub.devrel.easypermissions.EasyPermissions;
/**
* Created by terminal on 9/2/2016.
*/
public class AttendanceActivity extends AppCompatActivity
implements EasyPermissions.PermissionCallbacks{
GoogleAccountCredential mCredential;
private TextView mOutputText;
private Button mCallApiButton;
private EditText editText;
private TextView textView7;
private TextView textView6;
private TextView textView5;
private Button checker;
ProgressDialog mProgress;
public int iString;
static final int REQUEST_ACCOUNT_PICKER = 1000;
static final int REQUEST_AUTHORIZATION = 1001;
static final int REQUEST_GOOGLE_PLAY_SERVICES = 1002;
static final int REQUEST_PERMISSION_GET_ACCOUNTS = 1003;
private static final String BUTTON_TEXT = "Check";
private static final String PREF_ACCOUNT_NAME = "accountName";
private static final String[] SCOPES = { SheetsScopes.SPREADSHEETS_READONLY };
/**
* Create the main activity.
* #param savedInstanceState previously saved instance data.
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout activityLayout = new LinearLayout(this);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
activityLayout.setLayoutParams(lp);
activityLayout.setOrientation(LinearLayout.VERTICAL);
activityLayout.setPadding(16, 16, 16, 16);
ViewGroup.LayoutParams tlp = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
textView6 = new TextView(this);
textView6.setText("Attendance");
textView6.setTextSize(50);
textView6.setGravity(Gravity.CENTER);
editText = new EditText(this);
editText.setInputType(InputType.TYPE_CLASS_NUMBER);
editText.setHint("Enter ID Number...");
LinearLayout.LayoutParams etLP = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
etLP.setMargins(40, 50, 40, 0);
int maxLength = 8;
editText.setFilters(new InputFilter[] {new InputFilter.LengthFilter(maxLength)});
mCallApiButton = new Button(this);
mCallApiButton.setText(BUTTON_TEXT);
mCallApiButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mCallApiButton.setEnabled(false);
mOutputText.setText("");
iString = Integer.parseInt(editText.getText().toString());
getResultsFromApi();
mCallApiButton.setEnabled(true);
}
});
textView5 = new TextView(this);
textView5.setText("-You currently have-");
textView5.setGravity(Gravity.CENTER);
textView7 = new TextView(this);
textView7.setText("Hours!");
textView7.setGravity(Gravity.CENTER);
LinearLayout.LayoutParams tv7lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
tv7lp.setMargins(0, 30, 0, 0);
mOutputText = new TextView(this);
mOutputText.setTextSize(30);
mOutputText.setLayoutParams(tlp);
mOutputText.setPadding(16, 16, 16, 16);
mOutputText.setVerticalScrollBarEnabled(true);
mOutputText.setMovementMethod(new ScrollingMovementMethod());
mOutputText.setText("");
activityLayout.addView(textView6);
activityLayout.addView(editText, etLP);
activityLayout.addView(mCallApiButton);
activityLayout.addView(textView5);
activityLayout.addView(mOutputText);
activityLayout.addView(textView7, tv7lp);
mProgress = new ProgressDialog(this);
mProgress.setMessage("Searching for your ID Number ...");
setContentView(activityLayout);
// Initialize credentials and service object.
mCredential = GoogleAccountCredential.usingOAuth2(
getApplicationContext(), Arrays.asList(SCOPES))
.setBackOff(new ExponentialBackOff());
}
public boolean onOptionsItemSelected(MenuItem item){
Intent myIntent = new Intent(getApplicationContext(), MainActivity.class);
startActivityForResult(myIntent, 0);
return true;
}
/**
* Attempt to call the API, after verifying that all the preconditions are
* satisfied. The preconditions are: Google Play Services installed, an
* account was selected and the device currently has online access. If any
* of the preconditions are not satisfied, the app will prompt the user as
* appropriate.
*/
private void getResultsFromApi() {
if (! isGooglePlayServicesAvailable()) {
acquireGooglePlayServices();
} else if (mCredential.getSelectedAccountName() == null) {
chooseAccount();
} else if (! isDeviceOnline()) {
mOutputText.setText("No network connection available.");
} else {
new MakeRequestTask(mCredential).execute();
}
}
/**
* Attempts to set the account used with the API credentials. If an account
* name was previously saved it will use that one; otherwise an account
* picker dialog will be shown to the user. Note that the setting the
* account to use with the credentials object requires the app to have the
* GET_ACCOUNTS permission, which is requested here if it is not already
* present. The AfterPermissionGranted annotation indicates that this
* function will be rerun automatically whenever the GET_ACCOUNTS permission
* is granted.
*/
#AfterPermissionGranted(REQUEST_PERMISSION_GET_ACCOUNTS)
private void chooseAccount() {
if (EasyPermissions.hasPermissions(
this, Manifest.permission.GET_ACCOUNTS)) {
String accountName = getPreferences(Context.MODE_PRIVATE)
.getString(PREF_ACCOUNT_NAME, null);
if (accountName != null) {
mCredential.setSelectedAccountName(accountName);
getResultsFromApi();
} else {
// Start a dialog from which the user can choose an account
startActivityForResult(
mCredential.newChooseAccountIntent(),
REQUEST_ACCOUNT_PICKER);
}
} else {
// Request the GET_ACCOUNTS permission via a user dialog
EasyPermissions.requestPermissions(
this,
"This app needs to access your Google account (via Contacts).",
REQUEST_PERMISSION_GET_ACCOUNTS,
Manifest.permission.GET_ACCOUNTS);
}
}
/**
* Called when an activity launched here (specifically, AccountPicker
* and authorization) exits, giving you the requestCode you started it with,
* the resultCode it returned, and any additional data from it.
* #param requestCode code indicating which activity result is incoming.
* #param resultCode code indicating the result of the incoming
* activity result.
* #param data Intent (containing result data) returned by incoming
* activity result.
*/
#Override
protected void onActivityResult(
int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode) {
case REQUEST_GOOGLE_PLAY_SERVICES:
if (resultCode != RESULT_OK) {
mOutputText.setText(
"This app requires Google Play Services. Please install " +
"Google Play Services on your device and relaunch this app.");
} else {
getResultsFromApi();
}
break;
case REQUEST_ACCOUNT_PICKER:
if (resultCode == RESULT_OK && data != null &&
data.getExtras() != null) {
String accountName =
data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
if (accountName != null) {
SharedPreferences settings =
getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putString(PREF_ACCOUNT_NAME, accountName);
editor.apply();
mCredential.setSelectedAccountName(accountName);
getResultsFromApi();
}
}
break;
case REQUEST_AUTHORIZATION:
if (resultCode == RESULT_OK) {
getResultsFromApi();
}
break;
}
}
/**
* Respond to requests for permissions at runtime for API 23 and above.
* #param requestCode The request code passed in
* requestPermissions(android.app.Activity, String, int, String[])
* #param permissions The requested permissions. Never null.
* #param grantResults The grant results for the corresponding permissions
* which is either PERMISSION_GRANTED or PERMISSION_DENIED. Never null.
*/
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String[] permissions,
#NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
EasyPermissions.onRequestPermissionsResult(
requestCode, permissions, grantResults, this);
}
/**
* Callback for when a permission is granted using the EasyPermissions
* library.
* #param requestCode The request code associated with the requested
* permission
* #param list The requested permission list. Never null.
*/
#Override
public void onPermissionsGranted(int requestCode, List<String> list) {
// Do nothing.
}
/**
* Callback for when a permission is denied using the EasyPermissions
* library.
* #param requestCode The request code associated with the requested
* permission
* #param list The requested permission list. Never null.
*/
#Override
public void onPermissionsDenied(int requestCode, List<String> list) {
// Do nothing.
}
/**
* Checks whether the device currently has a network connection.
* #return true if the device has a network connection, false otherwise.
*/
private boolean isDeviceOnline() {
ConnectivityManager connMgr =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
return (networkInfo != null && networkInfo.isConnected());
}
/**
* Check that Google Play services APK is installed and up to date.
* #return true if Google Play Services is available and up to
* date on this device; false otherwise.
*/
private boolean isGooglePlayServicesAvailable() {
GoogleApiAvailability apiAvailability =
GoogleApiAvailability.getInstance();
final int connectionStatusCode =
apiAvailability.isGooglePlayServicesAvailable(this);
return connectionStatusCode == ConnectionResult.SUCCESS;
}
/**
* Attempt to resolve a missing, out-of-date, invalid or disabled Google
* Play Services installation via a user dialog, if possible.
*/
private void acquireGooglePlayServices() {
GoogleApiAvailability apiAvailability =
GoogleApiAvailability.getInstance();
final int connectionStatusCode =
apiAvailability.isGooglePlayServicesAvailable(this);
if (apiAvailability.isUserResolvableError(connectionStatusCode)) {
showGooglePlayServicesAvailabilityErrorDialog(connectionStatusCode);
}
}
/**
* Display an error dialog showing that Google Play Services is missing
* or out of date.
* #param connectionStatusCode code describing the presence (or lack of)
* Google Play Services on this device.
*/
void showGooglePlayServicesAvailabilityErrorDialog(
final int connectionStatusCode) {
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
Dialog dialog = apiAvailability.getErrorDialog(
AttendanceActivity.this,
connectionStatusCode,
REQUEST_GOOGLE_PLAY_SERVICES);
dialog.show();
}
/**
* An asynchronous task that handles the Google Sheets API call.
* Placing the API calls in their own task ensures the UI stays responsive.
*/
private class MakeRequestTask extends AsyncTask<Void, Void, List<String>> {
private com.google.api.services.sheets.v4.Sheets mService = null;
private Exception mLastError = null;
public MakeRequestTask(GoogleAccountCredential credential) {
HttpTransport transport = AndroidHttp.newCompatibleTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
mService = new com.google.api.services.sheets.v4.Sheets.Builder(
transport, jsonFactory, credential)
.setApplicationName("Google Sheets API Android Quickstart")
.build();
}
/**
* Background task to call Google Sheets API.
* #param params no parameters needed for this task.
*/
#Override
protected List<String> doInBackground(Void... params) {
try {
return getDataFromApi();
} catch (Exception e) {
mLastError = e;
cancel(true);
return null;
}
}
/**
* Fetch a list of names and majors of students in a sample spreadsheet:
* https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit
* #return List of names and majors
* #throws IOException
*/
private List<String> getDataFromApi() throws IOException {
String spreadsheetId = "1PWNdgkcmKVbzWc2e0rc5XWlI7pkF7xaYK7JQcq8Feyg";
String range = "Sheet1!A2:B300";
// It is "WorksheetName!StartingCell:NextColumn Convert Letters into numbers, and find the value of the difference
List<String> results = new ArrayList<String>();
ValueRange response = this.mService.spreadsheets().values()
.get(spreadsheetId, range)
.execute();
List<List<Object>> values = response.getValues();
if (values != null) {
for (List column : values) {
results.add(column.get(0) + "");
// The last value must be 1 less of the value of the difference above
}
}
return results;
}
#Override
protected void onPreExecute() {
mOutputText.setText("");
mProgress.show();
}
#Override
protected void onPostExecute(List<String> output) {
mProgress.hide();
if (output == null || output.size() == 0) {
mOutputText.setText("Invalid ID Number!");
} else {
//output.add(0, "This is a string before the list");
mOutputText.setText(TextUtils.join("\n", output));
}
}
#Override
protected void onCancelled() {
mProgress.hide();
if (mLastError != null) {
if (mLastError instanceof GooglePlayServicesAvailabilityIOException) {
showGooglePlayServicesAvailabilityErrorDialog(
((GooglePlayServicesAvailabilityIOException) mLastError)
.getConnectionStatusCode());
} else if (mLastError instanceof UserRecoverableAuthIOException) {
startActivityForResult(
((UserRecoverableAuthIOException) mLastError).getIntent(),
AttendanceActivity.REQUEST_AUTHORIZATION);
} else {
mOutputText.setText("The following error occurred:\n"
+ mLastError.getMessage());
}
} else {
mOutputText.setText("Request cancelled.");
}
}
}
}
However, I specifically need help on this part.
private List<String> getDataFromApi() throws IOException {
String spreadsheetId = "1PWNdgkcmKVbzWc2e0rc5XWlI7pkF7xaYK7JQcq8Feyg";
String range = "Sheet1!A2:B300";
// It is "WorksheetName!StartingCell:NextColumn Convert Letters into numbers, and find the value of the difference
List<String> results = new ArrayList<String>();
ValueRange response = this.mService.spreadsheets().values()
.get(spreadsheetId, range)
.execute();
List<List<Object>> values = response.getValues();
if (values != null) {
for (List column : values) {
results.add(column.get(0) + "");
// The last value must be 1 less of the value of the difference above
}
}
return results;
}
So what I have done is that I have an editText input field consisting of only numbers, and it's input is put into a public integer iString when I click a button.
Now, I have to declare SOMEHOW that Google Spreadsheets will search the first column(Column A) for iString. If it exists, then give the value of the adjacent column (Column B).
I know this was a bit long, but thank you for any particular insight or solutions you guys may have. Cheers!
Checking out the Reading & Writing Value section of the documentation, it doesn't indicate an easy way of retrieving the cell number of your use case. The spreadsheet.values.get API call will need the spreadsheetId and range, the request body only indicates a view VariableRenderOptions (formatted, unformatted, formula).
With this limitation, you can make use of the 2d array values from the response to check the array[x][0] if its the value of iString. Use that x value to update array[x][1] and call the update API.
Hopefully this could help you a bit for your scenario.
Happy coding!

Android/GoogleDrive Pictures upload

First i'm a french student so forgive my english..
I have started an app which takes photos and now I want it to save thoses photos on GoogleDrive. I followed the Google tutorial and I now have a mistake that I can't explain and I don't know how to solve it :
400 Bad Request
{
"code":400,
"errors":[{
"domain": "global",
"location": "fields",
"locationType": "parameter",
"message": "Invalid field selection items",
"reason": "invalidParameter"
}],
"message": "Invalid field selection items"
}
This link may help https://developers.google.com/drive/v3/web/handle-errors even if I don't really understand how it is suppose to help.
Of course, I did everything that google asked : https://developers.google.com/drive/quickstart/android
This is the activity in which there is the error.
I hope you will understand my problem and if you do and help to solve it I just have to say thank you (even if you just read)..
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.googleapis.extensions.android.gms.auth.GooglePlayServicesAvailabilityIOException;
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.ExponentialBackOff;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.*;
import android.accounts.AccountManager;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.text.method.ScrollingMovementMethod;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import com.google.api.client.json.gson.GsonFactory;
public class DriveActivity extends Activity {
GoogleAccountCredential mCredential;
private TextView mOutputText;
ProgressDialog mProgress;
static final int REQUEST_ACCOUNT_PICKER = 1000;
static final int REQUEST_AUTHORIZATION = 1001;
static final int REQUEST_GOOGLE_PLAY_SERVICES = 1002;
private static final String PREF_ACCOUNT_NAME = "accountName";
private static final String[] SCOPES = { DriveScopes.DRIVE_METADATA_READONLY };
/**
* Create the main activity.
* #param savedInstanceState previously saved instance data.
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout activityLayout = new LinearLayout(this);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
activityLayout.setLayoutParams(lp);
activityLayout.setOrientation(LinearLayout.VERTICAL);
activityLayout.setPadding(16, 16, 16, 16);
ViewGroup.LayoutParams tlp = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
mOutputText = new TextView(this);
mOutputText.setLayoutParams(tlp);
mOutputText.setPadding(16, 16, 16, 16);
mOutputText.setVerticalScrollBarEnabled(true);
mOutputText.setMovementMethod(new ScrollingMovementMethod());
activityLayout.addView(mOutputText);
mProgress = new ProgressDialog(this);
mProgress.setMessage("Connexion Google Drive ...");
setContentView(activityLayout);
// Initialize credentials and service object.
SharedPreferences settings = getPreferences(Context.MODE_PRIVATE);
mCredential = GoogleAccountCredential.usingOAuth2(
getApplicationContext(), Arrays.asList(SCOPES))
.setBackOff(new ExponentialBackOff())
.setSelectedAccountName(settings.getString(PREF_ACCOUNT_NAME, null));
}
/**
* Called whenever this activity is pushed to the foreground, such as after
* a call to onCreate().
*/
#Override
protected void onResume() {
super.onResume();
if (isGooglePlayServicesAvailable()) {
refreshResults();
} else {
mOutputText.setText("Google Play Services requièrent: " +
"après l'installation, fermer et relancer l'app.");
}
}
/**
* Called when an activity launched here (specifically, AccountPicker
* and authorization) exits, giving you the requestCode you started it with,
* the resultCode it returned, and any additional data from it.
* #param requestCode code indicating which activity result is incoming.
* #param resultCode code indicating the result of the incoming
* activity result.
* #param data Intent (containing result data) returned by incoming
* activity result.
*/
#Override
protected void onActivityResult(
int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode) {
case REQUEST_GOOGLE_PLAY_SERVICES:
if (resultCode != RESULT_OK) {
isGooglePlayServicesAvailable();
}
break;
case REQUEST_ACCOUNT_PICKER:
if (resultCode == RESULT_OK && data != null &&
data.getExtras() != null) {
String accountName =
data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
if (accountName != null) {
mCredential.setSelectedAccountName(accountName);
SharedPreferences settings =
getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putString(PREF_ACCOUNT_NAME, accountName);
editor.apply();
}
} else if (resultCode == RESULT_CANCELED) {
mOutputText.setText("Compte non spécifié.");
}
break;
case REQUEST_AUTHORIZATION:
if (resultCode != RESULT_OK) {
chooseAccount();
}
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
/**
* Attempt to get a set of data from the Drive API to display. If the
* email address isn't known yet, then call chooseAccount() method so the
* user can pick an account.
*/
private void refreshResults() {
if (mCredential.getSelectedAccountName() == null) {
chooseAccount();
} else {
if (isDeviceOnline()) {
new MakeRequestTask(mCredential).execute();
} else {
mOutputText.setText("Pas de connexion internet.");
}
}
}
/**
* Starts an activity in Google Play Services so the user can pick an
* account.
*/
private void chooseAccount() {
startActivityForResult(
mCredential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
}
/**
* Checks whether the device currently has a network connection.
* #return true if the device has a network connection, false otherwise.
*/
private boolean isDeviceOnline() {
ConnectivityManager connMgr =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
return (networkInfo != null && networkInfo.isConnected());
}
/**
* Check that Google Play services APK is installed and up to date. Will
* launch an error dialog for the user to update Google Play Services if
* possible.
* #return true if Google Play Services is available and up to
* date on this device; false otherwise.
*/
private boolean isGooglePlayServicesAvailable() {
final int connectionStatusCode =
GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (GooglePlayServicesUtil.isUserRecoverableError(connectionStatusCode)) {
showGooglePlayServicesAvailabilityErrorDialog(connectionStatusCode);
return false;
} else if (connectionStatusCode != ConnectionResult.SUCCESS ) {
return false;
}
return true;
}
/**
* Display an error dialog showing that Google Play Services is missing
* or out of date.
* #param connectionStatusCode code describing the presence (or lack of)
* Google Play Services on this device.
*/
void showGooglePlayServicesAvailabilityErrorDialog(
final int connectionStatusCode) {
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(
connectionStatusCode,
DriveActivity.this,
REQUEST_GOOGLE_PLAY_SERVICES);
dialog.show();
}
/**
* An asynchronous task that handles the Drive API call.
* Placing the API calls in their own task ensures the UI stays responsive.
*/
private class MakeRequestTask extends AsyncTask<Void, Void, List<String>> {
private com.google.api.services.drive.Drive mService = null;
private Exception mLastError = null;
public MakeRequestTask(GoogleAccountCredential credential) {
HttpTransport transport = AndroidHttp.newCompatibleTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
mService = new com.google.api.services.drive.Drive.Builder(
transport, jsonFactory, credential)
.setApplicationName("AthexisPics")
.build();
}
/**
* Background task to call Drive API.
* #param params no parameters needed for this task.
*/
#Override
protected List<String> doInBackground(Void... params) {
try {
return getDataFromApi();
} catch (Exception e) {
mLastError = e;
cancel(true);
return null;
}
}
/**
* Fetch a list of up to 10 file names and IDs.
* #return List of Strings describing files, or an empty list if no files
* found.
* #throws IOException
*/
private List<String> getDataFromApi() throws IOException {
// Get a list of up to 10 files.
List<String> fileInfo = new ArrayList<String>();
FileList result = mService.files().list()
.setPageSize(10)
.setFields("nextPageToken, items(id, name)")
.execute();
List<File> files = result.getFiles();
if (files != null) {
for (File file : files) {
fileInfo.add(String.format("%s (%s)\n",
file.getName(), file.getId()));
}
}
return fileInfo;
}
#Override
protected void onPreExecute() {
mOutputText.setText("");
mProgress.show();
}
#Override
protected void onPostExecute(List<String> output) {
mProgress.hide();
if (output == null || output.size() == 0) {
mOutputText.setText("Pas de résultats trouvés.");
} else {
output.add(0, "Données récupérées:");
mOutputText.setText(TextUtils.join("\n", output));
}
}
#Override
protected void onCancelled() {
mProgress.hide();
if (mLastError != null) {
if (mLastError instanceof GooglePlayServicesAvailabilityIOException) {
showGooglePlayServicesAvailabilityErrorDialog(
((GooglePlayServicesAvailabilityIOException) mLastError)
.getConnectionStatusCode());
} else if (mLastError instanceof UserRecoverableAuthIOException) {
startActivityForResult(
((UserRecoverableAuthIOException) mLastError).getIntent(),
DriveActivity.REQUEST_AUTHORIZATION);
} else {
mOutputText.setText("L'erreur suivante vient de se produire:\n"
+ mLastError.getMessage());
}
} else {
mOutputText.setText("Requête annulée.");
}
}
}
}
Dude, I figured it out!
Same error message was displayed to me while running sample code for Rest Api for Drive in Android.
The Error Message "Invalid field selection items" means that field item' is not recognized by the API. Actually the name of field must have been changed in API code, without corresponding changes in sample code (Bad Google).
So in your code, instead of this line:
setFields("nextPageToken, items(id, name)")
Try this line with changed field names:
setFields("nextPageToken, files(id, name)")
Apart from items <---> files, title(as given in online docs) <---> name.
Again, bad Google.
Based on the Official Google documentation the 400 'invalidParameter' means that a required field or parameter has not been provided, the value supplied is invalid or the combination of provided fields is invalid. Double check the parameter and value being set.
Here's a sample Demo app which takes photos and save them in Drive: https://github.com/googledrive/android-quickstart

Categories

Resources