My realtime-database has data persistence for offline use and recently a recording error recorded a String as HashMap and consequently the application crashed for all my clients. I quickly corrected the error, but now all clients can no longer open the application, as it loads offline before online and ends up slowing down the error and closing the application for all users, or a good part of them.
I'm instructing them to do data wiping manually, but this is a big problem for me and I need to find a way to force this data wiping of all users remotely or predict in the application that when there are some crashes it will clear the local data automatically.
Any code suggestions or how can I do this?
I solve this problem with an try/catch, like code below:
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
try {
User user = dataSnapshot.getValue(User.class); // error occurs here
//... some code ...//
} catch (DatabaseException databaseException) {
Log.e(TAG, "DatabaseException ****** The read failed: " + databaseException);
clearPreferences(context.getApplicationContext());
deleteCache(context.getApplicationContext());
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) { Log.e(TAG, "onCancelled ****** The read failed: " + databaseError); }
public static void clearPreferences(Context context) {
try {
// clearing app data
Runtime runtime = Runtime.getRuntime();
runtime.exec("pm clear "+context.getPackageName());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void deleteCache(Context context) {
try {
File dir = context.getCacheDir();
deleteDir(dir);
} catch (Exception ignored) {}
}
Related
I'm having a hard time passing files with spaces in their names into Twilio chat.
Forgetting about the fact that I'm using Twilio, and just concentrating that I'm trying to upload a file from within the Android phone. I have an image on my android phone which I found its path as /Internal storage/Download/4893079.jpg
Below is the full code:
public void testing() {
Messages messagesObject = channel.getMessages();
try {
messagesObject.sendMessage(
Message.options()
.withMedia(new FileInputStream("/Internal%20storage/Download/4893079.jpg"), "image/jpeg")
.withMediaFileName("4893079.jpg")
.withMediaProgressListener(new ProgressListener() {
#Override
public void onStarted() {
System.out.println("Upload started");
}
#Override
public void onProgress(long bytes) {
System.out.println("Uploaded " + bytes + " bytes");
}
#Override
public void onCompleted(String mediaSid) {
System.out.println("Upload completed");
}
}),
new CallbackListener<Message>() {
#Override
public void onSuccess(Message msg) {
System.out.println("Successfully sent MEDIA message");
}
#Override
public void onError(ErrorInfo error) {
System.out.println("Error sending MEDIA message");
}
});
} catch (FileNotFoundException e) {
System.out.println("FAILED HORRIBLY");
System.out.println(e);
e.printStackTrace();
}
}
However running the app I end up with the error,
java.io.FileNotFoundException: /Internal%20storage/Download/4893079.jpg (No such file or directory)
As shown I've tried replacing space with %20, but that didn't work. I've also tried \ , \\ . However non of them worked. I've looked at Opening a local Android File with spaces, Save file in Android with spaces in file name.
How should I be replacing the space?
You need to get the actual path programmatically. So the real path is
Environment.getExternalStorageDirectory().toString() + "/Download/4893079.jpg"
Internal storage is just something the user sees, but not a real path on the machine.
I'm using FFmpeg in one of my projects for video compression. On Android 10 (Google Pixel 3a), it goes straight to onFailure(String message) with empty message for any command sent for execution.
so I have (api 'com.writingminds:FFmpegAndroid:0.3.2') specified in my app gradle file,
permission (android.permission.WRITE_EXTERNAL_STORAGE) in the manifest is specified
So I do:
InitializationCallback initializationCallback = new InitializationCallback();
try {
FFmpeg.getInstance(context).loadBinary(initializationCallback);
} catch (FFmpegNotSupportedException e) {
initializationCallback.onFailure();
initializationCallback.onFinish();
}
Initializes just fine, no problems here.
Later:
void getData(File inputFile) {
//inputFile points to: /storage/emulated/0/Android/data/{package_name}/files/temp_files/temp_1.mp4
String[] cmd = ("-i " + inputFile.getAbsolutePath()).split(" ");
try {
FFmpeg.getInstance(App.instance).execute(cmd, this);
} catch (FFmpegCommandAlreadyRunningException e) {
throw new Error(e);
}
}
#Override
public void onStart() {
//This method is called
}
#Override
public void onSuccess(String message) {
//This method is NOT called
extractAvailableData(message);
}
#Override
public void onProgress(String message) {
//This method is NOT called
extractAvailableData(message);
}
#Override
public void onFailure(String message) {
//This method is called and the message is empty
extractAvailableData(message);
}
#Override
public void onFinish() {
//This method is called
}
If I do something like:
String command = "-i ***/file1.mp4 -map 0:v -map 0:a -preset ultrafast -s:v 750:350 ***/file2.mp4";
//file2.mp4 is a non existent file at this point
// (***) --> is just a replacement for the full path of the file, just to keep things shorter here.
String[] cmd = command.split(" ");
try {
FFmpeg.getInstance(App.instance).execute(cmd, this);
} catch (FFmpegCommandAlreadyRunningException e) {
throw new Error(e);
}
gives the same result, no video conversion, just a call to onFailure("Nothing")
Even if I do:
String[] cmd = {"-version"};
try {
FFmpeg.getInstance(App.instance).execute(cmd, this);
} catch (FFmpegCommandAlreadyRunningException e) {
throw new Error(e);
}
I get nothing, no output at all.
I encountered this issue only on Android 10 so far, it works fine on other devices.
Android 10 had behavioral changes where execute permission for app home directory was removed. You will get a permission denied exception if you try and run the execution file from App home directory.
Here are the details on the changes for target SDK version 29 : https://developer.android.com/about/versions/10/behavior-changes-10#execute-permission
java.io.IOException: Cannot run program "/data/user/0/<package name>/files/ffmpeg": error=13, Permission denied
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1050)
at nl.bravobit.ffmpeg.ShellCommand.run(ShellCommand.java:15)
at nl.bravobit.ffmpeg.FFcommandExecuteAsyncTask.doInBackground(FFcommandExecuteAsyncTask.java:43)
at nl.bravobit.ffmpeg.FFcommandExecuteAsyncTask.doInBackground(FFcommandExecuteAsyncTask.java:12)
at android.os.AsyncTask$3.call(AsyncTask.java:378)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
Caused by: java.io.IOException: error=13, Permission denied
at java.lang.UNIXProcess.forkAndExec(Native Method)
at java.lang.UNIXProcess.<init>(UNIXProcess.java:133)
at java.lang.ProcessImpl.start(ProcessImpl.java:141)
I don't know if it'd be your case, but in my case the problem was that I didn't call ffmpeg.loadBinary before using it.
It seems a bit counter intuitive, because it actually work with my testing device without doing that. I have some ideas on why, but no time to test these. The important thing is that it's working now. Here an example of what I had to implement:
FFmpeg ffmpeg = FFmpeg.getInstance(context);
ffmpeg.loadBinary(new FFmpegLoadBinaryResponseHandler() {
#Override
public void onFailure() {
// Report failure to logcat,show the user a dialog, throw an exception or whatever you want to do in case of failure
}
#Override
public void onSuccess() {
// Execute the real ffmpeg stuff here
}
#Override
public void onStart() {
}
#Override
public void onFinish() {
}
});
In a real world scenario, if you plan to use it several times, you may use a flag to make sure it's not been loaded already and avoid trying to reload it in such case.
I'm trying to connect to another database on an Android App, and can't seem to see if I've successfully init the secondary database.
How I'm instantiating the second one.
public void initFirebase() {
//init the default db;
FirebaseApp.initializeApp(this);
//init the second db;
FirebaseOptions.Builder builder = new FirebaseOptions.Builder();
builder.setApplicationId("id");
builder.setApiKey("key");
builder.setDatabaseUrl("https://second-db.firebaseio.com");
try {
FirebaseApp.initializeApp(this, builder.build(), "second-db");
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
Then I try to read something here.
public static DatabaseReference getSecondDbRef(String child) {
FirebaseApp app = FirebaseApp.getInstance("second-db");
return FirebaseDatabase.getInstance(app).getReference(child);
}
Then this fails with some: Listen at /child/child/child/teams failed: DatabaseError: Permission denied, though I've allowed access at this location and can confirm with the rules simulator that this node can be read.
Is there a way to have this log: Listen to second-db/child/child/child/teams failed ..., notice the prefix second-db.
I'm trying to upload an image, saved in the internal memory of my phone, clicked by an android app to a cloud service, and am using Kinvey to do so. But I'm facing some problems with it.
Every time I run the code that contains the upload part, I encounter an exception. I'm uploading an image of ".png" type. Any conversion to blob is not a necessary process that is required, unlike that in Google Cloud Platform.
Here is my .java code -
`Client mKinveyClient = new Client.Builder(APP_KEY, SECRET_KEY, this.getApplicationContext()).build();
mKinveyClient.enableDebugLogging();
mKinveyClient.ping(new KinveyPingCallback() {
public void onFailure(Throwable t) {
Log.e(TAG, "Kinvey Ping Failed", t);
}
public void onSuccess(Boolean b) {
Log.d(TAG, "Kinvey Ping Success");
}
});
java.io.File file = new java.io.File(Environment.getExternalStorageDirectory().getPath() + "/Camera/" + "IMG_20161115_193353.jpg");
mKinveyClient.file().upload(file, new UploaderProgressListener() {
public void onSuccess(Void result) {
Log.i(TAG, "successfully upload file");
}
#Override
public void onSuccess(FileMetaData fileMetaData) {
Log.i(TAG, "successfully uploaded file");
}
#Override
public void onFailure(Throwable error) {
Log.e(TAG, "failed to upload file.", error);
}
#Override
public void progressChanged(MediaHttpUploader uploader) throws IOException {
Log.i(TAG, "upload progress: " + uploader.getUploadState()); // all updates to UI widgets need to be done on the UI thread
}
});`
Now, although the ping call is giving me a successful response, the upload part is giving me an error.
E/Activity file: failed to upload file.
com.kinvey.java.KinveyException:
REASON: No user is currently logged in.
I've searched a lot on this topic, on kinvey's discussion platform and here too. But I'm still stuck. I don't know where I'm going wrong or what I might be missing.
If anyone is out there who has successfully managed to upload images through kinvey then please help me out.
Any kind of Kinvey operations must be provided via a logged user.
You must sign up (or login) before you start to i/o any information.
mKinveyClient.user().create("username", "password", new KinveyUserCallback()) {
#Override
public void onFailure(Throwable t) {
CharSequence text = "Could not sign up.";
Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
}
#Override
public void onSuccess(User u) {
//here we go on uploading file
}
});
You can find more info about users here
Sharmistha,
Yes, every app action needs an active user context.
So you will need to login in the app and then upload the file.
Please take a look at the following:
http://devcenter.kinvey.com/android/guides/users#ActiveUser
http://devcenter.kinvey.com/android/guides/files#Uploading
Thanks,
Pranav
Kinvey
I've been running into a problem using the AWS Mobile SDK version 2.2.15. After carefully looking at their own S3TransferUtilitySample, I have made a couple attempts to get a file uploaded to an Amazon S3 bucket on my own.
My first attempt was to try calling the TransferUtility's .upload() method from within Android's own AsyncTask, inside the doInBackground() method. No success there, and after reading about this issue, it inspired me to try moving the SDK calls outside of the AsyncTask and into the UI thread under onPostExecute() in suspicion that the call itself is asynchronous and the AsyncTask is running garbage collection on the AWS SDK objects. Still no luck, no exceptions are being thrown, and no indication of anything going wrong aside from the file not actually uploading.
My second attempt was following this exact example. I downloaded the source and was able to supply the application with the correct identity pool ID, region, bucket, key, and a test jpeg file. I ran the application and the calls were being made. The file made it to AWS S3 without any issues.
I copied their exact methods into a helper class of my application, and made all the AWS SDK objects a static field of the class, but I am still running into the same issue of no exceptions being thrown. I ended up making the fields non-static and instantiating the helper class as an object in my main activity, safely assuming that the object would not be treated with garbage collection. Still nothing! No indication of failure from these calls!
I decided to get really generous with logging using Android's Log.i() method, watching every step of the way, and it even makes it to the TransferUtility's .upload() method, but even having the TransferListener set and full of logging lines, there is no status change, onError() is not being called. TransferUtility's .upload() and its resulting TransferObserver object is not reporting anything like it was running the test application.
Here are a couple things to note:
* The correct identity pool ID is being used here, no issue with that
* I have tried using both version 2.2.15 as well as 2.2.13
* All dependencies included are .jar files, the project is not Gradle (yet)
* The service is declared in the manifest just as it was in the examples
* There are no build errors, Android Studio builds the project just fine
* The TransferListener object is not firing onStateChanged(), onProgressChanged(), nor onError()
Has anyone encountered such a strange issue with AWS S3 SDK? Any suggestions on how I can better debug this issue?
Here's the class right now:
public class AmazonS3Helper
{
Context context;
public String bucket;
public String key;
public File file;
public AmazonS3 s3;
public TransferUtility utility;
public AmazonS3Helper(JSONObject p, Context c)
{
Log.i("tag", "new AmazonS3Helper object");
this.context = c;
try
{
bucket = p.getString("bucket");
key = p.getString("key");
this.file = new File(
c.getExternalFilesDir(null),
"nn_temp_photo.jpg");
credentialsProvider();
setTransferUtility();
upload();
}
catch (Exception x)
{
Log.i("tag", "Error in new AmazonS3Helper object: " + x.getMessage());
}
}
public void credentialsProvider()
{
Log.i("tag", "Providing credentials");
try
{
CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(
this.context,
// This has been verified to return the correct identity pool
MyApplicationClass.getPreference("aws.credentials"),
Regions.US_EAST_1);
setAmazonS3Client(credentialsProvider);
}
catch (Exception x)
{
Log.i("tag", "Error in providing credentials: " + x.getMessage());
}
}
public void setAmazonS3Client(CognitoCachingCredentialsProvider credentialsProvider)
{
Log.i("tag", "Setting amazon s3 client");
try
{
s3 = new AmazonS3Client(credentialsProvider);
s3.setRegion(Region.getRegion(Regions.US_EAST_1));
}
catch (Exception x)
{
Log.i("tag", "Error in setting amazon s3 client:" + x.getMessage());
}
}
public void setTransferUtility()
{
Log.i("tag", "Setting transfer utility");
try
{
utility =
new TransferUtility(
s3,
this.context);
}
catch (Exception x)
{
Log.i("tag", "Error in setting transfer utility: " + x.getMessage());
}
}
public void upload()
{
Log.i("tag", "uploading");
try
{
TransferObserver transferObserver = utility.upload(
bucket,
key,
file
);
transferObserverListener(transferObserver);
}
catch (Exception x)
{
Log.i("tag", "Error in uploading: " + x.getMessage());
}
}
public void transferObserverListener(TransferObserver transferObserver)
{
Log.i("tag", "transferObserverListener");
try
{
transferObserver.setTransferListener(new TransferListener()
{
#Override
public void onStateChanged(int id, TransferState state)
{
Log.i("tag", state + "");
}
#Override
public void onProgressChanged(int id, long bytesCurrent, long bytesTotal)
{
int percentage = (int) (bytesCurrent / bytesTotal * 100);
Log.i("tag", percentage + "");
}
#Override
public void onError(int id, Exception ex)
{
Log.i("tag", "error");
}
});
}
catch (Exception x)
{
Log.i("tag", "Error in transferObserverListener: " + x.getMessage());
}
}
}
Edit
I forgot to mention, but the version of Android this is being tested on is Android Lollipop 5.1.
This is a bug in 2.2.15. Some IO exceptions aren't reported. It is fixed in 2.2.16. Would you please try the latest version?
The issue has been solved and is entirely unrelated to the code itself. What was happening was that I was declaring the com.amazonaws.mobileconnectors.s3.transferutility.TransferService in the library's manifest, but the child apps also needed it in their manifest.
I found this out by dropping the sample Activity straight into my application, and realizing the child apps also needed this activity declaration. The child apps have no code themselves, but without the declaration in their own manifest, they are unaware the activities/services being referenced exist. In this case, Amazon was silently refusing to upload because the service wasn't declared for the specific application.