java.lang.NoClassDefFoundError in android studio - android

I am getting java.lang.NoClassDefFoundError in android studio ,when i add a new class in my project that class is not detected by the rest of the code(It is not giving any compile time errors by not working as expected).
In this case I have added a UtilDateTime class which is giving java.lang.NoClassDefFoundError. Please help me out this probably does not seem to be a coding problem but something related to the libraries I am using(Though i am not sure of the sorce of problem).
The Log is showing this :-
08-08 17:03:36.832 19979-20179/com.indiacom.salondemo E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #3
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:299)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
at java.util.concurrent.FutureTask.run(FutureTask.java:239)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
at java.lang.Thread.run(Thread.java:838)
Caused by: java.lang.NoClassDefFoundError: com.indiacom.salondemo.utilities.UtilDateTime
at com.indiacom.salondemo.asynctask.CalendarApiAsyncTask.getDataFromApi(CalendarApiAsyncTask.java:86)
at com.indiacom.salondemo.asynctask.CalendarApiAsyncTask.doInBackground(CalendarApiAsyncTask.java:45)
at com.indiacom.salondemo.asynctask.CalendarApiAsyncTask.doInBackground(CalendarApiAsyncTask.java:22)
at android.os.AsyncTask$2.call(AsyncTask.java:287)
at java.util.concurrent.FutureTask.run(FutureTask.java:234)
            at
android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
            at java.lang.Thread.run(Thread.java:838)
This is my code :-
AppointmentActivity class:-
package com.indiacom.salondemo;
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.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.client.util.ExponentialBackOff;
import com.google.api.services.calendar.CalendarScopes;
import com.indiacom.salondemo.asynctask.CalendarApiAsyncTask;
import com.indiacom.salondemo.utilities.UtilDateTime;
import android.accounts.AccountManager;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Typeface;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.text.TextUtils;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class AppointmentActivity extends Activity {
/**
* A Google Calendar API service object used to access the API.
* Note: Do not confuse this class with API library's model classes, which
* represent specific data structures.
*/
public com.google.api.services.calendar.Calendar mService;
GoogleAccountCredential credential;
private TextView mStatusText;
private TextView mResultsText;
final HttpTransport transport = AndroidHttp.newCompatibleTransport();
final JsonFactory jsonFactory = GsonFactory.getDefaultInstance();
public static final int REQUEST_ACCOUNT_PICKER = 1000;
public 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 = { CalendarScopes.CALENDAR_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);
mStatusText = new TextView(this);
mStatusText.setLayoutParams(tlp);
mStatusText.setTypeface(null, Typeface.BOLD);
mStatusText.setText("Retrieving data...");
activityLayout.addView(mStatusText);
mResultsText = new TextView(this);
mResultsText.setLayoutParams(tlp);
mResultsText.setPadding(16, 16, 16, 16);
mResultsText.setVerticalScrollBarEnabled(true);
mResultsText.setMovementMethod(new ScrollingMovementMethod());
activityLayout.addView(mResultsText);
setContentView(activityLayout);
// Initialize credentials and service object.
SharedPreferences settings = getPreferences(Context.MODE_PRIVATE);
credential = GoogleAccountCredential.usingOAuth2(
getApplicationContext(), Arrays.asList(SCOPES))
.setBackOff(new ExponentialBackOff())
.setSelectedAccountName(settings.getString(PREF_ACCOUNT_NAME, null));
mService = new com.google.api.services.calendar.Calendar.Builder(
transport, jsonFactory, credential)
.setApplicationName("Google Calendar API Android Quickstart")
.build();
}
/**
* 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 {
mStatusText.setText("Google Play Services required: " +
"after installing, close and relaunch this 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) {
credential.setSelectedAccountName(accountName);
SharedPreferences settings =
getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putString(PREF_ACCOUNT_NAME, accountName);
editor.commit();
}
} else if (resultCode == RESULT_CANCELED) {
mStatusText.setText("Account unspecified.");
}
break;
case REQUEST_AUTHORIZATION:
if (resultCode != RESULT_OK) {
chooseAccount();
}
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
/**
* Attempt to get a set of data from the Google Calendar 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 (credential.getSelectedAccountName() == null) {
chooseAccount();
} else {
if (isDeviceOnline()) {
new CalendarApiAsyncTask(this).execute();
} else {
mStatusText.setText("No network connection available.");
}
}
}
/**
* Clear any existing Google Calendar API data from the TextView and update
* the header message; called from background threads and async tasks
* that need to update the UI (in the UI thread).
*/
public void clearResultsText() {
runOnUiThread(new Runnable() {
#Override
public void run() {
mStatusText.setText("Retrieving data…");
mResultsText.setText("");
}
});
}
/**
* Fill the data TextView with the given List of Strings; called from
* background threads and async tasks that need to update the UI (in the
* UI thread).
* #param dataStrings a List of Strings to populate the main TextView with.
*/
public void updateResultsText(final ArrayList<UtilDateTime> dataStrings) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (dataStrings == null) {
mStatusText.setText("Error retrieving data!");
} else if (dataStrings.size() == 0) {
mStatusText.setText("No data found.");
}else{
mStatusText.setText("Data retrieved using" +
" the Google Calendar API:");
String sss=dataStrings.get(0).getmDate();
Log.d("Sample String:","String sss="+sss);
mResultsText.setText(sss);
}
}
});
}
/**
* Show a status message in the list header TextView; called from background
* threads and async tasks that need to update the UI (in the UI thread).
* #param message a String to display in the UI header TextView.
*/
public void updateStatus(final String message) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mStatusText.setText(message);
}
});
}
/**
* Starts an activity in Google Play Services so the user can pick an
* account.
*/
private void chooseAccount() {
startActivityForResult(
credential.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.
*/
public void showGooglePlayServicesAvailabilityErrorDialog(
final int connectionStatusCode) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(
connectionStatusCode,
AppointmentActivity.this,
REQUEST_GOOGLE_PLAY_SERVICES);
dialog.show();
}
});
}
}
CalenderApiAsyncTask class :-
package com.indiacom.salondemo.asynctask;
import android.os.AsyncTask;
import android.util.Log;
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.util.DateTime;
import com.google.api.services.calendar.model.*;
import com.indiacom.salondemo.AppointmentActivity;
import com.indiacom.salondemo.AppointmentActivity;
import com.indiacom.salondemo.utilities.UtilDateTime;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* An asynchronous task that handles the Google Calendar API call.
* Placing the API calls in their own task ensures the UI stays responsive.
*/
public class CalendarApiAsyncTask extends AsyncTask<Void, Void, Void> {
private AppointmentActivity mActivity;
ArrayList<UtilDateTime> mArrList;
/**
* Constructor.
*
* #param activity MainActivity that spawned this task.
*/
public CalendarApiAsyncTask(AppointmentActivity activity) {
this.mActivity = activity;
}
/**
* Background task to call Google Calendar API.
*
* #param params no parameters needed for this task.
*/
#Override
protected Void doInBackground(Void... params) {
try {
mActivity.clearResultsText();
mActivity.updateResultsText(getDataFromApi());
} catch (final GooglePlayServicesAvailabilityIOException availabilityException) {
mActivity.showGooglePlayServicesAvailabilityErrorDialog(
availabilityException.getConnectionStatusCode());
} catch (UserRecoverableAuthIOException userRecoverableException) {
mActivity.startActivityForResult(
userRecoverableException.getIntent(),
AppointmentActivity.REQUEST_AUTHORIZATION);
} catch (Exception e) {
mActivity.updateStatus("The following error occurred:\n" +
e.getMessage());
}
return null;
}
/**
* Fetch a list of the next 10 events from the primary calendar.
*
* #return List of Strings describing returned events.
* #throws IOException
*/
private ArrayList<UtilDateTime> getDataFromApi() throws IOException {
// List the next 10 events from the primary calendar.
DateTime now = new DateTime(System.currentTimeMillis());
List<String> eventStrings = new ArrayList<String>();
Events events = mActivity.mService.events().list("primary")
.setMaxResults(10)
.setTimeMin(now)
.setOrderBy("startTime")
.setSingleEvents(true)
.execute();
List<Event> items = events.getItems();
mArrList= new ArrayList<UtilDateTime>();
for(int i=0;i<5;i++)
{
UtilDateTime objectForDateTime=new UtilDateTime();
objectForDateTime.setmDate("12-7-2015");
objectForDateTime.setmTime("12.00");
mArrList.add(objectForDateTime);
}
Log.e("arraylist::","list:"+mArrList.get(0).getmDate());
//
// for (Event event : items) {
// DateTime start = event.getStart().getDateTime();
// if (start == null) {
// // All-day events don't have start times, so just use
// // the start date.
// start = event.getStart().getDate();
// }
// eventStrings.add(
// String.format("%s (%s)", event.getSummary(), start));
// }
return mArrList;
}
}
UtilDateTime class :-
package com.indiacom.salondemo.utilities;
/**
* Created by cloud1 on 7/8/15.
*/
public class UtilDateTime {
String mDate, mTime;
public UtilDateTime()
{
}
public UtilDateTime(String mDate, String mTime) {
this.mDate = mDate;
this.mTime = mTime;
}
public String getmDate() {
return mDate;
}
public void setmDate(String mDate) {
this.mDate = mDate;
}
public String getmTime() {
return mTime;
}
public void setmTime(String mTime) {
this.mTime = mTime;
}
}

Related

getDriveResourceClient method cannot be resolved

I'm trying to create a google spreadsheet directly from android app using google drive api. I'm run the code given in quickstart https://developers.google.com/drive/v3/web/quickstart/android#step_5_setup_the_sample and it works fine. Now while creating spreadsheet, android studio cannot resolve
getDriveResourceClient()
method given in google docs : https://developers.google.com/drive/android/create-file .Can anyone tell me which import statement I have to add as android studio itself isn't suggesting any? This is how my code looks
I'm getting error within the getDataFromApi() method
package com.example.kriti.kidharhai;
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.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
import android.text.TextUtils;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.drive.DriveContents;
import com.google.android.gms.drive.DriveFile;
import com.google.android.gms.drive.DriveFolder;
import com.google.android.gms.drive.*;
import com.google.android.gms.drive.MetadataChangeSet;
import com.google.android.gms.tasks.Continuation;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.Tasks;
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.FileList;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executor;
import pub.devrel.easypermissions.AfterPermissionGranted;
import pub.devrel.easypermissions.EasyPermissions;
public class Door5 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;
private static final String BUTTON_TEXT = "Call Drive API";
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);
mCallApiButton = new Button(this);
mCallApiButton.setText(BUTTON_TEXT);
mCallApiButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mCallApiButton.setEnabled(false);
mOutputText.setText("");
getResultsFromApi();
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 Drive API ...");
setContentView(activityLayout);
// Initialize credentials and service object.
mCredential = GoogleAccountCredential.usingOAuth2(
getApplicationContext(), Arrays.asList(SCOPES))
.setBackOff(new ExponentialBackOff());
}
/**
* 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(
Door5.this,
connectionStatusCode,
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;
MakeRequestTask(GoogleAccountCredential credential) {
HttpTransport transport = AndroidHttp.newCompatibleTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
mService = new com.google.api.services.drive.Drive.Builder(
transport, jsonFactory, credential)
.setApplicationName("Drive API Android Quickstart")
.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()
.setFields("nextPageToken, files(id, name)")
.execute();
/*List<File> files = result.getFiles();
if (files != null) {
for (File file : files) {
fileInfo.add(String.format("%s (%s)\n",
file.getName()));
}
}*/
final Task<DriveFolder> rootFolderTask = getDriveResourceClient().getRootFolder();
final Task<DriveContents> createContentsTask = getDriveResourceClient().createContents();
Tasks.whenAll(rootFolderTask, createContentsTask)
.continueWithTask(new Continuation<Void, Task<DriveFile>>() {
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
public Task<DriveFile> then(#NonNull Task<Void> task) throws Exception {
DriveFolder parent = rootFolderTask.getResult();
DriveContents contents = createContentsTask.getResult();
OutputStream outputStream = contents.getOutputStream();
try (Writer writer = new OutputStreamWriter(outputStream)) {
writer.write("Hello World!");
}
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setTitle("HelloWorld.txt")
.setMimeType("text/plain")
.setStarred(true)
.build();
return getDriveResourceClient().createFile(parent, changeSet, contents);
}
})
.addOnSuccessListener((Executor) this,
new OnSuccessListener<DriveFile>() {
#Override
public void onSuccess(DriveFile driveFile) {
mOutputText.setText("Created");
finish();
}
})
.addOnFailureListener(this, new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.e(TAG, "Unable to create file", e);
showMessage(getString(R.string.file_create_error));
finish();
}
});
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("No results returned.");
} else {
output.add(0, "Data retrieved using the Drive API:");
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(),
Door5.REQUEST_AUTHORIZATION);
} else {
mOutputText.setText("The following error occurred:\n"
+ mLastError.getMessage());
}
} else {
mOutputText.setText("Request cancelled.");
}
}
}
}
This is my build.gradle file
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.1"
configurations.all {
resolutionStrategy.force 'com.google.code.findbugs:jsr305:1.3.9'
}
defaultConfig {
applicationId "com.example.kriti.kidharhai"
minSdkVersion 16
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.0.1'
//Added for firebase and Sheets
compile 'com.google.firebase:firebase-core:11.4.0'
compile 'com.google.firebase:firebase-database:11.4.0'
compile 'com.google.android.gms:play-services-auth:11.4.0'
compile 'pub.devrel:easypermissions:0.3.0'
testCompile 'junit:junit:4.12'
compile('com.google.api-client:google-api-client-android:1.23.0') {
exclude group: 'org.apache.httpcomponents'
}
compile('com.google.apis:google-api-services-sheets:v4-rev506-1.23.0') {
exclude group: 'org.apache.httpcomponents'
}
//For drive
compile 'com.google.android.gms:play-services-drive:11.4.0'
compile 'com.google.android.gms:play-services:11.4.0'
compile 'com.google.api-client:google-api-client-xml:1.18.0-rc'
compile 'com.google.http-client:google-http-client-gson:1.18.0-rc'
compile 'com.google.api-client:google-api-client-android:1.18.0-rc'
compile 'com.google.apis:google-api-services-drive:v2-rev155-1.19.0'
compile 'com.android.support.test.espresso:espresso-core:2.2.2'
}
apply plugin: 'com.google.gms.google-services'
AndroidManifest.xml file :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.kriti.kidharhai">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".Door1"
android:parentActivityName=".MainActivity"></activity>
<activity
android:name=".Door2"
android:parentActivityName=".MainActivity"></activity>
<activity
android:name=".Door3"
android:parentActivityName=".Door1"></activity>
<activity
android:name=".Door4"
android:parentActivityName=".Door1"></activity>
<activity
android:name=".Door5"
android:parentActivityName=".Door2"></activity>
<activity
android:name=".door6"
android:parentActivityName=".Door2"></activity>
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity" />
</application>
</manifest>
The issue is that the getdriveresourceclient function is an internal project function.
protected DriveResourceClient getDriveResourceClient() {
return mDriveResourceClient;
}
while mDriveResourceClient is
mDriveResourceClient = Drive.getDriveResourceClient(getApplicationContext(), signInAccount);
all can be found in the following link:
https://github.com/gsuitedevs/drive-android-demos/blob/71105dc51d466d4892e3798fcaa8cdde06e34a07/app/src/main/java/com/google/android/gms/drive/sample/demo/BaseDemoActivity.java
Best,
It seems to me there might be modules/package that you haven't imported yet. Anyway, for the full code sample of creating a file, refer to Drive API Android: Create a File.
Try importing these files
import com.google.android.gms.drive.Drive;
import com.google.android.gms.drive.DriveClient;
import com.google.android.gms.drive.DriveResourceClient;
U need client to get access to Drive Resources

App crashing due to two differnet Async Tasks?

So I have been working on this code for a while now trying to implement Google Visions into my prior app that displays an image from pixabay then tells me the tags of the photo.I had both the google vision app and pixabay app work just fine on their own. In this new version it should give me tags and the labels found by Google Visions but, whenever I activate the UP command on the sensors it crashes.
Here is my code:
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.MediaPlayer;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Vibrator;
import android.speech.tts.TextToSpeech;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.TextView;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.vision.v1.Vision;
import com.google.api.services.vision.v1.VisionRequest;
import com.google.api.services.vision.v1.VisionRequestInitializer;
import com.google.api.services.vision.v1.model.AnnotateImageRequest;
import com.google.api.services.vision.v1.model.BatchAnnotateImagesRequest;
import com.google.api.services.vision.v1.model.BatchAnnotateImagesResponse;
import com.google.api.services.vision.v1.model.EntityAnnotation;
import com.google.api.services.vision.v1.model.Feature;
import com.google.api.services.vision.v1.model.Image;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import static edu.ggc.lutz.recipe.pixabaysamplerwalkthrough.R.id.tvLabels;
import static edu.ggc.lutz.recipe.pixabaysamplerwalkthrough.R.id.tvTags;
public class MainActivity extends AppCompatActivity implements SensorEventListener {
public static final String PIXABAY = "Pixabay";
private ImageView imageView;
private static PixabayQueryResult result;
private String tags;
long numberOfHits;
long selected;
float[] gravity = new float[3];
float[] accel = new float[3];
private static final float ALPHA = 0.80f; // weighing factor used by the low pass filter
private static final String TAG = "OMNI";
private static final float VERTICAL_TOL = 0.3f;
private SensorManager manager;
private long lastUpdate;
private MediaPlayer popPlayer;
private MediaPlayer backgroundPlayer;
private TextToSpeech tts;
private TextView[] tvGravity;
private TextView[] tvAcceleration;
private boolean isDown = false;
private boolean isUp = false;
private static final String CLOUD_VISION_API_KEY = "AIzaSyCt35MZjvD_3ynTbYmeUuBFyMbYrjXUmzs";
private static final String ANDROID_CERT_HEADER = "X-Android-Cert";
private static final String ANDROID_PACKAGE_HEADER = "X-Android-Package";
private static final String TAGgoogle = MainActivity.class.getSimpleName();
private TextView pixtags;
private TextView googlelab;
private String urlString;
private Bitmap bitmapT;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
pixtags= (TextView) findViewById(tvTags);
googlelab= (TextView) findViewById(tvLabels);
/* FloatingActionButton fab = (FloatingActionButton) findViewById(fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
PixabayFetchTask task = new PixabayFetchTask();
String service = "https://pixabay.com/api/";
String key = "5535853-23bc4a5e307cd5d1a5e16ebcc";
String query_params = "&editor_choice=true&safesearch=true&image_type=photo";
String urlString = service + "?key=" + key + query_params;
task.execute(urlString);
}
});*/
imageView= (ImageView) findViewById(R.id.imageView);
tts = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
int result1=0;
if(status == TextToSpeech.SUCCESS) {
result1 = tts.setLanguage(Locale.US);
}
if( result1 == TextToSpeech.LANG_MISSING_DATA || result1== TextToSpeech.LANG_NOT_SUPPORTED){
Log.e("TTS", "This Language is not supported");
}
else
{
Log.e("TTS", "Inizalization Failed");
}
}
});
//////////////////////////
manager = (SensorManager) getSystemService(SENSOR_SERVICE);
lastUpdate = System.currentTimeMillis();
backgroundPlayer = MediaPlayer.create(this, R.raw.mistsoftime4tmono);
//////////////////////////
//callCloudVision("https://pixabay.com/get/eb36b90f2df1053ed95c4518b7494395e67fe7d604b0154892f2c67da7eabc_640.jpg");
}
///////////////////////////////
#Override
protected void onResume() {
super.onResume();
manager.registerListener(this, manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_UI);
backgroundPlayer.start();
}
//////////////////////////////
#Override
protected void onPause() {
super.onPause();
manager.unregisterListener(this);
backgroundPlayer.pause();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
Intent intent = new Intent(this, About.class);
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
}
public static long getRandomLong(long minimum, long maximum)
{
return (long) (Math.random()* (maximum- minimum))+ minimum;
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
#Override
public void onSensorChanged(SensorEvent event) {
gravity[0] = lowPass(event.values[0], gravity[0]);
gravity[1] = lowPass(event.values[1], gravity[1]);
gravity[2] = lowPass(event.values[2], gravity[2]);
accel[0] = highPass(event.values[0], accel[0]);
accel[1] = highPass(event.values[1], accel[1]);
accel[2] = highPass(event.values[2], accel[2]);
long actualTime = System.currentTimeMillis();
if (actualTime - lastUpdate > 100) {
if (inRange(gravity[2], -9.81f, VERTICAL_TOL)) {
Log.i(TAG, "Down");
if (!isDown) {
Vibrator v = (Vibrator) this.getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(500);
PixabayFetchTask task = new PixabayFetchTask();
String service = "https://pixabay.com/api/";
String key = "5535853-23bc4a5e307cd5d1a5e16ebcc";
String query_params = "&editor_choice=true&safesearch=true&image_type=photo";
urlString = service + "?key=" + key + query_params;
task.execute(urlString);
backgroundPlayer.setVolume(0.1f, 0.1f);
tts.speak("The device is pointing down", TextToSpeech.QUEUE_FLUSH, null);
backgroundPlayer.setVolume(1.0f, 1.0f);
isDown = true;
isUp = false;
}
} else if (inRange(gravity[2], 9.81f, VERTICAL_TOL)) {
if (!isUp) {
try {
callCloudVision(urlString);
} catch (IOException e) {
e.printStackTrace();
}
backgroundPlayer.setVolume(0.1f, 0.1f);
Log.i(TAG, "Up");
tags= (String) result.getTags((int)selected);
pixtags.setText("Tags: "+tags, null);
/* Snackbar.make(imageView, tags, Snackbar.LENGTH_LONG)
.setAction("Action", null).show();*/
tts.speak(tags.toString(), TextToSpeech.QUEUE_ADD, null);
//tts.speak("up", TextToSpeech.QUEUE_FLUSH, null);
backgroundPlayer.setVolume(1.0f, 1.0f);
isUp = true;
isDown = false;
}
} else {
Log.i(TAG, "In between");
//isDown = false; // Rubbish!
//isUp = false;
}
lastUpdate = actualTime;
}
}
private boolean inRange(float value, float target, float tol) {
return value >= target-tol && value <= target+tol;
}
// de-emphasize transient forces
private float lowPass(float current, float gravity) {
return current * (1-ALPHA) + gravity * ALPHA; // ALPHA indicates the influence of past observations
}
// de-emphasize constant forces
private float highPass(float current, float gravity) {
return current - gravity;
}
class PixabayFetchTask extends AsyncTask<String, Void, PixabayQueryResult> {
/**
* Override this method to perform a computation on a background thread. The
* specified parameters are the parameters passed to {#link #execute}
* by the caller of this task.
* <p>
* This method can call {#link #publishProgress} to publish updates
* on the UI thread.
*
* #param params The parameters of the task.
* #return A result, defined by the subclass of this task.
* #see #onPreExecute()
* #see #onPostExecute
* #see #publishProgress
*/
#Override
protected PixabayQueryResult doInBackground(String... params) {
Log.v(PIXABAY,"String[0] =" + params[0]);
if(result==null || result.isExpired()) {
try {
String line;
URL u = new URL(params[0]);
HttpURLConnection conn = (HttpURLConnection) u.openConnection();
InputStream in = new BufferedInputStream(conn.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder json = new StringBuilder();
while ((line = reader.readLine()) != null) json.append(line);
result = new PixabayQueryResult(json.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
/**
* <p>Runs on the UI thread after {#link #doInBackground}. The
* specified result is the value returned by {#link #doInBackground}.</p>
* <p>
* <p>This method won't be invoked if the task was cancelled.</p>
*
* #param bitmap The result of the operation computed by {#link #doInBackground}.
* #see #onPreExecute
* #see #doInBackground
* #see #onCancelled(Object)
*/
#Override
protected void onPostExecute(PixabayQueryResult result) {
super.onPostExecute(result);
numberOfHits= result.size();
selected = getRandomLong(0, numberOfHits);
Bitmap bitmap= result.getBitmap((int)selected);
imageView.setImageBitmap(bitmap);
/* try {
callCloudVision(urlString);
} catch (IOException e) {
e.printStackTrace();
}*/
}
}
private void callCloudVision(final String loc) throws IOException {
// Switch text to loading
googlelab.setText(R.string.loading_message);
// Do the real work in an async task, because we need to use the network anyway
new AsyncTask<Object, Bitmap, String>() {
#Override
protected String doInBackground(Object... params) {
try {
HttpTransport httpTransport = AndroidHttp.newCompatibleTransport();
JsonFactory jsonFactory = GsonFactory.getDefaultInstance();
VisionRequestInitializer requestInitializer =
new VisionRequestInitializer(CLOUD_VISION_API_KEY) {
/**
* We override this so we can inject important identifying fields into the HTTP
* headers. This enables use of a restricted cloud platform API key.
*/
#Override
protected void initializeVisionRequest(VisionRequest<?> visionRequest)
throws IOException {
super.initializeVisionRequest(visionRequest);
String packageName = getPackageName();
visionRequest.getRequestHeaders().set(ANDROID_PACKAGE_HEADER, packageName);
String sig = PackageManagerUtils.getSignature(getPackageManager(), packageName);
visionRequest.getRequestHeaders().set(ANDROID_CERT_HEADER, sig);
}
};
Vision.Builder builder = new Vision.Builder(httpTransport, jsonFactory, null);
builder.setVisionRequestInitializer(requestInitializer);
Vision vision = builder.build();
BatchAnnotateImagesRequest batchAnnotateImagesRequest =
new BatchAnnotateImagesRequest();
batchAnnotateImagesRequest.setRequests(new ArrayList<AnnotateImageRequest>() {{
AnnotateImageRequest annotateImageRequest = new AnnotateImageRequest();
Bitmap bitmap = null;
try {
InputStream stream = new URL(loc).openStream();
bitmap = BitmapFactory.decodeStream(stream);
publishProgress(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
// Add the image
Image base64EncodedImage = new Image();
// Convert the bitmap to a JPEG
// Just in case it's a format that Android understands but Cloud Vision
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, byteArrayOutputStream);
byte[] imageBytes = byteArrayOutputStream.toByteArray();
// Base64 encode the JPEG
base64EncodedImage.encodeContent(imageBytes);
annotateImageRequest.setImage(base64EncodedImage);
// add the features we want
annotateImageRequest.setFeatures(new ArrayList<Feature>() {{
Feature labelDetection = new Feature();
labelDetection.setType("LABEL_DETECTION");
labelDetection.setMaxResults(10);
add(labelDetection);
}});
// Add the list of one thing to the request
add(annotateImageRequest);
}});
Vision.Images.Annotate annotateRequest =
vision.images().annotate(batchAnnotateImagesRequest);
// Due to a bug: requests to Vision API containing large images fail when GZipped.
annotateRequest.setDisableGZipContent(true);
Log.d(TAGgoogle, "created Cloud Vision request object, sending request");
BatchAnnotateImagesResponse response = annotateRequest.execute();
return convertResponseToString(response);
} catch (GoogleJsonResponseException e) {
Log.d(TAGgoogle, "failed to make API request because " + e.getContent());
} catch (IOException e) {
Log.d(TAGgoogle, "failed to make API request because of other IOException " +
e.getMessage());
}
return "Cloud Vision API request failed. Check logs for details.";
}
/**
* Runs on the UI thread after {#link #publishProgress} is invoked.
* The specified values are the values passed to {#link #publishProgress}.
*
* #param bitmaps The values indicating progress.
* #see #publishProgress
* #see #doInBackground
*/
#Override
protected void onProgressUpdate(Bitmap... bitmaps) {
super.onProgressUpdate(bitmaps);
imageView.setImageBitmap(bitmaps[0]);
}
protected void onPostExecute(String result) {
googlelab.setText(result);
}
}.execute();
}
private String convertResponseToString(BatchAnnotateImagesResponse response) {
String message = "Labels:\n\n";
List<EntityAnnotation> labels = response.getResponses().get(0).getLabelAnnotations();
if (labels != null) {
for (EntityAnnotation label : labels) {
message += String.format(Locale.US, "%.3f: %s", label.getScore(), label.getDescription());
message += "\n";
}
} else {
message += "nothing";
}
return message;
}
}
Here is the it gives me error:
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #3
Process: edu.ggc.lutz.recipe.pixabaysamplerwalkthrough, PID: 21223 java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:309)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat, int, java.io.OutputStream)' on a null object reference
at edu.ggc.lutz.recipe.pixabaysamplerwalkthrough.MainActivity$2$2.<init>(MainActivity.java:419)
at edu.ggc.lutz.recipe.pixabaysamplerwalkthrough.MainActivity$2.doInBackground(MainActivity.java:400)
at edu.ggc.lutz.recipe.pixabaysamplerwalkthrough.MainActivity$2.doInBackground(MainActivity.java:366)
at android.os.AsyncTask$2.call(AsyncTask.java:295) at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
at java.lang.Thread.run(Thread.java:818)
There is another error that says something about the text to speech but I think that is the result of this error.
I believe it has something to do with running two different Async tasks at the same time overloading it or that fact a null value it getting passed in causing the error.

Android app + Drive API with full-drive access ... what's the procedure?

I'm looking for some guidance related to accessing Google Drive with an Android app.
1) I need to be able to read files uploaded by users outside of my app. Does this mean I need full-drive access? (If the app could create a folder and then see all files uploaded by the user that exist in this folder, that would be great, but I don't think it works this way.)
2) If I need full-drive access, it seems that Googles "Drive API for Android" doesn't support this, and I need to use the REST api. I think this is true.
3) I need an Auth 2.0 client ID from Google. If I use the rest API, does this mean I need to use a "Web Application" ID? I think I need this because I want an "auth code". I wasn't able to get it working with an "Android" type ID.
4) I'm currently using "Google Sign-In" for Android to handle the login and provide an auth code. I can then convert this into a Token + Refresh Token, and save these so I can get new tokens after an hour in some fashion. Is this manually handling of refresh tokens required?
It's getting ugly, but I think that since I need (?) full-drive access then this is the procedure.
Thanks for any guidance.
Edit: The question has been identified as a duplicate. The link provided gives an answer for question #2, but doesn't address the other questions.
I agree the question is messy...
I'm answering my own question.
I struggled with this because A) Google's REST example uses an outdated login process, B) The "Sign In" example uses code that doesn't work with "full-access" scope, and C) the there were too many vastly different code examples when trying to put it all together.
To quickly answer my questions as I see it now:
1) Yes, full-drive access is required to read files uploaded outside my app.
2) Yes, I need to use REST api.
3) Yes, I need a "Web Application" client ID.
4) Google Sign-In seems the best way currently to sign in, and using a GoogleCredential object along with the Drive api abject will handle the token refreshes automatically, as long as you keep around a refresh token.
In case anyone else is struggling with accessing Drive with full-access from Android using the latest "Sign-In" procedure and REST v3, below is my sample code.
In addition to the "Web application" OAuth client ID, you also need to create an "Android" type ID with a matching package name and certificate fingerprint in order for the Sign-In to work. Also note that you'll have different certificates for your dev and production versions. The IDs/codes from these Android clients do not need to be entered into the app.
build.gradle : app
// Google Sign In
compile 'com.google.android.gms:play-services-auth:10.0.1'
// Drive REST API
compile('com.google.apis:google-api-services-drive:v3-rev54-1.22.0') {
exclude group: 'org.apache.httpcomponents'
}
Activity
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Callback from Signin (Auth.GoogleSignInApi.getSignInIntent)
if (requestCode == 1) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
_googleApi.handleSignInResult(result);
}
}
A "GoogleApi" class to do the work
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.auth.api.signin.GoogleSignInResult;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Scope;
import com.google.android.gms.common.api.Status;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeTokenRequest;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.FileList;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class GoogleApi implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private Context _context;
private Handler _handler;
private GoogleCredential _credential;
private Drive _drive;
private GoogleApiClient _googleApiClient; // only set during login process
private Activity _activity; // launch intent for login (UI)
// Saved to data store
private boolean _loggedIn;
private String _refreshToken; // store, even if user is logged out as we may need to reuse
private static final String ClientID = "xxxxxx.apps.googleusercontent.com"; // web client
private static final String ClientSecret = "xxxxx"; // web client
private class FileAndErrorMsg {
public File file;
public String errorMsg;
public FileAndErrorMsg (File file_, String errorMsg_) { file = file_; errorMsg = errorMsg_; }
}
private class FileListAndErrorMsg {
public List<File> fileList;
public String errorMsg;
public FileListAndErrorMsg (List<File> fileList_, String errorMsg_) { fileList = fileList_; errorMsg = errorMsg_; }
}
// -------------------
// Constructor
// -------------------
public GoogleApi (Context context) {
_context = context;
_handler = new Handler();
loadFromPrefs(); // loggedIn, refreshToken
// create credential; will refresh itself automatically (in Drive calls) as long as valid refresh token exists
HttpTransport transport = new NetHttpTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
_credential = new GoogleCredential.Builder()
.setTransport(transport)
.setJsonFactory(jsonFactory)
.setClientSecrets(ClientID, ClientSecret) // .addRefreshListener
.build();
_credential.setRefreshToken(_refreshToken);
// Get app name from Manifest (for Drive builder)
ApplicationInfo appInfo = context.getApplicationInfo();
String appName = appInfo.labelRes == 0 ? appInfo.nonLocalizedLabel.toString() : context.getString(appInfo.labelRes);
_drive = new Drive.Builder(transport, jsonFactory, _credential).setApplicationName(appName).build();
}
// -------------------
// Auth
// -------------------
// https://developers.google.com/identity/sign-in/android/offline-access#before_you_begin
// https://developers.google.com/identity/sign-in/android/offline-access#enable_server-side_api_access_for_your_app
// https://android-developers.googleblog.com/2016/02/using-credentials-between-your-server.html
// https://android-developers.googleblog.com/2016/05/improving-security-and-user-experience.html
public boolean isLoggedIn () {
return _loggedIn;
}
public void startAuth(Activity activity) {
startAuth(activity, false);
}
public void startAuth(Activity activity, boolean forceRefreshToken) {
_activity = activity;
_loggedIn = false;
saveToPrefs();
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestScopes(new Scope("https://www.googleapis.com/auth/drive"))
.requestServerAuthCode(ClientID, forceRefreshToken) // if force, guaranteed to get back refresh token, but will show "offline access?" if Google already issued refresh token
.build();
_googleApiClient = new GoogleApiClient.Builder(activity)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
_googleApiClient.connect();
}
#Override
public void onConnected(Bundle connectionHint) {
// Called soon after .connect()
// This is only called when starting our Login process. Sign Out first so select-account screen shown. (OK if not already signed in)
Auth.GoogleSignInApi.signOut(_googleApiClient).setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
// Start sign in
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(_googleApiClient);
_activity.startActivityForResult(signInIntent, 1); // Activity's onActivityResult will use the same code: 1
}
});
}
#Override
public void onConnectionSuspended(int cause) {
authDone("Connection suspended.");
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) { authDone("Connection failed."); }
public void handleSignInResult(GoogleSignInResult result) {
// Callback from Activity > onActivityResult
if (result.isSuccess()) {
GoogleSignInAccount acct = result.getSignInAccount();
String authCode = acct.getServerAuthCode();
new Thread(new ContinueAuthWithAuthCode_Background(authCode)).start();
}
else authDone("Login canceled or unable to connect to Google."); // can we get better error message?
}
private class ContinueAuthWithAuthCode_Background implements Runnable {
String _authCode;
public ContinueAuthWithAuthCode_Background (String authCode) {
_authCode = authCode;
}
public void run() {
// Convert authCode to tokens
GoogleTokenResponse tokenResponse = null;
String errorMsg = null;
try {
tokenResponse = new GoogleAuthorizationCodeTokenRequest(new NetHttpTransport(), JacksonFactory.getDefaultInstance(), "https://www.googleapis.com/oauth2/v4/token", ClientID, ClientSecret, _authCode, "").execute();
}
catch (IOException e) { errorMsg = e.getLocalizedMessage(); }
final GoogleTokenResponse tokenResponseFinal = tokenResponse;
final String errorMsgFinal = errorMsg;
_handler.post(new Runnable() { public void run() {
// Main thread
GoogleTokenResponse tokenResponse = tokenResponseFinal;
String errorMsg = errorMsgFinal;
if (tokenResponse != null && errorMsg == null) {
_credential.setFromTokenResponse(tokenResponse); // this will keep old refresh token if no new one sent
_refreshToken = _credential.getRefreshToken();
_loggedIn = true;
saveToPrefs();
// FIXME: if our refresh token is bad and we're not getting a new one, how do we deal with this?
Log("New refresh token: " + tokenResponse.getRefreshToken());
}
else if (errorMsg == null) errorMsg = "Get token error."; // shouldn't get here
authDone(errorMsg);
} });
}
}
private void authDone(String errorMsg) {
// Disconnect (we only need googleApiClient for login process)
if (_googleApiClient != null && _googleApiClient.isConnected()) _googleApiClient.disconnect();
_googleApiClient = null;
}
/*
public void signOut() {
Auth.GoogleSignInApi.signOut(_googleApiClient).setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
}
});
}
public void revokeAccess() {
// FIXME: I don't know yet, but this may revoke access for all android devices
Auth.GoogleSignInApi.revokeAccess(_googleApiClient).setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
}
});
}
*/
public void LogOut() {
_loggedIn = false;
saveToPrefs(); // don't clear refresh token as we may need again
}
// -------------------
// API Calls
// -------------------
public void makeApiCall() {
new Thread(new TestApiCall_Background()).start();
}
private class TestApiCall_Background implements Runnable {
public void run() {
FileAndErrorMsg fileAndErr = getFolderFromName_b("Many Files", null);
if (fileAndErr.errorMsg != null) Log("getFolderFromName_b error: " + fileAndErr.errorMsg);
else {
FileListAndErrorMsg fileListAndErr = getFileListInFolder_b(fileAndErr.file);
if (fileListAndErr.errorMsg != null)
Log("getFileListInFolder_b error: " + fileListAndErr.errorMsg);
else {
Log("file count: " + fileListAndErr.fileList.size());
for (File file : fileListAndErr.fileList) {
//Log(file.getName());
}
}
}
_handler.post(new Runnable() { public void run() {
// Main thread
} });
}
}
private FileAndErrorMsg getFolderFromName_b (String folderName, File parent) {
// parent can be null for top level
// Working with folders: https://developers.google.com/drive/v3/web/folder
File folder = null;
folderName = folderName.replace("'", "\\'"); // escape '
String q = String.format(Locale.US, "mimeType='application/vnd.google-apps.folder' and '%s' in parents and name='%s' and trashed=false", parent == null ? "root" : parent.getId(), folderName);
String errorMsg = null;
try {
FileList result = _drive.files().list().setQ(q).setPageSize(1000).execute();
int foundCount = 0;
for (File file : result.getFiles()) {
foundCount++;
folder = file;
}
if (foundCount == 0) errorMsg = "Folder not found: " + folderName;
else if (foundCount > 1) errorMsg = "More than one folder found with name (" + foundCount + "): " + folderName;
}
catch (IOException e) { errorMsg = e.getLocalizedMessage(); }
if (errorMsg != null) folder = null;
return new FileAndErrorMsg(folder, errorMsg);
}
private FileListAndErrorMsg getFileListInFolder_b (File folder) {
// folder can be null for top level; does not return subfolder names
List<File> fileList = new ArrayList<File>();
String q = String.format(Locale.US, "mimeType != 'application/vnd.google-apps.folder' and '%s' in parents and trashed=false", folder == null ? "root" : folder.getId());
String errorMsg = null;
try {
String pageToken = null;
do {
FileList result = _drive.files().list().setQ(q).setPageSize(1000).setPageToken(pageToken).execute();
fileList.addAll(result.getFiles());
pageToken = result.getNextPageToken();
} while (pageToken != null);
}
catch (IOException e) { errorMsg = e.getLocalizedMessage(); }
if (errorMsg != null) fileList = null;
return new FileListAndErrorMsg(fileList, errorMsg);
}
// -------------------
// Misc
// -------------------
private void Log(String msg) {
Log.v("ept", msg);
}
// -------------------
// Load/Save Tokens
// -------------------
private void loadFromPrefs() {
SharedPreferences pref = _context.getSharedPreferences("prefs", Context.MODE_PRIVATE);
_loggedIn = pref.getBoolean("GoogleLoggedIn", false);
_refreshToken = pref.getString("GoogleRefreshToken", null);
}
private void saveToPrefs() {
SharedPreferences.Editor editor = _context.getSharedPreferences("prefs", Context.MODE_PRIVATE).edit();
editor.putBoolean("GoogleLoggedIn", _loggedIn);
editor.putString("GoogleRefreshToken", _refreshToken);
editor.apply(); // async
}
}
The latest example in https://developers.google.com/drive/v3/web/quickstart/android works out of the box.
Just do the following:
1 - Go to Google API console and create an OAuth2 Client ID using your package name and debug/release key as your Signing-certificate fingerprint.
2 - Enable Google Drive API
3 - Apply the following code
build.gradle : app
compile 'com.google.android.gms:play-services-auth:10.0.1'
compile 'pub.devrel:easypermissions:0.2.1'
compile('com.google.api-client:google-api-client-android:1.22.0') {
exclude group: 'org.apache.httpcomponents'
}
compile('com.google.apis:google-api-services-drive:v3-rev57-1.22.0') {
exclude group: 'org.apache.httpcomponents'
}
Activity
In this code just change the scope to DriveScopes.DRIVE for full drive access
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.drive.DriveScopes;
import com.google.api.services.drive.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.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;
private static final String BUTTON_TEXT = "Call Drive API";
private static final String PREF_ACCOUNT_NAME = "accountName";
private static final String[] SCOPES = { DriveScopes.DRIVE };
/**
* 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("");
getResultsFromApi();
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 Drive API ...");
setContentView(activityLayout);
// Initialize credentials and service object.
mCredential = GoogleAccountCredential.usingOAuth2(
getApplicationContext(), Arrays.asList(SCOPES))
.setBackOff(new ExponentialBackOff());
}
/**
* 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 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;
MakeRequestTask(GoogleAccountCredential credential) {
HttpTransport transport = AndroidHttp.newCompatibleTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
mService = new com.google.api.services.drive.Drive.Builder(
transport, jsonFactory, credential)
.setApplicationName("Drive API Android Quickstart")
.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, files(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("No results returned.");
} else {
output.add(0, "Data retrieved using the Drive API:");
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(),
MainActivity.REQUEST_AUTHORIZATION);
} else {
mOutputText.setText("The following error occurred:\n"
+ mLastError.getMessage());
}
} else {
mOutputText.setText("Request cancelled.");
}
}
}
}

Android Studio: Bluetooth Low Energy BLE Advertisements

on line 370 i need a way to look for a string of 'f's' in the advertisement data from a TI CC2650. I found this template online but I'm looking for specific advertising data. Please let me know what string array I need to look at to find this.
package net.jmodwyer.beacon.beaconPoC;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.content.SharedPreferences;
import android.location.Location;
import android.os.Bundle;
import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.text.util.Linkify;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ScrollView;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.location.LocationClient;
import net.jmodwyer.ibeacon.ibeaconPoC.R;
import org.altbeacon.beacon.Beacon;
import org.altbeacon.beacon.BeaconConsumer;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.RangeNotifier;
import org.altbeacon.beacon.Region;
import org.altbeacon.beacon.utils.UrlBeaconUrlCompressor;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
/**
* Adapted from original code written by D Young of Radius Networks.
* #author dyoung, jodwyer
*
*/
public class ScanActivity extends Activity implements BeaconConsumer,
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener {
// Constant Declaration
private static final String PREFERENCE_SCANINTERVAL = "scanInterval";
private static final String PREFERENCE_TIMESTAMP = "timestamp";
private static final String PREFERENCE_POWER = "power";
private static final String PREFERENCE_PROXIMITY = "proximity";
private static final String PREFERENCE_RSSI = "rssi";
private static final String PREFERENCE_MAJORMINOR = "majorMinor";
private static final String PREFERENCE_UUID = "uuid";
private static final String PREFERENCE_INDEX = "index";
private static final String PREFERENCE_LOCATION = "location";
private static final String PREFERENCE_REALTIME = "realTimeLog";
private static final String MODE_SCANNING = "Stop Scanning";
private static final String MODE_STOPPED = "Start Scanning";
protected static final String TAG = "ScanActivity";
/*
* Define a request code to send to Google Play services
* This code is returned in Activity.onActivityResult
*/
private final static int
CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
private FileHelper fileHelper;
private BeaconManager beaconManager;
private Region region;
private int eventNum = 1;
// This StringBuffer will hold the scan data for any given scan.
private StringBuffer logString;
// Preferences - will actually have a boolean value when loaded.
private Boolean index;
private Boolean location;
private Boolean uuid;
private Boolean majorMinor;
private Boolean rssi;
private Boolean proximity;
private Boolean power;
private Boolean timestamp;
private String scanInterval;
// Added following a feature request from D.Schmid.
private Boolean realTimeLog;
// LocationClient for Google Play Location Services
LocationClient locationClient;
private ScrollView scroller;
private EditText editText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scan);
verifyBluetooth();
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
BeaconScannerApp app = (BeaconScannerApp)this.getApplication();
beaconManager = app.getBeaconManager();
//beaconManager.setForegroundScanPeriod(10);
region = app.getRegion();
beaconManager.bind(this);
locationClient = new LocationClient(this, this, this);
fileHelper = app.getFileHelper();
scroller = (ScrollView)ScanActivity.this.findViewById(R.id.scanScrollView);
editText = (EditText)ScanActivity.this.findViewById(R.id.scanText);
// Initialise scan button.
getScanButton().setText(MODE_STOPPED);
}
#Override
public void onResume() {
super.onResume();
beaconManager.bind(this);
}
#Override
public void onPause() {
super.onPause();
// Uncommenting the following leak prevents a ServiceConnection leak when using the back
// arrow in the Action Bar to come out of the file list screen. Unfortunately it also kills
// background scanning, and as I have no workaround right now I'm settling for the lesser of
// two evils.
// beaconManager.unbind(this);
}
public String getCurrentLocation() {
/** Default "error" value is set for location, will be overwritten with the correct lat and
* long values if we're ble to connect to location services and get a reading.
*/
String location = "Unavailable";
if (locationClient.isConnected()) {
Location currentLocation = locationClient.getLastLocation();
if (currentLocation != null) {
location = Double.toString(currentLocation.getLatitude()) + "," +
Double.toString(currentLocation.getLongitude());
}
}
return location;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_activity_actions, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public void onBeaconServiceConnect() {}
/**
*
* #param view
*/
public void onScanButtonClicked(View view) {
toggleScanState();
}
// Handle the user selecting "Settings" from the action bar.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.Settings:
// Show settings
Intent api = new Intent(this, AppPreferenceActivity.class);
startActivityForResult(api, 0);
return true;
case R.id.action_listfiles:
// Launch list files activity
Intent fhi = new Intent(this, FileHandlerActivity.class);
startActivity(fhi);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/**
* Start and stop scanning, and toggle button label appropriately.
*/
private void toggleScanState() {
Button scanButton = getScanButton();
String currentState = scanButton.getText().toString();
if (currentState.equals(MODE_SCANNING)) {
stopScanning(scanButton);
} else {
startScanning(scanButton);
}
}
/**
* start looking for beacons.
*/
private void startScanning(Button scanButton) {
// Set UI elements to the correct state.
scanButton.setText(MODE_SCANNING);
((EditText)findViewById(R.id.scanText)).setText("");
// Reset event counter
eventNum = 1;
// Get current values for logging preferences
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
HashMap <String, Object> prefs = new HashMap<String, Object>();
prefs.putAll(sharedPrefs.getAll());
index = (Boolean)prefs.get(PREFERENCE_INDEX);
location = (Boolean)prefs.get(PREFERENCE_LOCATION);
uuid = (Boolean)prefs.get(PREFERENCE_UUID);
majorMinor = (Boolean)prefs.get(PREFERENCE_MAJORMINOR);
rssi = (Boolean)prefs.get(PREFERENCE_RSSI);
proximity = (Boolean)prefs.get(PREFERENCE_PROXIMITY);
power = (Boolean)prefs.get(PREFERENCE_POWER);
timestamp = (Boolean)prefs.get(PREFERENCE_TIMESTAMP);
scanInterval = (String)prefs.get(PREFERENCE_SCANINTERVAL);
realTimeLog = (Boolean)prefs.get(PREFERENCE_REALTIME);
// Get current background scan interval (if specified)
if (prefs.get(PREFERENCE_SCANINTERVAL) != null) {
beaconManager.setBackgroundBetweenScanPeriod(Long.parseLong(scanInterval));
}
logToDisplay("Scanning...");
// Initialise scan log
logString = new StringBuffer();
//Start scanning again.
beaconManager.setRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
if (beacons.size() > 0) {
Iterator <Beacon> beaconIterator = beacons.iterator();
while (beaconIterator.hasNext()) {
Beacon beacon = beaconIterator.next();
// Debug - logging a beacon - checking background logging is working.
System.out.println("Logging another beacon.");
logBeaconData(beacon);
}
}
}
});
try {
beaconManager.startRangingBeaconsInRegion(region);
} catch (RemoteException e) {
// TODO - OK, what now then?
}
}
/**
* Stop looking for beacons.
*/
private void stopScanning(Button scanButton) {
try {
beaconManager.stopRangingBeaconsInRegion(region);
} catch (RemoteException e) {
// TODO - OK, what now then?
}
String scanData = logString.toString();
if (scanData.length() > 0) {
// Write file
fileHelper.createFile(scanData);
// Display file created message.
Toast.makeText(getBaseContext(),
"File saved to:" + getFilesDir().getAbsolutePath(),
Toast.LENGTH_SHORT).show();
scanButton.setText(MODE_STOPPED);
} else {
// We didn't get any data, so there's no point writing an empty file.
Toast.makeText(getBaseContext(),
"No data captured during scan, output file will not be created.",
Toast.LENGTH_SHORT).show();
scanButton.setText(MODE_STOPPED);
}
}
/**
*
* #return reference to the start/stop scanning button
*/
private Button getScanButton() {
return (Button)findViewById(R.id.scanButton);
}
/**
*
* #param beacon The detected beacon
*/
private void logBeaconData(Beacon beacon) {
StringBuilder scanString = new StringBuilder();
if (index) {
scanString.append(eventNum++);
}
if (beacon.getServiceUuid() == 0xfeaa) {
if (beacon.getBeaconTypeCode() == 0x00) {
scanString.append(" Eddystone-UID -> ");
scanString.append(" Namespace : ").append(beacon.getId1());
scanString.append(" Identifier : ").append(beacon.getId2());
logEddystoneTelemetry(scanString, beacon);
} else if (beacon.getBeaconTypeCode() == 0x10) {
String url = UrlBeaconUrlCompressor.uncompress(beacon.getId1().toByteArray());
scanString.append(" Eddystone-URL -> " + url);
} else if (beacon.getBeaconTypeCode() == 0x20) {
scanString.append(" Eddystone-TLM -> ");
logEddystoneTelemetry(scanString, beacon);
}
} else {
// Just an old fashioned iBeacon or AltBeacon...
logGenericBeacon(scanString, beacon);
}
logToDisplay(scanString.toString());
scanString.append("\n");
// Code added following a feature request by D.Schmid - writes a single entry to a file
// every time a beacon is detected, the file will only ever have one entry as it will be
// recreated on each call to this method.
// Get current background scan interval (if specified)
if (realTimeLog) {
// We're in realtime logging mode, create a new log file containing only this entry.
fileHelper.createFile(scanString.toString(), "realtimelog.txt");
}
logString.append(scanString.toString());
}
/**
* Logs iBeacon & AltBeacon data.
*/
private void logGenericBeacon(StringBuilder scanString, Beacon beacon) {
// Comment stuff out for whatever reason
/*
if (location) {
scanString.append(" Location: ").append(getCurrentLocation()).append(" ");
}
`
*/
if (uuid) {
scanString.append(" UUID: ").append(beacon.getId1());
if (beacon.getId1().equals("ffffffff-ffff-ffff-ffff-ffffffffffff ")){
scanString.append("WE DID IT!!!!!!!!!!!");
}else{
scanString.append(" WE DID NOT DO IT =( ");
}
/*
if ((beacon.getId1()).equals ("f")){
scanString.append("WE DID IT!!!!!!!!!!!");
}else{
scanString.append(" WE DID NOT DO IT!!!!!!!!!!! ");
}
*/
}
// Making if statements to test for advertising data
/*
if (majorMinor) {
scanString.append(" Maj. Mnr.: ");
if (beacon.getId2() != null) {
scanString.append(beacon.getId2());
}
scanString.append("-");
if (beacon.getId3() != null) {
scanString.append(beacon.getId3());
}
}
if (rssi) {
scanString.append(" RSSI: ").append(beacon.getRssi());
}
if (proximity) {
scanString.append(" Proximity: ").append(BeaconHelper.getProximityString(beacon.getDistance()));
}
if (power) {
scanString.append(" Power: ").append(beacon.getTxPower());
}
if (timestamp) {
scanString.append(" Timestamp: ").append(BeaconHelper.getCurrentTimeStamp());
} */
}
private void logEddystoneTelemetry(StringBuilder scanString, Beacon beacon) {
// Do we have telemetry data?
if (beacon.getExtraDataFields().size() > 0) {
long telemetryVersion = beacon.getExtraDataFields().get(0);
long batteryMilliVolts = beacon.getExtraDataFields().get(1);
long pduCount = beacon.getExtraDataFields().get(3);
long uptime = beacon.getExtraDataFields().get(4);
scanString.append(" Telemetry version : " + telemetryVersion);
scanString.append(" Uptime (sec) : " + uptime);
scanString.append(" Battery level (mv) " + batteryMilliVolts);
scanString.append(" Tx count: " + pduCount);
}
}
/**
*
* #param line
*/
private void logToDisplay(final String line) {
runOnUiThread(new Runnable() {
public void run() {
editText.append(line + "\n");
// Temp code - don't really want to do this for every line logged, will look for a
// workaround.
Linkify.addLinks(editText, Linkify.WEB_URLS);
scroller.fullScroll(View.FOCUS_DOWN);
}
});
}
private void verifyBluetooth() {
try {
if (!BeaconManager.getInstanceForApplication(this).checkAvailability()) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Bluetooth not enabled");
builder.setMessage("Please enable bluetooth in settings and restart this application.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
finish();
System.exit(0);
}
});
builder.show();
}
}
catch (RuntimeException e) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Bluetooth LE not available");
builder.setMessage("Sorry, this device does not support Bluetooth LE.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
finish();
System.exit(0);
}
});
builder.show();
}
}
/* Location services code follows */
#Override
protected void onStart() {
super.onStart();
// Connect the client.
locationClient.connect();
}
#Override
protected void onStop() {
// Disconnect the client.
locationClient.disconnect();
super.onStop();
}
#Override
public void onConnected(Bundle dataBundle) {
// Uncomment the following line to display the connection status.
// Toast.makeText(this, "Connected", Toast.LENGTH_SHORT).show();
}
#Override
public void onDisconnected() {
// Display the connection status
Toast.makeText(this, "Disconnected. Please re-connect.",
Toast.LENGTH_SHORT).show();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
/* Google Play services can resolve some errors it detects.
* If the error has a resolution, try sending an Intent to
* start a Google Play services activity that can resolve
* error.
*/
if (connectionResult.hasResolution()) {
try {
// Start an Activity that tries to resolve the error
connectionResult.startResolutionForResult(
this,
CONNECTION_FAILURE_RESOLUTION_REQUEST);
/*
* Thrown if Google Play services canceled the original
* PendingIntent
*/
} catch (IntentSender.SendIntentException e) {
// Log the error
e.printStackTrace();
}
} else {
/*
* If no resolution is available, display a dialog to the
* user with the error.
*/
Toast.makeText(getBaseContext(),
"Location services not available, cannot track device location.",
Toast.LENGTH_SHORT).show();
}
}
// Define a DialogFragment that displays the error dialog
public static class ErrorDialogFragment extends DialogFragment {
// Global field to contain the error dialog
private Dialog mDialog;
// Default constructor. Sets the dialog field to null
public ErrorDialogFragment() {
super();
mDialog = null;
}
// Set the dialog to display
public void setDialog(Dialog dialog) {
mDialog = dialog;
}
// Return a Dialog to the DialogFragment.
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return mDialog;
}
}
/*
* Handle results returned to the FragmentActivity
* by Google Play services
*/
#Override
protected void onActivityResult(
int requestCode, int resultCode, Intent data) {
// Decide what to do based on the original request code
switch (requestCode) {
case CONNECTION_FAILURE_RESOLUTION_REQUEST :
/*
* If the result code is Activity.RESULT_OK, try
* to connect again
*/
switch (resultCode) {
case Activity.RESULT_OK :
/*
* TODO - Try the request again
*/
break;
}
}
}
}
Need to cast to string first .toString
if (uuid) {
scanString.append(" UUID: ").append(beacon.getId1());
// Making if statements to look for all f's in advertising data
if (beacon.getId1().toString().equals(Str1)){
scanString.append("\nAlarm ACTIVATED\n");
}else{
scanString.append("\n Alarm NOT active\n");
}
}

bounded service using messenger downloading images

I am not able to download image using messenger in boundservice eventhough in android manifest showing service in separate process
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="edu.vuum.mocca"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="19" />
<supports-screens android:smallScreens="false" android:xlargeScreens="true" android:normalScreens="true" android:largeScreens="true"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme"
android:uiOptions="splitActionBarWhenNarrow">
<activity
android:name="edu.vuum.mocca.DownloadActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="edu.vuum.mocca.DownloadService" android:process=":my_process"/>
</application>
</manifest>
Dowloadservice handler calling dowloadmessageandRespond it gives android.os.networkonmainthreadexception
But services handler runs in separate process so above execution shouldn't come?
If i do dowloadmessageandRespond method in separate thread then program runs fine which commented in dowloadmessageandRespond method.
package edu.vuum.mocca;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import android.app.Activity;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Base64;
import android.util.Log;
/**
* #class DownloadService
*
* #brief DownloadService receives an Intent containing a URL (which
* is a type of URI) and a Messenger. It downloads the file at
* the URL, stores it on the file system, then returns the path
* name to the caller using the supplied Messenger.
*
* The DownloadService class implements the CommandProcessor
* pattern and The Messenger is used as part of the Active
* Object pattern.
*/
public class DownloadService extends Service
{
/**
* Used for debugging.
*/
private final String TAG = getClass().getName();
private final static int LOG_OP = 1;
/**
* Looper associated with the HandlerThread.
*/
// private volatile Looper mServiceLooper;
/**
* Implementation a Messenger that encapsulates the RequestHandler
* used to handle request Messages sent from the
* UniqueIDGeneratorActivity.
*/
private final static String MESSAGE_URL = "course.examples.Services.Logging.MESSAGE";
final Messenger mMessengerImpl =
new Messenger(new ServiceHandler());
/**
* Factory method to make the desired Intent.
*/
public static Intent makeIntent(Context context
) {
// Create the Intent that's associated to the DownloadService
// class.
Intent intent = new Intent(context,
DownloadService.class);
return intent;
}
/**
* #class ServiceHandler
*
* #brief An inner class that inherits from Handler and uses its
* handleMessage() hook method to process Messages sent to
* it from onStartCommnand() that indicate which images to
* download.
*/
private final class ServiceHandler extends Handler {
/**
* A factory method that creates a Message to return to the
* DownloadActivity with the pathname of the downloaded image.
*/
private Message makeReplyMessage(String pathname){
Message message = Message.obtain();
// Return the result to indicate whether the download
// succeeded or failed.
message.arg1 = pathname == null
? Activity.RESULT_CANCELED
: Activity.RESULT_OK;
Bundle bundle = new Bundle();
// Pathname for the downloaded image.
bundle.putString("PATHNAME",
pathname);
message.setData(bundle);
return message;
}
/**
* A factory method that creates a Message that contains
* information on the image to download and how to stop the
* Service.
*/
/* private Message makeDownloadMessage(Intent intent,
int startId){
Message message = Message.obtain();
// Include Intent & startId in Message to indicate which URI
// to retrieve and which request is being stopped when
// download completes.
message.obj = intent;
message.arg1 = startId;
return message;
}*/
/**
* Retrieves the designated image and reply to the
* DownloadActivity via the Messenger .
*/
private void downloadImageAndReply(Message message) {
final Messenger messenger = message.replyTo;
final String url=message.getData().getString(MESSAGE_URL);
// Download the requested image.
//final String pathname;
// new Thread( new Runnable() {
// public void run(){
String pathname = downloadImage(DownloadService.this,url);
Log.d(TAG, "pathname----- after downloadImage()"+pathname);
sendPath(messenger, pathname);
// }
// }).start();
}
/**
* Send the pathname back to the DownloadActivity via the
* messenger.
*/
private void sendPath(Messenger messenger,
String pathname) {
// Call factory method to create Message.
Message message = makeReplyMessage(pathname);
try {
if (messenger == null)
Log.d(TAG, "replyMessenger is null");
else {
Log.d(TAG, "sending key" + pathname);
// Send pathname to back to the DownloadActivity.
messenger.send(message);
}
} catch (RemoteException e) {
Log.e(getClass().getName(),
"Exception while sending.",
e);
}
}
/**
* Create a file to store the result of a download.
*
* #param context
* #param url
* #return
* #throws IOException
*/
private File getTemporaryFile(final Context context,
final String url) throws IOException {
return context.getFileStreamPath(Base64.encodeToString(url.getBytes(),
Base64.NO_WRAP)
+ System.currentTimeMillis());
}
/**
* Copy the contents of an InputStream into an OutputStream.
*
* #param in
* #param out
* #return
* #throws IOException
*/
private int copy(final InputStream in,
final OutputStream out) throws IOException {
final int BUFFER_LENGTH = 1024;
final byte[] buffer = new byte[BUFFER_LENGTH];
int totalRead = 0;
int read = 0;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
totalRead += read;
}
return totalRead;
}
/**
* Download the requested image and return the local file path.
*
* #param context
* #param url
* #return
*/
public String downloadImage(final Context context,
final String url) {
try {
final File file = getTemporaryFile(context, url);
Log.d(getClass().getName(), " downloading to " + file);
final InputStream in = (InputStream)
new URL(url).getContent();
final OutputStream out =
new FileOutputStream(file);
copy(in, out);
in.close();
out.close();
return file.getAbsolutePath();
} catch (Exception e) {
Log.e(getClass().getName(),
"Exception while downloading. Returning null.");
Log.e(getClass().getName(),
e.toString());
e.printStackTrace();
return null;
}
}
/**
* Hook method that retrieves an image from a remote server.
*/
public void handleMessage( Message message) {
// Download the designated image and reply to the
// DownloadActivity via the Messenger sent with the
// Intent.
switch (message.what) {
case LOG_OP:
Log.i(TAG, message.getData().getString(MESSAGE_URL));
downloadImageAndReply(message);
break;
default:
super.handleMessage(message);
}
}
}
/**
* Hook method called when DownloadService is first launched by
* the Android ActivityManager.
*/
/* public void onCreate() {
super.onCreate();
// Create and start a background HandlerThread since by
// default a Service runs in the UI Thread, which we don't
// want to block.
HandlerThread thread =
new HandlerThread("DownloadService");
thread.start();
// Get the HandlerThread's Looper and use it for our Handler.
mServiceLooper = thread.getLooper();
mServiceHandler =
new ServiceHandler(mServiceLooper);
}*/
/**
* Hook method called each time a Started Service is sent an
* Intent via startService().
*/
/* public int onStartCommand(Intent intent,
int flags,
int startId) {
// Create a Message that will be sent to ServiceHandler to
// retrieve animagebased on the URI in the Intent.
Message message =
mServiceHandler.makeDownloadMessage(intent,
startId);
// Send the Message to ServiceHandler to retrieve an image
// based on contents of the Intent.
mServiceHandler.sendMessage(message);
// Don't restart the DownloadService automatically if its
// process is killed while it's running.
return Service.START_NOT_STICKY;
}*/
#Override
public IBinder onBind(Intent intent) {
return mMessengerImpl.getBinder();
}
}
downloadactivity downloadimage method Called when a user clicks the Download Image button to download image using the DownloadService
package edu.vuum.mocca;
import java.lang.ref.WeakReference;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
/**
* #class DownloadActivity
*
* #brief A class that allows a user to download a bitmap image using
* a DownloadService.
*/
public class DownloadActivity extends Activity {
/**
* Used for debugging.
*/
private final String TAG = getClass().getName();
private final static int LOG_OP = 1;
private final static String MESSAGE_URL = "course.examples.Services.Logging.MESSAGE";
private boolean mIsBound;
/**
* User's selection of URL to download
*/
private EditText mUrlEditText;
/**
* Image that's been downloaded
*/
private ImageView mImageView;
/**
* Default URL.
*/
private String mDefaultUrl =
"http://www.dre.vanderbilt.edu/~schmidt/ka.png";
/**
* Display progress of download
*/
private ProgressDialog mProgressDialog;
/**
* Reference to the Messenger that's implemented in the
* UniqueIDGeneratorService.
*/
private Messenger mMessengerRef = null;
/**
* This ServiceConnection is used to receive a Messenger proxy
* after binding to the UniqueIDGeneratorService using bindService().
*/
private ServiceConnection mConnection = new ServiceConnection() {
/**
* Called after the UniqueIDGeneratorService is connected to
* convey the result returned from onBind().
*/
public void onServiceConnected(ComponentName className,
IBinder messenger) {
//Log.d(TAG, "ComponentName:" + className);
// Create a newq Messenger that encapsulates the
// returned IBinder object and store it for later use
// in mMessengerRef.
mMessengerRef = new Messenger(messenger);
mIsBound = true;
}
/**
* Called if the Service crashes and is no longer
* available. The ServiceConnection will remain bound,
* but the service will not respond to any requests.
*/
public void onServiceDisconnected(ComponentName className) {
mMessengerRef = null;
mIsBound = false;
}
};
/**
* Method that initializes the Activity when it is first created.
*
* #param savedInstanceState
* Activity's previously frozen state, if there was one.
*/
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/**
* Sets the content view specified in the main.xml file.
*/
setContentView(R.layout.main);
/**
* Caches references to the EditText and ImageView objects in
* data members to optimize subsequent access.
*/
mUrlEditText = (EditText) findViewById(R.id.mUrlEditText);
mImageView = (ImageView) findViewById(R.id.mImageView);
}
/**
* Show a toast, notifying a user of an error when retrieving a
* bitmap.
*/
void showErrorToast(String errorString) {
Toast.makeText(this,
errorString,
Toast.LENGTH_LONG).show();
}
/**
* Display a downloaded bitmap image if it's non-null; otherwise,
* it reports an error via a Toast.
*
* #param image
* The bitmap image
*/
void displayImage(Bitmap image)
{
if (mImageView == null)
showErrorToast("Problem with Application,"
+ " please contact the Developer.");
else if (image != null)
mImageView.setImageBitmap(image);
else
showErrorToast("image is corrupted,"
+ " please check the requested URL.");
}
/**
* Called when a user clicks a button to reset an image to
* default.
*
* #param view
* The "Reset Image" button
*/
public void resetImage(View view) {
mImageView.setImageResource(R.drawable.default_image);
}
/**
* Called when a user clicks the Download Image button to download
* an image using the DownloadService
*
* #param view
* The "Download Image" button
*/
public void downloadImage(View view) {
// Obtain the requested URL from the user input.
if (mIsBound) {
String url = getUrlString();
Log.e(DownloadActivity.class.getSimpleName(),
"Downloading " + url);
hideKeyboard();
// Inform the user that the download is starting.
showDialog("downloading via startService()");
// Create a request Message that indicates the Service should
// send the reply back to ReplyHandler encapsulated by the
// Messenger.
Message msg = Message.obtain(null, LOG_OP);
Bundle bundle = new Bundle();
bundle.putString(MESSAGE_URL, url);
msg.setData(bundle);
// Message request = Message.obtain();
msg.replyTo = new Messenger(new DownloadHandler(this));
try {
if (mMessengerRef != null) {
Log.d(TAG, "sending message to service with url");
// Send the request Message to the
// UniqueIDGeneratorService.
mMessengerRef.send(msg);
}
} catch (RemoteException e) {
e.printStackTrace();
}
// Create an Intent to download an image in the background via
// a Service. The downloaded image is later diplayed in the
// UI Thread via the downloadHandler() method defined below.
// DownloadService.makeIntent(this, Uri.parse( getUrlString()));
}else{
Log.d(TAG, "service is not bounded restat again");
}
}
/**
* Hook method called by Android when this Activity becomes
* visible.
*/
#Override
protected void onStart() {
super.onStart();
Log.d(TAG, "onStart()");
Log.d(TAG, "calling bindService()");
if (mMessengerRef == null)
// Bind to the UniqueIDGeneratorService associated with this
// Intent.
bindService(DownloadService.makeIntent(this),
this.mConnection,
Context.BIND_AUTO_CREATE);
}
#Override
protected void onStop() {
super.onStop();
if (mIsBound)
unbindService(mConnection);
}
/**
* #class DownloadHandler
*
* #brief An inner class that inherits from Handler and uses its
* handleMessage() hook method to process Messages sent to
* it from the DownloadService.
*/
private static class DownloadHandler extends Handler {
/**
* Allows Activity to be garbage collected properly.
*/
private WeakReference<DownloadActivity> mActivity;
/**
* Class constructor constructs mActivity as weak reference
* to the activity
*
* #param activity
* The corresponding activity
*/
public DownloadHandler(DownloadActivity activity) {
mActivity = new WeakReference<DownloadActivity>(activity);
}
/**
/**
* This hook method is dispatched in response to receiving
* the pathname back from the DownloadService.
*/
public void handleMessage(Message msg) {
DownloadActivity activity = mActivity.get();
// Bail out of the DownloadActivity is gone.
if (activity == null)
return;
// Extract the data from Message, which is in the form
// of a Bundle that can be passed across processes.
Bundle data = msg.getData();
// Extract the pathname from the Bundle.
String pathname = data.getString("PATHNAME");
// See if things worked or not.
if (msg.arg1 != RESULT_OK || pathname == null)
activity.showDialog("failed download");
// Stop displaying the progress dialog.
activity.dismissDialog();
// Display the image in the UI Thread.
activity.displayImage(BitmapFactory.decodeFile(pathname));
}
};
/**
* Display the Dialog to the User.
*
* #param message
* The String to display what download method was used.
*/
public void showDialog(String message) {
mProgressDialog =
ProgressDialog.show(this,
"Download",
message,
true);
}
/**
* Dismiss the Dialog
*/
public void dismissDialog() {
if (mProgressDialog != null)
mProgressDialog.dismiss();
}
/**
* Hide the keyboard after a user has finished typing the url.
*/
private void hideKeyboard() {
InputMethodManager mgr =
(InputMethodManager) getSystemService
(Context.INPUT_METHOD_SERVICE);
mgr.hideSoftInputFromWindow(mUrlEditText.getWindowToken(),
0);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.download, menu);
return true;
}
/**
* Read the URL EditText and return the String it contains.
*
* #return String value in mUrlEditText
*/
String getUrlString() {
String s = mUrlEditText.getText().toString();
if (s.equals(""))
s = mDefaultUrl;
return s;
}
}
Bound service with messenger ,if it is running in separate process doesn't need separate thread to do long running task.
I need to know why this service of downloadimage not working even though its running in separate process.
Thanks for helping .
As there is a NetworkOnMainThreadException the solution is to put the network code in an AsyncTask or thread.

Categories

Resources