I'm trying to run some Google Drive sample code from the Android Developers website but I'm getting a number of instances where Android Studio cannot resolve method. I think most of the problem might be attributed to BaseDemoActivity also not being recognized. I've gone through the setup process to make sure I have everything correct and as far as I can see it is, I even just this morning updated my Google Play Services version in case it was that but still nothing. Can someone point me in the right direction of how I might fix this?
/**
* An activity to illustrate how to create a new folder.
*/
public class CreateFolderActivity extends BaseDemoActivity {
#Override
public void onConnected(Bundle connectionHint) {
super.onConnected(connectionHint);
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setTitle("New folder").build();
Drive.DriveApi.getRootFolder(getGoogleApiClient()).createFolder(
getGoogleApiClient(), changeSet).addResultCallback(folderCreatedCallback);
}
ResultCallback<DriveFolderResult> folderCreatedCallback = new
ResultCallback<DriveFolderResult>() {
#Override
public void onResult(DriveFolderResult result) {
if (!result.getStatus().isSuccess()) {
showMessage("Error while trying to create the folder");
return;
}
showMessage("Created a folder: " + result.getDriveFolder().getDriveId());
}
}
}
BaseDemoActivity is not part of the API, its just used in the samples. Make sure you have that class copied into your app from the sample.
Related
I'm implementing Google Smart Lock into an app, and I was having no trouble with the Api Client building before. In fact, I was finalizing some syntax changes and cleaning up the code (didn't even touch the code that initializes the Api Client), and my app now dies when build() is called on the Api Client builder, due to abstract method zza. Here is the error being displayed:
java.lang.AbstractMethodError: abstract method "com.google.android.gms.common.api.Api$zze com.google.android.gms.common.api.Api$zza.zza(android.content.Context, android.os.Looper, com.google.android.gms.common.internal.zzq, java.lang.Object, com.google.android.gms.common.api.GoogleApiClient$ConnectionCallbacks, com.google.android.gms.common.api.GoogleApiClient$OnConnectionFailedListener)"
at com.google.android.gms.common.api.GoogleApiClient$Builder.build(Unknown Source)
I have no clue why it suddenly started failing, and I couldn't find any changes I made that would have caused this error. Why isn't that abstract method being overridden? It's nested deep inside the library so I don't understand how I could have affected it.
I wrapped the Google Api Client calls in a manager I named CredentialManager. Here is the code I used to initialize the client:
public CredentialManager(ContextProvider contextProvider) {
mContextProvider = contextProvider;
mCredentialsApiClient = new GoogleApiClient.Builder(mContextProvider.getContext())
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.i(CredentialManager.TAG, "Api connected");
}
#Override
public void onConnectionSuspended(int i) {
Log.i(CredentialManager.TAG, "Connection suspended with status " + i);
}
})
.enableAutoManage(mContextProvider.getContext(), connectionFailedResult -> {
if (connectionFailedResult.hasResolution()) {
try {
connectionFailedResult.startResolutionForResult(
mContextProvider.getContext(),
CredentialManager.Codes.RESOLVE_CONNECTION_REQUEST_CODE);
} catch (IntentSender.SendIntentException e) {
// Unable to resolve, log error
Log.e(CredentialManager.TAG, "Resolution failed: " + e.getMessage());
}
} else {
//instead of displaying a dialog, just let the user continue and login manually.
Log.e(CredentialManager.TAG, "Connection failed: " + connectionFailedResult.getErrorMessage());
}
})
.addApi(Auth.CREDENTIALS_API)
.build();
}
If you have any insight as to what is causing this error, please let me know. I've scoured the internet for anyone that has seen something like this before, but couldn't find anything.
The issue was that some google play services dependencies had their versions updated and not the play-services-auth dependency used for google smart lock. The apk would compile fine, but crash when the Google Api Client was trying to initialize. The fix was to make all the versions the same, and invalidate cache + restart android studio, recompile, and run.
I have the following scenario in my app -
SherlockFragmentActivity hosting a ViewPager containing 3 individual fragments. There is a sherlockactionbar on top, with backup and restore options, which should basically backup the app data to google drive account (connected to the user).
Now, everything works fine, wrt the backup-restore as well, by opening up the Google Api Client connection and uploading / downloading file, but as soon as the device rotates, the Activity is restarted from scratch and the google api client instance created and instantiated ealier (may be upload / download is also still in progress) becomes orphan.
I get a IllegalStateException (due to the activity restart, while the instance still needs an original activity to tie back to).
Knowing, that the Fragments themselves can be retained across activity restarts, I can put the drive api implementation in fragment, but having a common action bar icon on top, wouldn't it be a repetition to just put drive implementation on all 3 fragments??
Also, when the ViewPager swipe occurs, the fragment will be changed, so wouldn't I face the same issue again, wherein the original drive api client instance creator fragment is no longer in scope.?
What is a good way to implement such a thing? Any ideas would help me to research in given direction.
I have a viewpager and several fragments, just as your case. I let the my activity class extend the BaseDriveActivity from the Google-drive-exapmle, but letting it extend FragmentActivity instead of Activity.
The rotation was not any problem, even if onResume is called during rotation, sinde it is checking if mGoogleApiClient is null:
#Override
protected void onResume() {
super.onResume();
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API).addScope(Drive.SCOPE_FILE)
.addScope(Drive.SCOPE_APPFOLDER)
// required for App Folder sample
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
}
if (!mGoogleApiClient.isConnected() && !mGoogleApiClient.isConnecting())
mGoogleApiClient.connect();
}
There is some logic for errorhandling as well. You can use it as is.
The operations for creating a folder, creating a folder inside a foldet etc I added to my main class like this:
protected void createFolder(String folderName){
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setTitle(folderName).build();
Drive.DriveApi.getRootFolder(getGoogleApiClient()).createFolder(
getGoogleApiClient(), changeSet).setResultCallback(createFolderCallback);
}
final ResultCallback<DriveFolderResult> createFolderCallback = new ResultCallback<DriveFolderResult>() {
#Override
public void onResult(DriveFolderResult result) {
if (!result.getStatus().isSuccess()) {
showMessage("Error while trying to create the folder");
return;
}
showMessage("Created a folder: " + result.getDriveFolder().getDriveId());
}
};
private String folderName;
protected void createFolderInFolder(String exsistingDriveId, String folderName){
Drive.DriveApi.fetchDriveId(getGoogleApiClient(), exsistingDriveId).setResultCallback(idCallback);
this.folderName=folderName;
}
final ResultCallback<DriveIdResult> idCallback = new ResultCallback<DriveIdResult>() {
#Override
public void onResult(DriveIdResult result) {
if (!result.getStatus().isSuccess()) {
showMessage("Cannot find DriveId. Are you authorized to view this file?");
return;
}
DriveFolder folder = Drive.DriveApi
.getFolder(getGoogleApiClient(), result.getDriveId());
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setTitle(folderName).build();
folder.createFolder(getGoogleApiClient(), changeSet)
.setResultCallback(createFolderCallback);
}
};
private DriveId mFolderDriveId;
protected void createFileInFolder(String exsistingDriveId, String folderName){
Drive.DriveApi.fetchDriveId(getGoogleApiClient(), exsistingDriveId).setResultCallback(fileIdCallback);
this.folderName=folderName;
}
final private ResultCallback<DriveIdResult> fileIdCallback = new ResultCallback<DriveIdResult>() {
#Override
public void onResult(DriveIdResult result) {
if (!result.getStatus().isSuccess()) {
showMessage("Cannot find DriveId. Are you authorized to view this file?");
return;
}
mFolderDriveId = result.getDriveId();
Drive.DriveApi.newDriveContents(getGoogleApiClient())
.setResultCallback(driveContentsCallback);
}
};
final private ResultCallback<DriveContentsResult> driveContentsCallback =
new ResultCallback<DriveContentsResult>() {
#Override
public void onResult(DriveContentsResult result) {
if (!result.getStatus().isSuccess()) {
showMessage("Error while trying to create new file contents");
return;
}
DriveFolder folder = Drive.DriveApi.getFolder(getGoogleApiClient(), mFolderDriveId);
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setTitle(folderName)
.setMimeType("text/plain")
.setStarred(true).build();
folder.createFile(getGoogleApiClient(), changeSet, result.getDriveContents())
.setResultCallback(fileCallback);
}
};
final private ResultCallback<DriveFileResult> fileCallback =
new ResultCallback<DriveFileResult>() {
#Override
public void onResult(DriveFileResult result) {
if (!result.getStatus().isSuccess()) {
showMessage("Error while trying to create the file");
return;
}
showMessage("Created a file: " + result.getDriveFile().getDriveId());
}
};
EDIT:
I have found the following:
if createFolderInFolder (or any other of the api-funcions) is called, just before an intent is used to call an activity, the result-callback will not be called while the called activity is running. When the main activity is receiving control, the onResume is called, and giving an exception, since connect is called again. Then the result-callback is never called.
This means that the api-call and the result-callback must be able to run without any other calls being run.
New Edit:
Step1: You need a callback function in your Fragment
private Callbacks mCallbacks;
interface Callbacks {
public void onSaveToDrive(byte[] filecontent);
}
Step2: The main activity must implement the fragment callback-methods
Step3: Call the api-function, and add the fragment-update call in the result-callback
If you would like to store the driveid, you should use DriveId.encodeFromString(exsistingDriveId) and DriveId.decodeFromString(exsistingDriveId) in this way you can store the existingDriveId, and safely refer to it again at a later stage, even if the drive has been disconnected and reconnected.
Remember one api-call must be done without calling other classes, since that may cause the onResume() to be called.
I have a DropboxHelper Class that is handling downloading and uploading from dropbox.
Downloading works fine but when I try to upload from dropbox the first time the code is called. The following Line is false
if (dropboxFileSystem.isFile(dropboxPath)) {
}
It returns false. Tell the app to try again and this time it sees the file and uploads it to the app. Below is some of the code I am using for the class. Debug seems to incdicate the dropbox api has not completing started / synced the first time
public class DropBoxHelper {
public DropBoxHelper(Context pContext) {
context = pContext;
defineVariables();
}
private void defineVariables() {
dropboxAccountManager = DbxAccountManager.getInstance(context.getApplicationContext(), DROPBOX_APP_KEY, DROPBOX_APP_SECRET);
dropboxPath = new DbxPath(DbxPath.ROOT, DROPBOX_FILE_NAME);
}
public boolean importFromDropbox() {
try {
dropboxFileSystem = DbxFileSystem.forAccount(dropboxAccountManager.getLinkedAccount());
if (dropboxFileSystem.isFile(dropboxPath)) {
DbxFile databaseFileonDropbox = dropboxFileSystem.open(dropboxPath);
try {
// Do Copy
} finally {
Log.i(DEBUG_TAG, "Closing File");
databaseFileonDropbox.close();
}
}
Any ideas on why the copy fails first time.
Thanks
I'm not 100% sure, but I believe you need to use dropboxFileSystem.awaitFirstSync() to make sure at least one sync with the server has happened before you try to find the file.
An alternative might be to just call dropboxFileSystem.open(...) directly and handle the exception that's raised if the file doesn't exist.
I have to publish a paid app on Samsung Apps, so I have tried to implement Zirconia license management protection for Android, following the guide on the official Samsung Developer Site.
I have added the Zirconia.jar library to the build path, and the armeabi folder with the file libnativeinterface.so in the libs folder of the project.
When I try to run this simple test project
class MyLicenseCheckListener implements LicenseCheckListener {
public void licenseCheckedAsValid() {
Log.d("ZirconiaTest", "License is valid");
ownerHandler.post(new Runnable() {
public void run() {
ownerTextView.setText("Licenza verificata correttamente");
}
});
}
public void licenseCheckedAsInvalid() {
Log.d("ZirconiaTest", "License is invalid");
ownerHandler.post(new Runnable() {
public void run() {
ownerTextView.setText("Licenza non valida");
}
});
}
Handler ownerHandler;
TextView ownerTextView;
}
public class ZirconiaTest extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Handler handler = new Handler();
TextView tv = new TextView(this);
tv.setText( "This is a simple test application for Zirconia!\nPlease hold on while verifying the license..." );
setContentView(tv);
Zirconia zirconia = new Zirconia(this);
zirconia.doVariablesTest();
MyLicenseCheckListener listener = new MyLicenseCheckListener();
listener.ownerHandler = handler;
listener.ownerTextView = tv;
//zirconia.setBogusIMEI("");
zirconia.setLicenseCheckListener(listener);
zirconia.checkLicense(false, false);
zirconia.doVariablesTest();
}
}
I get this error and app crashes
01-04 22:09:23.519: E/dalvikvm(28775): Could not find class 'com.samsung.zirconia.Zirconia', referenced from method com.samsung.zirconia.test.ZirconiaTest.onCreate
01-04 22:09:23.519: W/dalvikvm(28775): VFY: unable to resolve new-instance 9 (Lcom/samsung/zirconia/Zirconia;) in Lcom/samsung/zirconia/test/ZirconiaTest;
What is wrong?
Oh, i had this error too. Here is solution :
Drag "Zirconia.jar" file and drop this into "libs" folder in your project, in Eclipse. Don't delete this from bulid path ! I attached photo for you. I hope I helped
This is an old question which I had forgotten.
This problem was caused by a corrupted Eclipse cache, deleting .metadata folder and recompiling the project the issue gone away.
I'm trying to use the APK Expansion extension from Google to download expansion files I have hosted with them. I'm also using the code from the SampleDownloadActivity to do this, albeit slightly modified to fit in my app.
My problem is that the download is never initiated. In my class that implements IDownloadClient, onStart() is called, but onServiceConnected() is not.
I have traced this down to this line in DownloaderClientMarshaller:
if( c.bindService(bindIntent, mConnection, Context.BIND_DEBUG_UNBIND) ) {
This always returns false, and therefore the service is not bound.
I'm using the calling activity within a TabHost, which has caused problems for other people. They were saying that you must not pass the TabHost context, rather that the Application context to the connect function. I've changed this by doing:
mDownloaderClientStub.connect(getApplicationContext());
instead of:
mDownloaderClientStub.connect(this);
but it doesn't help, I still get false. I'm doing all my testing on the Emulator if that makes a difference.
I'm really pulling my hair out on this one. If anyone has any ideas, I'd be extremely grateful!
In most cases, bindService() method returns false if the service was not declared in the application's Manifest file.
In my case, the problem was that I had given the wrong class object to the DownloaderClientMarshaller.CreateStub() method. I accidentally used DownloaderService.class instead of MyDownloaderService.class.
When using the downloader API, make sure to pass the correct class object that extends the base DownloaderService.
I recommend using the updated Downloader Library included in Better APK Expansion package. It has this and other issues fixed and also provides simplified API that minimizes chances to shoot yourself in the foot.
To receive the download progress, you will just have to extend the BroadcastDownloaderClient.
public class SampleDownloaderActivity extends AppCompatActivity {
private final DownloaderClient mClient = new DownloaderClient(this);
// ...
#Override
protected void onStart() {
super.onStart();
mClient.register(this);
}
#Override
protected void onStop() {
mClient.unregister(this);
super.onStop();
}
// ...
class DownloaderClient extends BroadcastDownloaderClient {
#Override
public void onDownloadStateChanged(int newState) {
if (newState == STATE_COMPLETED) {
// downloaded successfully...
} else if (newState >= 15) {
// failed
int message = Helpers.getDownloaderStringResourceIDFromState(newState);
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
}
#Override
public void onDownloadProgress(DownloadProgressInfo progress) {
if (progress.mOverallTotal > 0) {
// receive the download progress
// you can then display the progress in your activity
String progress = Helpers.getDownloadProgressPercent(
progress.mOverallProgress, progress.mOverallTotal);
Log.i("SampleDownloaderActivity", "downloading progress: " + progress);
}
}
}
}
Check the full documentation on the library's page.