I'm making a module that can download all file from apps folder on dropbox to devices.
Now, I'm using Core API to download a file. Everything works fine. But with multiple file, I don't know when the current file finish download to go to the next file.
Here is my download code:
final String cachePath = FileHandler.ROOT_LOCAL_FOLDER_DIR + "/" + mFile.getFileName();
try {
mFos = new FileOutputStream(cachePath);
} catch (FileNotFoundException e) {
mErrorMsg = "Couldn't create a local file to store the image";
return false;
}
ProgressListener mProgressLisenter = new ProgressListener() {
#Override
public void onProgress(long arg0, long arg1) {
// TODO Auto-generated method stub
tmpFile = new File(cachePath);
OnDownloadProgressDropboxChecked(FileHandler.PROGRESS_STATUS_ONPROGRESS, (int) (arg0 * 100 / arg1));
}
#Override
public long progressInterval() {
return 100;
}
};
mDownloaded = mApi.getFile(mFile.getFileId(), null, mFos, mProgressLisenter);
OnDownloadDropboxChecked(TRUE, "Download complete");
} catch (DropboxUnlinkedException e) {
mErrorMsg = "Unlinked";
} catch (DropboxPartialFileException e) {
// We canceled the operation
mErrorMsg = "Download canceled";
} catch (DropboxServerException e) {
}
}
I've tried:
Catch progress download, when reached 100% then notify - On this way, the OnProgress of dropbox isn't show up imediately and sometime It not reach 100%
Put It in a asynctask - Useless
I'm out of idea now, any advance are good for me.
Edited:
the solution is put some trigger under getFile() then It work.
here is my complete class:
public class DownloadFile extends AsyncTask<Void, Long, Boolean> implements DConst {
Context act;
private DropboxAPI<?> mApi;
// private String mPath;
private FileOutputStream mFos;
private boolean mCanceled;
private Long mFileLen;
private String mErrorMsg;
private String mFileName;
String path;
DFile mFile;
DropboxAPI.DropboxFileInfo mDownloaded;
#SuppressWarnings("deprecation")
public DownloadFile(Context act, DropboxAPI<?> api, DFile mDFile) {
// We set the context this way so we don't accidentally leak activities
this.act = act;
mApi = api;
mFile = mDFile;
path = mDFile.getFileId();
mFileName = mDFile.getFileName();
OnDownloadProgressDropboxChecked(FileHandler.PROGRESS_STATUS_START, 0);
}
File tmpFile;
#Override
protected Boolean doInBackground(Void... params) {
try {
final String cachePath = FileHandler.ROOT_LOCAL_FOLDER_DIR + "/" + mFile.getFileName();
try {
mFos = new FileOutputStream(cachePath);
} catch (FileNotFoundException e) {
mErrorMsg = "Couldn't create a local file to store the image";
return false;
}
ProgressListener mProgressLisenter = new ProgressListener() {
#Override
public void onProgress(long arg0, long arg1) {
// TODO Auto-generated method stub
tmpFile = new File(cachePath);
OnDownloadProgressDropboxChecked(FileHandler.PROGRESS_STATUS_ONPROGRESS, (int) (arg0 * 100 / arg1));
Log.d("Dolphin got interval", String.valueOf(tmpFile.length() + " - " + arg0 + " - " + arg1));
}
#Override
public long progressInterval() {
return 100;
}
};
mDownloaded = mApi.getFile(mFile.getFileId(), null, mFos, mProgressLisenter);
} catch (DropboxUnlinkedException e) {
mErrorMsg = "Unlinked";
} catch (DropboxPartialFileException e) {
// We canceled the operation
mErrorMsg = "Download canceled";
} catch (DropboxServerException e) {
// Server-side exception. These are examples of what could happen,
// but we don't do anything special with them here.
if (e.error == DropboxServerException._304_NOT_MODIFIED) {
// won't happen since we don't pass in revision with metadata
} else if (e.error == DropboxServerException._401_UNAUTHORIZED) {
// Unauthorized, so we should unlink them. You may want to
// automatically log the user out in this case.
} else if (e.error == DropboxServerException._403_FORBIDDEN) {
// Not allowed to access this
} else if (e.error == DropboxServerException._404_NOT_FOUND) {
// path not found (or if it was the thumbnail, can't be
// thumbnailed)
} else if (e.error == DropboxServerException._406_NOT_ACCEPTABLE) {
// too many entries to return
} else if (e.error == DropboxServerException._415_UNSUPPORTED_MEDIA) {
// can't be thumbnailed
} else if (e.error == DropboxServerException._507_INSUFFICIENT_STORAGE) {
// user is over quota
} else {
// Something else
}
// This gets the Dropbox error, translated into the user's language
mErrorMsg = e.body.userError;
if (mErrorMsg == null) {
mErrorMsg = e.body.error;
}
} catch (DropboxIOException e) {
// Happens all the time, probably want to retry automatically.
mErrorMsg = "Network error. Try again.";
} catch (DropboxParseException e) {
// Probably due to Dropbox server restarting, should retry
mErrorMsg = "Dropbox error. Try again.";
} catch (DropboxException e) {
// Unknown error
mErrorMsg = "Unknown error. Try again.";
} finally {
if (mFos != null) {
try {
mFos.close();
return true;
} catch (IOException e) {
}
}
}
return false;
}
#Override
protected void onPostExecute(Boolean result) {
OnDownloadProgressDropboxChecked(FileHandler.PROGRESS_STATUS_FINISH, 0);
if (result) {
OnDownloadDropboxChecked(TRUE, "Download complete");
} else {
OnDownloadDropboxChecked(FALSE, mErrorMsg);
}
}
OnAsyncDownloadListener onAsyncDownloadListener;
OnAsyncDownloadProgressListener onAsyncDownloadProgressListener;
private void OnDownloadDropboxChecked(int res, String messenger) {
if (onAsyncDownloadListener != null) {
onAsyncDownloadListener.OnAsyncDownload(res, messenger);
}
}
private void OnDownloadProgressDropboxChecked(int status, int percent) {
if (onAsyncDownloadProgressListener != null) {
onAsyncDownloadProgressListener.OnAsyncDownloadProgress(status, percent);
}
}
public void setOnAsyncDownloadListener(OnAsyncDownloadListener listener) {
onAsyncDownloadListener = listener;
}
public void setOnAsyncDownloadProgressListener(OnAsyncDownloadProgressListener listener) {
onAsyncDownloadProgressListener = listener;
}
public interface OnAsyncDownloadListener {
public abstract void OnAsyncDownload(int res, String messenger);
}
public interface OnAsyncDownloadProgressListener {
public abstract void OnAsyncDownloadProgress(int status, int percent);
}
}
The error caused by 'OnDownloadDropboxChecked()' of Asynctask fired before the one of getFile(). So It return a false notify.
Converting my comment to an answer:
If I'm reading this right, you're using the Android Core API SDK, right? If so, I think that when mApi.getFile returns, the file has been downloaded. So you can do whatever you need to do on the next line.
Related
I am Uploading image files to Dropbox.
while uploading the images from android app to Dropbox, i want the Dropbox share Url link of each image.
then i want to save that link in local database.
Anyone Help me How to get this programatically.
my upload picture code to dropbox
MainActivity .java
public class MainActivity extends ActionBarActivity
{
private static final String TAG = "MY DropBox App";
private static final String APP_KEY = "************";
private static final String APP_SECRET = "***************";
// You don't need to change these, leave them alone.
private static final String ACCOUNT_PREFS_NAME = "prefs";
private static final String ACCESS_KEY_NAME = "ACCESS_KEY";
private static final String ACCESS_SECRET_NAME = "ACCESS_SECRET";
private static final boolean USE_OAUTH1 = false;
DropboxAPI<AndroidAuthSession> dropboxApi;
private boolean mLoggedIn;
// Android widgets
private Button mSubmit;
private LinearLayout mDisplay;
private Button mPhoto;
private Button mRoulette;
private ImageView mImage;
private final String PHOTO_DIR = "/Photos/MYPHOTOS/";
private static final int NEW_PICTURE = 1;
private String mCameraFileName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null)
{
mCameraFileName = savedInstanceState.getString("mCameraFileName");
}
// We create a new AuthSession so that we can use the Dropbox API.
AndroidAuthSession session = buildSession();
dropboxApi = new DropboxAPI<AndroidAuthSession>(session);
// Basic Android widgets
setContentView(R.layout.activity_main);
checkAppKeySetup();
mSubmit = (Button) findViewById(R.id.auth_button);
mSubmit.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// This logs you out if you're logged in, or vice versa
if (mLoggedIn) {
logOut();
} /*
* else { // Start the remote authentication if (USE_OAUTH1) {
* mApi.getSession().startAuthentication(DBRoulette.this); }
* else {
* mApi.getSession().startOAuth2Authentication(DBRoulette.this);
* } }
*/
}
});
mDisplay = (LinearLayout) findViewById(R.id.logged_in_display);
// This is where a photo is displayed
mImage = (ImageView) findViewById(R.id.image_view);
// This is the button to take a photo
mPhoto = (Button) findViewById(R.id.photo_button);
mPhoto.setOnClickListener(new OnClickListener() {
public void onClick(View v)
{
Intent intent = new Intent();
// Picture from camera
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
// This is not the right way to do this, but for some reason,
// having
// it store it in
// MediaStore.Images.Media.EXTERNAL_CONTENT_URI isn't working
// right.
Date date = new Date();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd-kk-mm-ss");
String newPicFile = df.format(date) + ".jpg";
Log.i(TAG, newPicFile);
String outPath = new File(Environment
.getExternalStorageDirectory(), newPicFile).getPath();
File outFile = new File(outPath);
mCameraFileName = outFile.toString();
Uri outuri = Uri.fromFile(outFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, outuri);
Log.i(TAG, "Importing New Picture: " + mCameraFileName);
try {
startActivityForResult(intent, NEW_PICTURE);
} catch (ActivityNotFoundException e) {
showToast("There doesn't seem to be a camera.");
}
}
});
// This is the button to Download photo
mRoulette = (Button) findViewById(R.id.roulette_button);
mRoulette.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
DownloadRandomPicture download = new DownloadRandomPicture(
MainActivity.this, dropboxApi, PHOTO_DIR, mImage);
download.execute();
}
});
// Display the proper UI state if logged in or not
setLoggedIn(dropboxApi.getSession().isLinked());
}
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putString("mCameraFileName", mCameraFileName);
super.onSaveInstanceState(outState);
}
#Override
protected void onResume() {
super.onResume();
AndroidAuthSession session = dropboxApi.getSession();
// The next part must be inserted in the onResume() method of the
// activity from which session.startAuthentication() was called, so
// that Dropbox authentication completes properly.
if (session.authenticationSuccessful()) {
try {
// Mandatory call to complete the auth
session.finishAuthentication();
// Store it locally in our app for later use
storeAuth(session);
setLoggedIn(true);
} catch (IllegalStateException e) {
showToast("Couldn't authenticate with Dropbox:"
+ e.getLocalizedMessage());
Log.i(TAG, "Error authenticating", e);
}
}
}
// This is what gets called on finishing a media piece to import
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == NEW_PICTURE) {
// return from file upload
if (resultCode == Activity.RESULT_OK) {
Uri uri = null;
if (data != null) {
uri = data.getData();
}
if (uri == null && mCameraFileName != null) {
uri = Uri.fromFile(new File(mCameraFileName));
}
File file = new File(mCameraFileName);
if (uri != null) {
UploadPicture upload = new UploadPicture(this, dropboxApi,
PHOTO_DIR, file);
upload.execute();
}
} else {
Log.w(TAG, "Unknown Activity Result from mediaImport: "
+ resultCode);
}
}
}
private void logOut() {
// Remove credentials from the session
dropboxApi.getSession().unlink();
// Clear our stored keys
clearKeys();
// Change UI state to display logged out version
setLoggedIn(false);
}
/**
* Convenience function to change UI state based on being logged in
*/
private void setLoggedIn(boolean loggedIn) {
mLoggedIn = loggedIn;
if (loggedIn) {
mSubmit.setText("Unlink from Dropbox");
mDisplay.setVisibility(View.VISIBLE);
} else {
mSubmit.setText("Link with Dropbox");
mDisplay.setVisibility(View.GONE);
mImage.setImageDrawable(null);
}
}
private void checkAppKeySetup() {
// Check to make sure that we have a valid app key
if (APP_KEY.startsWith("CHANGE") || APP_SECRET.startsWith("CHANGE")) {
showToast("You must apply for an app key and secret from developers.dropbox.com, and add them to the DBRoulette ap before trying it.");
finish();
return;
}
// Check if the app has set up its manifest properly.
Intent testIntent = new Intent(Intent.ACTION_VIEW);
String scheme = "db-" + APP_KEY;
String uri = scheme + "://" + AuthActivity.AUTH_VERSION + "/test";
testIntent.setData(Uri.parse(uri));
PackageManager pm = getPackageManager();
if (0 == pm.queryIntentActivities(testIntent, 0).size()) {
showToast("URL scheme in your app's "
+ "manifest is not set up correctly. You should have a "
+ "com.dropbox.client2.android.AuthActivity with the "
+ "scheme: " + scheme);
finish();
}
}
private void showToast(String msg) {
Toast error = Toast.makeText(this, msg, Toast.LENGTH_LONG);
error.show();
}
/**
* Shows keeping the access keys returned from Trusted Authenticator in a
* local store, rather than storing user name & password, and
* re-authenticating each time (which is not to be done, ever).
*/
private void loadAuth(AndroidAuthSession session) {
SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME, 0);
String key = "oauth2:";
String secret = "**************";
if (key == null || secret == null || key.length() == 0
|| secret.length() == 0)
return;
if (key.equals("oauth2:")) {
// If the key is set to "oauth2:", then we can assume the token is
// for OAuth 2.
session.setOAuth2AccessToken(secret);
} else {
// Still support using old OAuth 1 tokens.
session.setAccessTokenPair(new AccessTokenPair(key, secret));
}
}
/**
* Shows keeping the access keys returned from Trusted Authenticator in a
* local store, rather than storing user name & password, and
* re-authenticating each time (which is not to be done, ever).
*/
private void storeAuth(AndroidAuthSession session) {
// Store the OAuth 2 access token, if there is one.
String oauth2AccessToken = "****************";
if (oauth2AccessToken != null) {
SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME,
0);
Editor edit = prefs.edit();
edit.putString(ACCESS_KEY_NAME, "oauth2:");
edit.putString(ACCESS_SECRET_NAME, oauth2AccessToken);
edit.commit();
return;
}
// Store the OAuth 1 access token, if there is one. This is only
// necessary if
// you're still using OAuth 1.
AccessTokenPair oauth1AccessToken = session.getAccessTokenPair();
if (oauth1AccessToken != null) {
SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME,
0);
Editor edit = prefs.edit();
edit.putString(ACCESS_KEY_NAME, oauth1AccessToken.key);
edit.putString(ACCESS_SECRET_NAME, oauth1AccessToken.secret);
edit.commit();
return;
}
}
private void clearKeys() {
SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME, 0);
Editor edit = prefs.edit();
edit.clear();
edit.commit();
}
private AndroidAuthSession buildSession() {
AppKeyPair appKeyPair = new AppKeyPair(APP_KEY, APP_SECRET);
AndroidAuthSession session = new AndroidAuthSession(appKeyPair);
loadAuth(session);
return session;
}
}
UploadPicture .java
public class UploadPicture extends AsyncTask<Void, Long, Boolean> {
private DropboxAPI<?> mApi;
private String mPath;
private File mFile;
private long mFileLen;
private UploadRequest mRequest;
private Context mContext;
private final ProgressDialog mDialog;
private String mErrorMsg;
public UploadPicture(Context context, DropboxAPI<?> api, String dropboxPath,
File file) {
// We set the context this way so we don't accidentally leak activities
mContext = context.getApplicationContext();
mFileLen = file.length();
mApi = api;
mPath = dropboxPath;
mFile = file;
mDialog = new ProgressDialog(context);
mDialog.setMax(100);
mDialog.setMessage("Uploading " + file.getName());
mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mDialog.setProgress(0);
mDialog.setButton(ProgressDialog.BUTTON_POSITIVE, "Cancel", new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// This will cancel the putFile operation
mRequest.abort();
}
});
mDialog.show();
}
#Override
protected Boolean doInBackground(Void... params) {
try {
// By creating a request, we get a handle to the putFile operation,
// so we can cancel it later if we want to
FileInputStream fis = new FileInputStream(mFile);
String path = mPath + mFile.getName();
mRequest = mApi.putFileOverwriteRequest(path, fis, mFile.length(),new ProgressListener()
{
#Override
public long progressInterval()
{
// Update the progress bar every half-second or so
return 500;
}
#Override
public void onProgress(long bytes, long total)
{
publishProgress(bytes);
}
});
if (mRequest != null)
{
mRequest.upload();
return true;
}
} catch (DropboxUnlinkedException e) {
// This session wasn't authenticated properly or user unlinked
mErrorMsg = "This app wasn't authenticated properly.";
} catch (DropboxFileSizeException e) {
// File size too big to upload via the API
mErrorMsg = "This file is too big to upload";
} catch (DropboxPartialFileException e) {
// We canceled the operation
mErrorMsg = "Upload canceled";
} catch (DropboxServerException e) {
// Server-side exception. These are examples of what could happen,
// but we don't do anything special with them here.
if (e.error == DropboxServerException._401_UNAUTHORIZED) {
// Unauthorized, so we should unlink them. You may want to
// automatically log the user out in this case.
} else if (e.error == DropboxServerException._403_FORBIDDEN) {
// Not allowed to access this
} else if (e.error == DropboxServerException._404_NOT_FOUND) {
// path not found (or if it was the thumbnail, can't be
// thumbnailed)
} else if (e.error == DropboxServerException._507_INSUFFICIENT_STORAGE) {
// user is over quota
} else {
// Something else
}
// This gets the Dropbox error, translated into the user's language
mErrorMsg = e.body.userError;
if (mErrorMsg == null) {
mErrorMsg = e.body.error;
}
} catch (DropboxIOException e) {
// Happens all the time, probably want to retry automatically.
mErrorMsg = "Network error. Try again.";
} catch (DropboxParseException e) {
// Probably due to Dropbox server restarting, should retry
mErrorMsg = "Dropbox error. Try again.";
} catch (DropboxException e) {
// Unknown error
mErrorMsg = "Unknown error. Try again.";
} catch (FileNotFoundException e) {
}
return false;
}
#Override
protected void onProgressUpdate(Long... progress) {
int percent = (int)(100.0*(double)progress[0]/mFileLen + 0.5);
mDialog.setProgress(percent);
}
#Override
protected void onPostExecute(Boolean result) {
mDialog.dismiss();
if (result) {
showToast("Image successfully uploaded");
} else {
showToast(mErrorMsg);
}
}
private void showToast(String msg) {
Toast error = Toast.makeText(mContext, msg, Toast.LENGTH_LONG);
error.show();
}
Need to modify UploadPicture class:
Extract field from this variable:
String path = mPath + mFile.getName();
Put this snippet into onPostExecute method in upload successful case:
DropboxAPI.Entry filesInPath = mApi.metadata(path, 1, null, true, null);
// Basing on provided code, only one file is uploaded
DropboxAPI.Entry uploadedFile = entries.contents.get(0);
String shareUrl = mApi.share(uploadedFile.path).url;
After this manipulations shareUrl variable will contain sharing link for the image.
I think you're looking for share.
I'm doing an Android application which needs to list out all installed applications with cache size & app user data size. Now I want to clear the data (both cache & User data) of all installed applications. Below is my tried code.
Its not clearing data. When I go to Settings -> Applications -> Manage Applications -> Your Application -> Size is still showing as data & Cache. How could I remove those unused data for all installed applications. Thanks.
My code:
...
public static void trimCache(Context context) {
try {
File dir = context.getCacheDir();
if (dir != null && dir.isDirectory()) {
deleteDir(dir);
}
} catch (Exception e) {
// TODO: handle exception
}
}
public void clearApplicationData() {
File cache = getCacheDir();
File appDir = new File(cache.getParent());
if (appDir.exists()) {
String[] children = appDir.list();
for (String s : children) {
// if (!s.equals("lib")) {
deleteDir(new File(appDir, s));
Log.i("TAG", "**************** File /data/data/APP_PACKAGE/" + s + " DELETED *******************");
// }
}
}
}
public static boolean deleteDir(File dir) {
if (dir != null && dir.isDirectory()) {
String[] children = dir.list();
for (int i = 0; i < children.length; i++) {
boolean success = deleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
// The directory is now empty so delete it
return dir.delete();
}
private void showProgress(String message) {
pd = new ProgressDialog(this);
pd.setIcon(R.drawable.ic_launcher);
pd.setTitle("Please Wait...");
pd.setMessage(message);
pd.setCancelable(false);
pd.show();
}
long packageSize = 0, size = 0;
AppDetails cAppDetails;
public ArrayList<PackageInfoStruct> res;
private void getpackageSize() {
PACK_SIZE.clear();
DATA_SIZE.clear();
CACHE_SIZE.clear();
mPack = null;
mData = null;
mCache = null;
cAppDetails = new AppDetails(this);
res = cAppDetails.getPackages();
if (res == null)
return;
for (int m = 0; m < res.size(); m++) {
PackageManager pm = getPackageManager();
Method getPackageSizeInfo;
try {
getPackageSizeInfo = pm.getClass().getMethod(
"getPackageSizeInfo", String.class,
IPackageStatsObserver.class);
getPackageSizeInfo.invoke(pm, res.get(m).pname,
new cachePackState());
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
handle.sendEmptyMessage(ALL_PACAGE_SIZE_COMPLETED);
Log.v("Total Cache Size", " " + packageSize);
}
private Handler handle = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case FETCH_PACKAGE_SIZE_COMPLETED:
if (packageSize > 0)
size = (packageSize / 1024000);
lbl_cache_size.setText("Cache Size : " + size + " MB");
break;
case ALL_PACAGE_SIZE_COMPLETED:
MySimpleArrayAdapter adapter = new MySimpleArrayAdapter(
CacheList.this, mPack, mData, mCache);
lv.setAdapter(adapter);
if (null != pd)
if (pd.isShowing())
pd.dismiss();
break;
default:
break;
}
}
};
private class cachePackState extends IPackageStatsObserver.Stub {
#Override
public void onGetStatsCompleted(PackageStats pStats, boolean succeeded)
throws RemoteException {
Log.d("Package Size", pStats.packageName + "");
Log.i("Cache Size", pStats.cacheSize + "");
Log.w("Data Size", pStats.dataSize + "");
packageSize = packageSize + pStats.cacheSize;
Log.v("Total Cache Size", " " + packageSize);
PACK_SIZE.add(pStats.packageName);
DATA_SIZE.add(String.valueOf(pStats.dataSize / 1024000));
CACHE_SIZE.add(String.valueOf(pStats.cacheSize / 1024000));
mPack = PACK_SIZE.toArray(new String[PACK_SIZE.size()]);
mData = DATA_SIZE.toArray(new String[DATA_SIZE.size()]);
mCache = CACHE_SIZE.toArray(new String[CACHE_SIZE.size()]);
handle.sendEmptyMessage(FETCH_PACKAGE_SIZE_COMPLETED);
}
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_get_cacheSize:
size = 0;
packageSize = 0;
showProgress("Calculating Cache Size..!!!");
/**
* You can also use async task
* */
new Thread(new Runnable() {
#Override
public void run() {
getpackageSize();
}
}).start();
break;
case R.id.btn_clear_cache:
clearApplicationData();// Clear User Data
trimCache(CacheList.this);// Clear Cache Data
Toast.makeText(getApplicationContext(), "Successfully Cleared",
Toast.LENGTH_SHORT).show();
}
}
i have made an application that gives user option to upload and download dropbox application. i am giving my app secret and app key. the question is when some one else use my application do they need to enter their app secret and app key?
if yes, why? and if no then whats the actual purpose of app secret and app key. i am sharing the code as well:
upload file:
import com.dropbox.client2.DropboxAPI;
import com.dropbox.client2.DropboxAPI.UploadRequest;
import com.dropbox.client2.ProgressListener;
import com.dropbox.client2.exception.DropboxException;
import com.dropbox.client2.exception.DropboxFileSizeException;
import com.dropbox.client2.exception.DropboxIOException;
import com.dropbox.client2.exception.DropboxParseException;
import com.dropbox.client2.exception.DropboxPartialFileException;
import com.dropbox.client2.exception.DropboxServerException;
import com.dropbox.client2.exception.DropboxUnlinkedException;
/**
* Here we show uploading a file in a background thread, trying to show
* typical exception handling and flow of control for an app that uploads a
* file from Dropbox.
*/
public class UploadFile extends AsyncTask<Void, Long, Boolean> {
private DropboxAPI<?> mApi;
private String mPath;
private File mFile;
private long mFileLen;
private UploadRequest mRequest;
private Context mContext;
private final ProgressDialog mDialog;
private String mErrorMsg;
public UploadFile(Context context, DropboxAPI<?> api, String dropboxPath,
File file) {
// We set the context this way so we don't accidentally leak activities
mContext = context.getApplicationContext();
mFileLen = file.length();
mApi = api;
mPath = dropboxPath;
mFile = file;
mDialog = new ProgressDialog(context);
mDialog.setMax(100);
mDialog.setMessage("Uploading " + file.getName());
mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mDialog.setProgress(0);
mDialog.setButton(ProgressDialog.BUTTON_POSITIVE, "Cancel", new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// This will cancel the putFile operation
mRequest.abort();
}
});
mDialog.show();
}
#Override
protected Boolean doInBackground(Void... params) {
try {
// By creating a request, we get a handle to the putFile operation,
// so we can cancel it later if we want to
FileInputStream fis = new FileInputStream(mFile);
String path = mPath + mFile.getName();
mRequest = mApi.putFileOverwriteRequest(path, fis, mFile.length(),
new ProgressListener() {
#Override
public long progressInterval() {
// Update the progress bar every half-second or so
return 500;
}
#Override
public void onProgress(long bytes, long total) {
publishProgress(bytes);
}
});
if (mRequest != null) {
mRequest.upload();
return true;
}
} catch (DropboxUnlinkedException e) {
// This session wasn't authenticated properly or user unlinked
mErrorMsg = "This app wasn't authenticated properly.";
} catch (DropboxFileSizeException e) {
// File size too big to upload via the API
mErrorMsg = "This file is too big to upload";
} catch (DropboxPartialFileException e) {
// We canceled the operation
mErrorMsg = "Upload canceled";
} catch (DropboxServerException e) {
// Server-side exception. These are examples of what could happen,
// but we don't do anything special with them here.
if (e.error == DropboxServerException._401_UNAUTHORIZED) {
// Unauthorized, so we should unlink them. You may want to
// automatically log the user out in this case.
} else if (e.error == DropboxServerException._403_FORBIDDEN) {
// Not allowed to access this
} else if (e.error == DropboxServerException._404_NOT_FOUND) {
// path not found (or if it was the thumbnail, can't be
// thumbnailed)
} else if (e.error == DropboxServerException._507_INSUFFICIENT_STORAGE) {
// user is over quota
} else {
// Something else
}
// This gets the Dropbox error, translated into the user's language
mErrorMsg = e.body.userError;
if (mErrorMsg == null) {
mErrorMsg = e.body.error;
}
} catch (DropboxIOException e) {
// Happens all the time, probably want to retry automatically.
mErrorMsg = "Network error. Try again.";
} catch (DropboxParseException e) {
// Probably due to Dropbox server restarting, should retry
mErrorMsg = "Dropbox error. Try again.";
} catch (DropboxException e) {
// Unknown error
mErrorMsg = "Unknown error. Try again.";
} catch (FileNotFoundException e) {
}
return false;
}
#Override
protected void onProgressUpdate(Long... progress) {
int percent = (int)(100.0*(double)progress[0]/mFileLen + 0.5);
mDialog.setProgress(percent);
}
#Override
protected void onPostExecute(Boolean result) {
mDialog.dismiss();
if (result) {
showToast("File successfully uploaded");
} else {
showToast(mErrorMsg);
}
}
private void showToast(String msg) {
Toast error = Toast.makeText(mContext, msg, Toast.LENGTH_LONG);
error.show();
}
}
Download file:
/**
* Here we show getting metadata for a directory and downloading a file in a
* background thread, trying to show typical exception handling and flow of
* control for an app that downloads a file from Dropbox.
*/
public class DownloadFile extends AsyncTask<Void, Long, Boolean> {
private Context mContext;
private final ProgressDialog mDialog;
private DropboxAPI<?> mApi;
private String mPath;
private ImageView mView;
private Drawable mDrawable;
private FileOutputStream mFos;
private boolean mCanceled;
private Long mFileLen;
private String mErrorMsg;
// Note that, since we use a single file name here for simplicity, you
// won't be able to use this code for two simultaneous downloads.
private final static String IMAGE_FILE_NAME = "dbroulette.png";
private String localFilePath;
private String dropboxPath;
public DownloadFile(Context context, DropboxAPI<?> api,
String dropboxPath, String localFilePath) {
// We set the context this way so we don't accidentally leak activities
mContext = context.getApplicationContext();
this.localFilePath = localFilePath;
this.dropboxPath= dropboxPath;
mApi = api;
mPath = dropboxPath;
mDialog = new ProgressDialog(context);
mDialog.setMessage("Downloading File");
mDialog.setButton("Cancel", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
mCanceled = true;
mErrorMsg = "Canceled";
// This will cancel the getThumbnail operation by closing
// its stream
if (mFos != null) {
try {
mFos.close();
} catch (IOException e) {
}
}
}
});
mDialog.show();
}
#Override
protected Boolean doInBackground(Void... params) {
try{
File localFile = new File(localFilePath);
File fileSelected = new File(dropboxPath);
if (!localFile.exists()) {
localFile.createNewFile();
} else {
//copy(fileSelected, localFile);
//mApi.copy("/Test/test.png", "/sdcard/testfile.png");
BufferedInputStream br = null;
BufferedOutputStream bw = null;
DropboxInputStream fd;
try {
fd = mApi.getFileStream(fileSelected.getPath(), null);
br = new BufferedInputStream(fd);
bw = new BufferedOutputStream(new FileOutputStream(localFile));
byte[] buffer = new byte[4096];
int read;
while (true) {
read = br.read(buffer);
if (read <= 0) {
break;
}
bw.write(buffer, 0, read);
}
} catch (DropboxException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bw != null) {
try {
bw.close();
if (br != null) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}/*
else {
showToast("File already exists");
}*/
}
catch (IOException e) {
showToast("Exception");
e.printStackTrace();
}
catch (Exception e) {
showToast("Exception");
e.printStackTrace();
}
return false;
}
#Override
protected void onProgressUpdate(Long... progress) {
int percent = (int)(100.0*(double)progress[0]/mFileLen + 0.5);
mDialog.setProgress(percent);
}
#Override
protected void onPostExecute(Boolean result) {
mDialog.dismiss();
if (result) {
// Set the image now that we have it
//mView.setImageDrawable(mDrawable);
showToast("Successful download");
} else {
// Couldn't download it, so show an error
showToast(mErrorMsg);
}
}
private void showToast(String msg) {
Toast error = Toast.makeText(mContext, msg, Toast.LENGTH_LONG);
error.show();
}
}
main activity:
public class MainActivity extends Activity {
// Replace this with your app key and secret assigned by Dropbox.
// Note that this is a really insecure way to do this, and you shouldn't
// ship code which contains your key & secret in such an obvious way.
// Obfuscation is good.
final static private String APP_KEY = "";
final static private String APP_SECRET = "";
// You don't need to change these, leave them alone.
final static private String ACCOUNT_PREFS_NAME = "prefs";
final static private String ACCESS_KEY_NAME = "ACCESS_KEY";
final static private String ACCESS_SECRET_NAME = "ACCESS_SECRET";
private static final boolean USE_OAUTH1 = false;
DropboxAPI<AndroidAuthSession> mApi;
private boolean mLoggedIn;
private Button mSubmit;
private Button btnUpload;
private Button btnDownload;
private LinearLayout mDisplay;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// We create a new AuthSession so that we can use the Dropbox API.
AndroidAuthSession session = buildSession();
mApi = new DropboxAPI<AndroidAuthSession>(session);
setContentView(R.layout.main);
mSubmit = (Button)findViewById(R.id.auth_button);
btnDownload = (Button)findViewById(R.id.roulette_button);
btnUpload = (Button)findViewById(R.id.photo_button);
mDisplay = (LinearLayout)findViewById(R.id.logged_in_display);
mSubmit.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (mLoggedIn) {
logOut();
} else {
// Start the remote authentication
if (USE_OAUTH1) {
mApi.getSession().startAuthentication(MainActivity.this);
} else {
mApi.getSession().startOAuth2Authentication(MainActivity.this);
}
}
}
});
// Upload File
String testFile = "DeviceAdmin.apk";
String outPath = new File(Environment.getExternalStorageDirectory(), testFile).getPath();
Toast.makeText(MainActivity.this, outPath, Toast.LENGTH_LONG).show();
final File outFile = new File(outPath);
btnUpload.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
try{
UploadFile upload = new UploadFile(MainActivity.this, mApi, "/Test/", outFile);
upload.execute();
} catch (Exception e) {
Toast.makeText(MainActivity.this, "File not found", Toast.LENGTH_LONG).show();
}
}
});
// Download File
final String localFilePath = "/sdcard/testfile.txt";
final String dropboxPath= "/abc.txt";
btnDownload.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
DownloadFile download = new DownloadFile(MainActivity.this, mApi, dropboxPath, localFilePath);
download.execute();
}
});
setLoggedIn(mApi.getSession().isLinked());
}
private void setLoggedIn(boolean loggedIn) {
mLoggedIn = loggedIn;
if (loggedIn) {
Toast.makeText(MainActivity.this, "Successful login", Toast.LENGTH_LONG).show();
mDisplay.setVisibility(View.VISIBLE);
} else {
Toast.makeText(MainActivity.this, "logged out", Toast.LENGTH_LONG).show();
mDisplay.setVisibility(View.GONE);
}
}
private AndroidAuthSession buildSession() {
AppKeyPair appKeyPair = new AppKeyPair(APP_KEY, APP_SECRET);
AndroidAuthSession session = new AndroidAuthSession(appKeyPair);
loadAuth(session);
return session;
}
/**
* Shows keeping the access keys returned from Trusted Authenticator in a local
* store, rather than storing user name & password, and re-authenticating each
* time (which is not to be done, ever).
*/
private void loadAuth(AndroidAuthSession session) {
SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME, 0);
String key = prefs.getString(ACCESS_KEY_NAME, null);
String secret = prefs.getString(ACCESS_SECRET_NAME, null);
if (key == null || secret == null || key.length() == 0 || secret.length() == 0) return;
if (key.equals("oauth2:")) {
// If the key is set to "oauth2:", then we can assume the token is for OAuth 2.
session.setOAuth2AccessToken(secret);
} else {
// Still support using old OAuth 1 tokens.
session.setAccessTokenPair(new AccessTokenPair(key, secret));
}
}
#Override
protected void onResume() {
super.onResume();
AndroidAuthSession session = mApi.getSession();
// The next part must be inserted in the onResume() method of the
// activity from which session.startAuthentication() was called, so
// that Dropbox authentication completes properly.
if (session.authenticationSuccessful()) {
try {
// Mandatory call to complete the auth
session.finishAuthentication();
// Store it locally in our app for later use
storeAuth(session);
setLoggedIn(true);
} catch (IllegalStateException e) {
Toast.makeText(MainActivity.this, "Couldn't authenticate with Dropbox:" + e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
Log.i("Exception: ", "Error authenticating", e);
}
}
}
/**
* Shows keeping the access keys returned from Trusted Authenticator in a local
* store, rather than storing user name & password, and re-authenticating each
* time (which is not to be done, ever).
*/
private void storeAuth(AndroidAuthSession session) {
// Store the OAuth 2 access token, if there is one.
String oauth2AccessToken = session.getOAuth2AccessToken();
if (oauth2AccessToken != null) {
SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME, 0);
Editor edit = prefs.edit();
edit.putString(ACCESS_KEY_NAME, "oauth2:");
edit.putString(ACCESS_SECRET_NAME, oauth2AccessToken);
edit.commit();
return;
}
// Store the OAuth 1 access token, if there is one. This is only necessary if
// you're still using OAuth 1.
AccessTokenPair oauth1AccessToken = session.getAccessTokenPair();
if (oauth1AccessToken != null) {
SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME, 0);
Editor edit = prefs.edit();
edit.putString(ACCESS_KEY_NAME, oauth1AccessToken.key);
edit.putString(ACCESS_SECRET_NAME, oauth1AccessToken.secret);
edit.commit();
return;
}
}
private void clearKeys() {
SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME, 0);
Editor edit = prefs.edit();
edit.clear();
edit.commit();
}
private void logOut() {
// Remove credentials from the session
mApi.getSession().unlink();
// Clear our stored keys
clearKeys();
// Change UI state to display logged out version
setLoggedIn(false);
}
}
this is the code for reference, please have a look and give some suggestion.my main task is to retrieve a file, encrypt and upload it on dropbox.
No, users don't have to enter a different app key and secret. The app key and secret identifies your app. For example, when a user authorizes your app, they see the name of the app they're authorizing. That comes from the app key.
Only a small portion of my users are getting this error and I can't for the life of me figure it out. I use GooglePlayServicesUtil.isGooglePlayServicesAvailable(downloadService) to test whether or not Play Services is available, and it always returns SUCCESS. I setup the channel to connect to the Chromecast, and everything works fine up until the point where I try to use RemoteMediaPlayer.load. The result is always SIGN_IN_REQUIRED for some users, with resolution: null. The status.toString() is Failed to load: Status{statusCode=SIGN_IN_REQUIRED, resolution=null}. I'm really not sure what I am supposed to with this or how to get rid of the error for my few users who are getting this.
I don't know what portion is related, so I am just posting my entire controller class:
public class ChromeCastController extends RemoteController {
private static final String TAG = ChromeCastController.class.getSimpleName();
private CastDevice castDevice;
private GoogleApiClient apiClient;
private ConnectionCallbacks connectionCallbacks;
private ConnectionFailedListener connectionFailedListener;
private Cast.Listener castClientListener;
private boolean applicationStarted = false;
private boolean waitingForReconnect = false;
private boolean error = false;
private boolean ignoreNextPaused = false;
private String sessionId;
private FileProxy proxy;
private String rootLocation;
private RemoteMediaPlayer mediaPlayer;
private double gain = 0.5;
public ChromeCastController(DownloadService downloadService, CastDevice castDevice) {
this.downloadService = downloadService;
this.castDevice = castDevice;
SharedPreferences prefs = Util.getPreferences(downloadService);
rootLocation = prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null);
}
#Override
public void create(boolean playing, int seconds) {
downloadService.setPlayerState(PlayerState.PREPARING);
connectionCallbacks = new ConnectionCallbacks(playing, seconds);
connectionFailedListener = new ConnectionFailedListener();
castClientListener = new Cast.Listener() {
#Override
public void onApplicationStatusChanged() {
if (apiClient != null && apiClient.isConnected()) {
Log.i(TAG, "onApplicationStatusChanged: " + Cast.CastApi.getApplicationStatus(apiClient));
}
}
#Override
public void onVolumeChanged() {
if (apiClient != null && applicationStarted) {
try {
gain = Cast.CastApi.getVolume(apiClient);
} catch(Exception e) {
Log.w(TAG, "Failed to get volume");
}
}
}
#Override
public void onApplicationDisconnected(int errorCode) {
shutdownInternal();
}
};
Cast.CastOptions.Builder apiOptionsBuilder = Cast.CastOptions.builder(castDevice, castClientListener);
apiClient = new GoogleApiClient.Builder(downloadService)
.addApi(Cast.API, apiOptionsBuilder.build())
.addConnectionCallbacks(connectionCallbacks)
.addOnConnectionFailedListener(connectionFailedListener)
.build();
apiClient.connect();
}
#Override
public void start() {
if(error) {
error = false;
Log.w(TAG, "Attempting to restart song");
startSong(downloadService.getCurrentPlaying(), true, 0);
return;
}
try {
mediaPlayer.play(apiClient);
} catch(Exception e) {
Log.e(TAG, "Failed to start");
}
}
#Override
public void stop() {
try {
mediaPlayer.pause(apiClient);
} catch(Exception e) {
Log.e(TAG, "Failed to pause");
}
}
#Override
public void shutdown() {
try {
if(mediaPlayer != null && !error) {
mediaPlayer.stop(apiClient);
}
} catch(Exception e) {
Log.e(TAG, "Failed to stop mediaPlayer", e);
}
try {
if(apiClient != null) {
Cast.CastApi.stopApplication(apiClient);
Cast.CastApi.removeMessageReceivedCallbacks(apiClient, mediaPlayer.getNamespace());
mediaPlayer = null;
applicationStarted = false;
}
} catch(Exception e) {
Log.e(TAG, "Failed to shutdown application", e);
}
if(apiClient != null && apiClient.isConnected()) {
apiClient.disconnect();
}
apiClient = null;
if(proxy != null) {
proxy.stop();
proxy = null;
}
}
private void shutdownInternal() {
// This will call this.shutdown() indirectly
downloadService.setRemoteEnabled(RemoteControlState.LOCAL, null);
}
#Override
public void updatePlaylist() {
if(downloadService.getCurrentPlaying() == null) {
startSong(null, false, 0);
}
}
#Override
public void changePosition(int seconds) {
try {
mediaPlayer.seek(apiClient, seconds * 1000L);
} catch(Exception e) {
Log.e(TAG, "FAiled to seek to " + seconds);
}
}
#Override
public void changeTrack(int index, DownloadFile song) {
startSong(song, true, 0);
}
#Override
public void setVolume(boolean up) {
double delta = up ? 0.1 : -0.1;
gain += delta;
gain = Math.max(gain, 0.0);
gain = Math.min(gain, 1.0);
getVolumeToast().setVolume((float) gain);
try {
Cast.CastApi.setVolume(apiClient, gain);
} catch(Exception e) {
Log.e(TAG, "Failed to the volume");
}
}
#Override
public int getRemotePosition() {
if(mediaPlayer != null) {
return (int) (mediaPlayer.getApproximateStreamPosition() / 1000L);
} else {
return 0;
}
}
#Override
public int getRemoteDuration() {
if(mediaPlayer != null) {
return (int) (mediaPlayer.getStreamDuration() / 1000L);
} else {
return 0;
}
}
void startSong(DownloadFile currentPlaying, boolean autoStart, int position) {
if(currentPlaying == null) {
try {
if (mediaPlayer != null && !error) {
mediaPlayer.stop(apiClient);
}
} catch(Exception e) {
// Just means it didn't need to be stopped
}
downloadService.setPlayerState(PlayerState.IDLE);
return;
}
downloadService.setPlayerState(PlayerState.PREPARING);
MusicDirectory.Entry song = currentPlaying.getSong();
try {
MusicService musicService = MusicServiceFactory.getMusicService(downloadService);
String url;
// Offline, use file proxy
if(Util.isOffline(downloadService) || song.getId().indexOf(rootLocation) != -1) {
if(proxy == null) {
proxy = new FileProxy(downloadService);
proxy.start();
}
url = proxy.getPublicAddress(song.getId());
} else {
if(proxy != null) {
proxy.stop();
proxy = null;
}
if(song.isVideo()) {
url = musicService.getHlsUrl(song.getId(), currentPlaying.getBitRate(), downloadService);
} else {
url = musicService.getMusicUrl(downloadService, song, currentPlaying.getBitRate());
}
url = fixURLs(url);
}
// Setup song/video information
MediaMetadata meta = new MediaMetadata(song.isVideo() ? MediaMetadata.MEDIA_TYPE_MOVIE : MediaMetadata.MEDIA_TYPE_MUSIC_TRACK);
meta.putString(MediaMetadata.KEY_TITLE, song.getTitle());
if(song.getTrack() != null) {
meta.putInt(MediaMetadata.KEY_TRACK_NUMBER, song.getTrack());
}
if(!song.isVideo()) {
meta.putString(MediaMetadata.KEY_ARTIST, song.getArtist());
meta.putString(MediaMetadata.KEY_ALBUM_ARTIST, song.getArtist());
meta.putString(MediaMetadata.KEY_ALBUM_TITLE, song.getAlbum());
String coverArt = "";
if(proxy == null) {
coverArt = musicService.getCoverArtUrl(downloadService, song);
coverArt = fixURLs(coverArt);
meta.addImage(new WebImage(Uri.parse(coverArt)));
} else {
File coverArtFile = FileUtil.getAlbumArtFile(downloadService, song);
if(coverArtFile != null && coverArtFile.exists()) {
coverArt = proxy.getPublicAddress(coverArtFile.getPath());
meta.addImage(new WebImage(Uri.parse(coverArt)));
}
}
}
String contentType;
if(song.isVideo()) {
contentType = "application/x-mpegURL";
}
else if(song.getTranscodedContentType() != null) {
contentType = song.getTranscodedContentType();
} else if(song.getContentType() != null) {
contentType = song.getContentType();
} else {
contentType = "audio/mpeg";
}
// Load it into a MediaInfo wrapper
MediaInfo mediaInfo = new MediaInfo.Builder(url)
.setContentType(contentType)
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
.setMetadata(meta)
.build();
if(autoStart) {
ignoreNextPaused = true;
}
mediaPlayer.load(apiClient, mediaInfo, autoStart, position * 1000L).setResultCallback(new ResultCallback<RemoteMediaPlayer.MediaChannelResult>() {
#Override
public void onResult(RemoteMediaPlayer.MediaChannelResult result) {
if (result.getStatus().isSuccess()) {
// Handled in other handler
} else if(result.getStatus().getStatusCode() != ConnectionResult.SIGN_IN_REQUIRED) {
Log.e(TAG, "Failed to load: " + result.getStatus().toString());
failedLoad();
}
}
});
} catch (IllegalStateException e) {
Log.e(TAG, "Problem occurred with media during loading", e);
failedLoad();
} catch (Exception e) {
Log.e(TAG, "Problem opening media during loading", e);
failedLoad();
}
}
private String fixURLs(String url) {
// Only change to internal when using https
if(url.indexOf("https") != -1) {
SharedPreferences prefs = Util.getPreferences(downloadService);
int instance = prefs.getInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1);
String externalUrl = prefs.getString(Constants.PREFERENCES_KEY_SERVER_URL + instance, null);
String internalUrl = prefs.getString(Constants.PREFERENCES_KEY_SERVER_INTERNAL_URL + instance, null);
url = url.replace(internalUrl, externalUrl);
}
// Use separate profile for Chromecast so users can do ogg on phone, mp3 for CC
return url.replace(Constants.REST_CLIENT_ID, Constants.CHROMECAST_CLIENT_ID);
}
private void failedLoad() {
Util.toast(downloadService, downloadService.getResources().getString(R.string.download_failed_to_load));
downloadService.setPlayerState(PlayerState.STOPPED);
error = true;
}
private class ConnectionCallbacks implements GoogleApiClient.ConnectionCallbacks {
private boolean isPlaying;
private int position;
private ResultCallback<Cast.ApplicationConnectionResult> resultCallback;
ConnectionCallbacks(boolean isPlaying, int position) {
this.isPlaying = isPlaying;
this.position = position;
resultCallback = new ResultCallback<Cast.ApplicationConnectionResult>() {
#Override
public void onResult(Cast.ApplicationConnectionResult result) {
Status status = result.getStatus();
if (status.isSuccess()) {
ApplicationMetadata applicationMetadata = result.getApplicationMetadata();
sessionId = result.getSessionId();
String applicationStatus = result.getApplicationStatus();
boolean wasLaunched = result.getWasLaunched();
applicationStarted = true;
setupChannel();
} else {
shutdownInternal();
}
}
};
}
#Override
public void onConnected(Bundle connectionHint) {
if (waitingForReconnect) {
Log.i(TAG, "Reconnecting");
reconnectApplication();
} else {
launchApplication();
}
}
#Override
public void onConnectionSuspended(int cause) {
Log.w(TAG, "Connection suspended");
isPlaying = downloadService.getPlayerState() == PlayerState.STARTED;
position = getRemotePosition();
waitingForReconnect = true;
}
void launchApplication() {
try {
Cast.CastApi.launchApplication(apiClient, CastCompat.APPLICATION_ID, false).setResultCallback(resultCallback);
} catch (Exception e) {
Log.e(TAG, "Failed to launch application", e);
}
}
void reconnectApplication() {
try {
Cast.CastApi.joinApplication(apiClient, CastCompat.APPLICATION_ID, sessionId).setResultCallback(resultCallback);
} catch (Exception e) {
Log.e(TAG, "Failed to reconnect application", e);
}
}
void setupChannel() {
if(!waitingForReconnect) {
mediaPlayer = new RemoteMediaPlayer();
mediaPlayer.setOnStatusUpdatedListener(new RemoteMediaPlayer.OnStatusUpdatedListener() {
#Override
public void onStatusUpdated() {
MediaStatus mediaStatus = mediaPlayer.getMediaStatus();
if (mediaStatus == null) {
return;
}
switch (mediaStatus.getPlayerState()) {
case MediaStatus.PLAYER_STATE_PLAYING:
if (ignoreNextPaused) {
ignoreNextPaused = false;
}
downloadService.setPlayerState(PlayerState.STARTED);
break;
case MediaStatus.PLAYER_STATE_PAUSED:
if (!ignoreNextPaused) {
downloadService.setPlayerState(PlayerState.PAUSED);
}
break;
case MediaStatus.PLAYER_STATE_BUFFERING:
downloadService.setPlayerState(PlayerState.PREPARING);
break;
case MediaStatus.PLAYER_STATE_IDLE:
if (mediaStatus.getIdleReason() == MediaStatus.IDLE_REASON_FINISHED) {
downloadService.setPlayerState(PlayerState.COMPLETED);
downloadService.onSongCompleted();
} else if (mediaStatus.getIdleReason() == MediaStatus.IDLE_REASON_INTERRUPTED) {
if (downloadService.getPlayerState() != PlayerState.PREPARING) {
downloadService.setPlayerState(PlayerState.PREPARING);
}
} else if (mediaStatus.getIdleReason() == MediaStatus.IDLE_REASON_ERROR) {
Log.e(TAG, "Idle due to unknown error");
downloadService.setPlayerState(PlayerState.COMPLETED);
downloadService.next();
} else {
Log.w(TAG, "Idle reason: " + mediaStatus.getIdleReason());
downloadService.setPlayerState(PlayerState.IDLE);
}
break;
}
}
});
}
try {
Cast.CastApi.setMessageReceivedCallbacks(apiClient, mediaPlayer.getNamespace(), mediaPlayer);
} catch (IOException e) {
Log.e(TAG, "Exception while creating channel", e);
}
if(!waitingForReconnect) {
DownloadFile currentPlaying = downloadService.getCurrentPlaying();
startSong(currentPlaying, isPlaying, position);
}
if(waitingForReconnect) {
waitingForReconnect = false;
}
}
}
private class ConnectionFailedListener implements GoogleApiClient.OnConnectionFailedListener {
#Override
public void onConnectionFailed(ConnectionResult result) {
shutdownInternal();
}
}
}
Edit for logs:
03-28 19:04:49.757 6305-6305/github.daneren2005.dsub I/ChromeCastController﹕ onApplicationStatusChanged: Chromecast Home Screen
03-28 19:04:52.280 6305-6305/github.daneren2005.dsub I/ChromeCastController﹕ onApplicationStatusChanged: null
03-28 19:04:54.162 6305-6305/github.daneren2005.dsub I/ChromeCastController﹕ onApplicationStatusChanged: Ready To Cast
03-28 19:05:05.194 6305-6305/github.daneren2005.dsub E/ChromeCastController﹕ Failed to load: Status{statusCode=SIGN_IN_REQUIRED, resolution=null}
It is strange that you are getting such status code at that time. What comes to mind is that the user may have not logged into his/her gmail account or something along those lines. Do you have the log file for us to take a look at to see if we can get more from the context? Also, to be sure, such user sees the application launched on the TV and only when it comes to loading a media that error is thrown?
The issue is due to using a Self Signed Certificate. I didn't realize the issue on my old phone because I had changed hosts and bought a normal certificate after switching phones. It would be nice if the SDK would through a useful error though. The one thrown makes you think that it is a problem with connecting to the Play Services SDK, and not a problem with the actual URL being used.
I have trouble using thread.join in my code below. It should wait for the thread to finish before executing the codes after it, right? It was behaving differently on different occasions.
I have three cases to check if my code goes well
App is used for the first time - works as expected but the loading page don't appear while downloading
App is used the second time (db is up to date) - works okay
App is used the third time (db is outdated, must update) - won't update, screen blacks out, then crashes
I think I have problems with this code on onCreate method:
dropOldSchedule();
dropThread.join();
triggerDownload();
Based on the logs, the code works until before this part... What can be the problem?
MainActivity.java
public class MainActivity extends Activity {
final static int INDEX_ACCTTYPE = 0;
final static int INDEX_ECN = 1;
final static int INDEX_TLN = 2;
final static int INDEX_SIN = 3;
final static int INDEX_MOBILE = 4;
final static int INDEX_CITY = 5;
final static int INDEX_START_DATE = 6;
final static int INDEX_START_TIME = 7;
final static int INDEX_END_DATE = 8;
final static int INDEX_END_TIME = 9;
final static int INDEX_REASON = 10;
final static int INDEX_DETAILS = 11;
DatabaseHandler db;
String str;
ProgressDialog pd;
TextView homeText1, homeText2, homeText3, homeText4;
final private String csvFile = "http://www.meralco.com.ph/pdf/pms/pms_test.csv";
final private String uploadDateFile = "http://www.meralco.com.ph/pdf/pms/UploadDate_test.txt";
Thread dropThread = new Thread(new Runnable() {
public void run() {
db = new DatabaseHandler(MainActivity.this);
db.dropOldSchedule();
runOnUiThread(new Runnable() {
public void run() {
while (!pd.isShowing());
db.close();
pd.dismiss();
}
});
}
});
Thread getUploadDateThread = new Thread(new Runnable() {
public void run() {
try {
URL myURL = new URL(uploadDateFile);
BufferedReader so = new BufferedReader(new InputStreamReader(myURL.openStream()));
while (true) {
String output = so.readLine();
if (output != null) {
str = output;
}
else {
break;
}
}
so.close();
}
catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
while (!pd.isShowing());
pd.dismiss();
}
});
}
});
Thread downloadThread = new Thread(new Runnable() {
public void run() {
db = new DatabaseHandler(MainActivity.this);
db.beginTransaction();
try {
URL url = new URL(csvFile);
Log.i("dl", "start");
InputStream input = url.openStream();
CSVReader reader = new CSVReader(new InputStreamReader(input));
Log.i("dl", "after reading");
String [] sched;
while ((sched = reader.readNext()) != null) {
if(sched[INDEX_CITY].equals("")) sched[INDEX_CITY]="OTHERS";
try {
db.addRow(sched[INDEX_SIN], sched[INDEX_CITY],
sched[INDEX_START_DATE], sched[INDEX_START_TIME],
sched[INDEX_END_DATE], sched[INDEX_END_TIME],
sched[INDEX_DETAILS], sched[INDEX_REASON]);
} catch (IndexOutOfBoundsException e) {
db.addRow(sched[INDEX_SIN], sched[INDEX_CITY],
sched[INDEX_START_DATE], sched[INDEX_START_TIME],
sched[INDEX_END_DATE], sched[INDEX_END_TIME],
"", sched[INDEX_REASON]);
//e.printStackTrace();
}
}
input.close();
Log.i("dl", "finished");
} catch (MalformedURLException e) {
e.printStackTrace();
db.endTransaction();
} catch (IOException e) {
e.printStackTrace();
db.endTransaction();
}
Log.d("Count", ""+db.count());
db.setTransactionSuccessful();
db.endTransaction();
writeUploadDateInTextFile();
}
});
#SuppressWarnings("unqualified-field-access")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pms_main);
Button home = (Button) findViewById(R.id.home);
home.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, MeralcoSuite_TabletActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
}
});
homeText1 = (TextView) findViewById(R.id.home_text1);
homeText2 = (TextView) findViewById(R.id.home_text2);
homeText3 = (TextView) findViewById(R.id.home_text3);
homeText4 = (TextView) findViewById(R.id.home_text4);
homeText1.setVisibility(View.INVISIBLE);
homeText2.setVisibility(View.INVISIBLE);
homeText3.setVisibility(View.INVISIBLE);
homeText4.setVisibility(View.INVISIBLE);
getUploadDate();
try {
getUploadDateThread.join(); //wait for upload date
Log.d("getUploadDate","thread died, upload date=" + str);
if(dbExists()){
db = new DatabaseHandler(MainActivity.this);
Log.d("Count", "" + db.count());
db.close();
if(!uploadDateEqualsDateInFile()){
dropOldSchedule();
dropThread.join();
triggerDownload();
}
showDisclaimer();
Log.i("oncreate", "finished!");
return;
}
triggerDownload();
showDisclaimer();
Log.i("oncreate", "finished!");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void dropOldSchedule(){
if(pd!=null && pd.isShowing())
pd.setTitle("Getting upload date...");
else
pd = ProgressDialog.show(this, "Getting upload date",
"This may take a few minutes...", true, false);
dropThread.start();
}
public void triggerDownload() {
if (!checkInternet()) {
showAlert("An internet connection is required to perform an update, please check that you are connected to the internet");
return;
}
if(pd!=null && pd.isShowing())
pd.setTitle("Getting upload date...");
else
pd = ProgressDialog.show(this, "Getting upload date",
"This may take a few minutes...", true, false);
downloadThread.start();
}
public void getUploadDate() {
Log.d("getUploadDate", "getting upload date of schedule");
if(pd!=null && pd.isShowing())
pd.setTitle("Getting upload date...");
else
pd = ProgressDialog.show(this, "Getting upload date",
"This may take a few minutes...", true, false);
getUploadDateThread.start();
}
public void writeUploadDateInTextFile() {
Log.d("writeUploadDateTextFile", "writing:"+str);
try {
OutputStreamWriter out = new OutputStreamWriter(openFileOutput(
"update.txt", 0));
out.write(str);
out.close();
} catch (java.io.IOException e) {
e.printStackTrace();
}
}
public void showDisclaimer() {
Log.d("ShowDisclaimer", "showing disclaimer");
homeText3
.setText("..." + str
+ "...");
homeText1.setVisibility(View.VISIBLE);
homeText2.setVisibility(View.VISIBLE);
homeText3.setVisibility(View.VISIBLE);
homeText4.setVisibility(View.VISIBLE);
Log.d("showDisclaimer", "finished showing disclaimer");
}
public boolean uploadDateEqualsDateInFile() {
Log.d("uploadDateEqualsDateInFile","comparing schedule upload dates");
try {
String recordedDate = "";
InputStream instream = openFileInput("update.txt");
if (instream != null) { // if file the available for reading
Log.d("uploadDateEqualsDateInFile","update.txt found!");
InputStreamReader inputreader = new InputStreamReader(instream);
BufferedReader buffreader = new BufferedReader(inputreader);
String line = null;
while ((line = buffreader.readLine()) != null) {
recordedDate = line;
Log.d("uploadDateEqualsDateInFile","recorded:"+recordedDate);
}
Log.d("uploadDateEqualsDateInFile","last upload date: " + str + ", recorded:" +recordedDate);
if(str.equals(recordedDate)) return true;
return false;
}
Log.d("uploadDateEqualsDateInFile","update.txt is null!");
return false;
} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
public boolean checkInternet() {
ConnectivityManager cm = (ConnectivityManager) this
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo infos[] = cm.getAllNetworkInfo();
for (NetworkInfo info : infos)
if (info.getState() == NetworkInfo.State.CONNECTED
|| info.getState() == NetworkInfo.State.CONNECTING) {
return true;
}
return false;
}
public boolean dbExists() {
File database=getApplicationContext().getDatabasePath(DatabaseHandler.DATABASE_NAME);
if (!database.exists()) {
Log.i("Database", "Not Found");
return false;
}
Log.i("Database", "Found");
return true;
}
#Override
protected void onDestroy() {
super.onDestroy();
if (db != null) {
db.close();
}
}
#Override
protected void onPause() {
super.onPause();
if (db != null) {
db.close();
}
}
}
Sorry but I couldn't find mistakes or problems in your code. But I would strongly recommend you to use AsyncTask for doing something in different thread. AsyncTask is very easy to use and I would say that it is one of the biggest advantages of java. I really miss it in obj-c.
http://labs.makemachine.net/2010/05/android-asynctask-example/
http://marakana.com/s/video_tutorial_android_application_development_asynctask_preferences_and_options_menu,257/index.html
check those links hope that will help you.
It was already mentioned that AsyncTask is the better alternative. However, it may be the case, that your call to join will throw InterruptedException. Try to use it like this:
while(getUploadDateThread.isRunning()){
try{
getUploadDateThread.join();
} catch (InterruptedException ie){}
}
// code after join
I think the problem that your facing is that you are blocking the UI thread when you call join in the onCreate() method. You should move this code into another thread which should execute in the background and once its done you can update the UI.
Here is a sample code:
final Thread t1 = new Thread();
final Thread t2 = new Thread();
t1.start();
t2.start();
new Thread(new Runnable() {
#Override
public void run() {
// Perform all your thread joins here.
try {
t1.join();
t2.join();
} catch (Exception e) {
// TODO: handle exception
}
// This thread wont move forward unless all your threads
// mentioned above are executed or timed out.
// ------ Update UI using this method
runOnUiThread(new Runnable() {
#Override
public void run() {
// Update UI code goes here
}
});
}
}).start();