Sorry for the long question, I have been stuck on this for a month, and I want to provide as much detail as possible...its just a file not found exception in a simple library... :)
I am getting a file not found exception on my variances file:
I do, however, have the variances file:
I am trying to simply implement voice recognition in my background service, so that I can detect when the user says the word hello (using pocketsphinx).
The problem happens in this method: createSphinxDir();
Here is my service:
#Override
public void onCreate() {
super.onCreate();
setupRecog();
}
private void setupRecog() {
String sphinxDir = createSphinxDir();
Log.v(TAG, "ABOUT TO CREATE SETUP");
if (sphinxDir != null) {
try {
Log.v(TAG, "SETTING UP! :)");
mSpeechRecognizer = defaultSetup()
.setAcousticModel(new File(sphinxDir, "en-us-ptm"))
.setDictionary(new File(sphinxDir, "hello.dict"))
.setBoolean("-allphone_ci", true) //WHAT IS THIS
.getRecognizer();
mSpeechRecognizer.addListener(this);
Log.v(TAG, "ADDED LISTENER");
if ((new File(sphinxDir + File.separator + "command.gram")).isFile()) {
mSpeechRecognizer.addKeywordSearch("hello",
new File(sphinxDir + File.separator + "command.gram"));
Log.v(TAG, "ADDED KEYWORD SEARCH! :)");
}
// Or wherever appropriate
mSpeechRecognizer.startListening("wakeup"); //Is this correct?
Log.v(TAG, "STARTED LISTENING");
} catch (IOException e) {
Log.v("ERROR", TAG);
}
}
}
String createSphinxDir() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
String sphinxDir = prefs.getString("sphinx", null);
if (sphinxDir == null) {
Assets assets;
Log.v(TAG, "Assets are not synced, should sync now:");
try {
Log.v(TAG, "In try block!");
assets = new Assets(this);
File sphinxDirFile = assets.syncAssets();
Log.v(TAG, "Syncing assets...should set up listener");
if (sphinxDirFile != null) {
sphinxDir = sphinxDirFile.getAbsolutePath();
SharedPreferences.Editor editor = prefs.edit();
editor.putString("sphinx", sphinxDir);
editor.commit();
Log.v(TAG, "Set up listener");
}else{
Log.v(TAG, "sphinxDirFile is null!");
}
} catch (IOException e) { //THIS IS THE PLACE WHERE I AM GETTING THE ERROR!
e.printStackTrace();
Log.d(TAG, e.toString());
}
}
return sphinxDir;
}
I also have all the call back methods (onPartialResult, onResult, etc.) but they never get called.
Earlier I was getting an exception saying the variances .md5 file didn't exist, so I put a space in between the variances and the .md5, but now I am getting this error, and I don't know why...
Please let me know,
Ruchir
Earlier I was getting an exception saying the variances .md5 file didn't exist, so I put a space in between the variances and the .md5, but now I am getting this error, and I don't know why...
You should not do such things, it causes problems, instead you need to follow the documentation:
The standard way to ship resource files with your application in Android is to put them in assets/ directory of your project. But in order to make them available for pocketsphinx files should have physical path, as long as they are within .apk they don't have one. Assets class from pocketsphinx-android provides a method to automatically copy asset files to external storage of the target device. edu.cmu.pocketsphinx.Assets#syncAssets synchronizes resources reading items from assets.lst file located on the top assets/. Before copying it matches MD5 checksums of an asset and a file on external storage with the same name if such exists. It only does actualy copying if there is incomplete information (no file on external storage, no any of two .md5 files) or there is hash mismatch. PocketSphinxAndroidDemo contains ant script that generates assets.lst as well as .md5 files, look for assets.xml.
Please note that if ant build script doesn't run properly in your build process, assets might be out of sync. Make sure that script runs during the build.
To integrate assets sync in your application do the following
Include app/asset.xml build file from the demo application into your application. Edit build.gradle build file to run assets.xml:
ant.importBuild 'assets.xml'
preBuild.dependsOn(list, checksum)
clean.dependsOn(clean_assets)
Related
I have been working on getting my database backing up to work and I have reached a point where I am not sure what to do.
Basically at first the application opens a Login activity, the user logs in and their database file (if it exists) is downloaded from the Firebase Storage, and then the application navigates to the MainActivity.
In the MainActivity I call a method that sends the user's database file to Firebase Storage. I tried to manage the process by closing the database but since i couldn't fix an error of "E/ROOM: Invalidation tracker is initialized twice :/.", then I found an answer to use a checkpoint (Backup Room database). Now I implemented the forced checkpoint method.
(MarkerDao)
#RawQuery
int checkpoint(SupportSQLiteQuery supportSQLiteQuery);
(MarkerRepository)
public void checkPoint(){
Thread thread= new Thread(() -> markerDao.checkpoint(new SimpleSQLiteQuery("pragma wal_checkpoint(full)")));
thread.start();
}
(ViewModel)
public void setCheckpoint(){
repository.checkPoint();
}
(Database back-up method in the MainActivity)
private void copyDbToFirebase(){
String currentDBPath = "/data/data/"+ getPackageName() + "/databases/locations_table";
File dbBackupFile = new File(currentDBPath);
if (dbBackupFile.exists()){
markerViewModel.setCheckpoint();
// create file from the database path and convert it to a URI
Uri backupDB = Uri.fromFile(new File(currentDBPath));
// Create a StorageReference
StorageReference dbReference = storageRef.child("users").child(userId).child("user database").child("locations_table");
// Use the StorageReference to upload the file
if (userId != null){
dbReference.putFile(backupDB).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Log.d(TAG, "onSuccess: "+4 + taskSnapshot);
Toast.makeText(getApplicationContext(), "Database copied to Firebase 4", Toast.LENGTH_LONG).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d(TAG, "onFailure: "+ e.getMessage());
}
});
}
}
}
If the user logs out, then the files in the "/data/data/"+ getPackageName() + "/databases/" are deleted, which I have manually confirmed by looking at the databases folder of the application.
My issue is that after the databases are deleted and a new user logs in, then the previous database data remains but when I manually check the app's data folder, then the /databases/ folder shows that the files were deleted and a new file is created but it doesn't show any WAL or SHM files and also I get the data of another database which is created when the application first runs, but that file is also not shown in the databases/ folder.
Can anyone explain why the folder doesn't show the files that should be present, where is the application getting the data that was deleted and how to fix it.
Edit: My application has multiple Room databases and I just realized that all the data is still readable after the files were deleted.
The method to delete the database files
private boolean deleteDatabaseFiles(File path) {
if(path.exists() ) {
File[] files = path.listFiles();
for(int i=0; i<files.length; i++) {
if(files[i].isDirectory()) {
deleteDatabaseFiles(files[i]);
}
else {
files[i].delete();
}
}
}
return true;
}
If you are using the same exact RoomDatabase object simply building another one over the same object will prevent any hold over cached data from showing up. I've tested this using multiple database swaps large and small and there is no bleed over.
If you are using a new Instance of the RoomDatabase object for every login try closing the old one after the user logs out. Room will typically close when not needed but if you need it to happen immediately, manually closing it is your best bet.
roomDb.getOpenHelper().close();
I have released App "A". Now I prepare to release App "B" that should load copy database from App "A" to enable users continue writing data.
This code from App "A" save db from internal storage to a file on scoped storage:
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DISPLAY_NAME, "/databasename.db");
values.put(MediaStore.MediaColumns.MIME_TYPE, "application/vnd.sqlite3");
values.put(MediaStore.MediaColumns.RELATIVE_PATH, DIRECTORY_DOWNLOADS);
Uri uri = getContentResolver().insert(MediaStore.Files.getContentUri("external"), values);
if (uri != null) {
OutputStream outputStream = getContentResolver().openOutputStream(uri);
if (outputStream != null) {
outputStream.write("This is menu category data.".getBytes());
outputStream.close();
Toast.makeText(ActivitySettings.this, "File created successfully", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(ActivitySettings.this, "outputStream == null", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(ActivitySettings.this, "uri == null", Toast.LENGTH_SHORT).show();
}
} catch (IOException e) {
Toast.makeText(ActivitySettings.this, "Fail to create file", Toast.LENGTH_SHORT).show();
}
This code from App "B" should upload database file that was saved in App "A":
try {
File sd = Environment.getDataDirectory();
File data = Environment.getStorageDirectory();
try {
String currentDBPath = "emulated/0/" + DIRECTORY_DOWNLOADS + "/databasename.db";
String backupDBPath = "/data/com.example.mypackagename/databases/databasename.db";
File currentDB = new File(data, currentDBPath);
File backupDB = new File(sd, backupDBPath);
if (currentDB.exists()) {
FileChannel src = new FileInputStream(currentDB).getChannel();
FileChannel dst = new FileOutputStream(backupDB).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
Toast.makeText(this, R.string.toast_db_loaded_succesfully, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, R.string.toast_db_not_exists, Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
Toast.makeText(this, R.string.toast_not_access, Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
Log.e("DBError", "exception", e);
Toast.makeText(this, R.string.toast_error_load_db, Toast.LENGTH_LONG).show();
}
It's working as well on Android 10 and below but it's not possible due to new access rules of scoped storage Android 11. With MANAGE_EXTERNAL_STORAGE permission it's possible but in my case Google may reject App "B" due to a policy violation.
SharedUserId is deprecated
Sharing files via FileProvider carried out by Activity with UI and additional user's operations.
But I need way without any additional operations, just load database with one click from App "B". It's possible on Android 11? Maybe there is an alternative to SharedUserId?
Any help/thoughts.
Thanks.
The new security requirements are a welcome change from a security standpoint.
The best solution is to send an upgrade to the existing app A to send the data an external endpoint accessible by app B.
Having App A modify App B data without app B's permission IS a violation of security protocols and should NEVER be allowed.
Unless you are the owner of both app A and app B, what you are asking is impossible and should never be allowed to happen.
I am trying to create a folder and subfolder namely "CJI/Export" in "Internal Memory" using the following code. To ensure that the command is successfully executed, I have added Toast Messages in all states.
I tried running the code on two devices: "Redmi Note 3" & "Honor 9i".
In Redmi Note-3, I am getting the results as expected. The command is creating the folder & subfolder successfully.
But in Honor 9i, I also shows the toast message "Export Folder created successfully", but I can't see any such folder or sub-folder in the device manager (internal memory). Also, on closing the app and launching it again, I get the same toast message "Export Folder created successfully".
package com.example.app.activities;
public class HomeScreenActivity extends AppCompatActivity implements{
private String dirPathExport;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_screen);
dirPathExport= createMediaDirExport(HomeScreenActivity.this);
}
public static String createMediaDirExport(Context context) {
String dirPath="";
try {
dirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/CJI/Export";
File dir_temp = new File(dirPath);
if (!dir_temp.exists()) {
dir_temp.mkdirs();
Toast.makeText(context, "Export Folder created successfully", Toast.LENGTH_SHORT).show();
}
Toast.makeText(context, "Export Folder already present", Toast.LENGTH_SHORT).show();
}
catch (Exception e) {
e.printStackTrace();
Toast.makeText(context, "Error during folder creation", Toast.LENGTH_SHORT).show();
}
return dirPath;
}
}
Expected Result is to get the folder in Internal Memory in Honor 9i
go to App Info-> Permissions of your application and enable Storage permission.
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.
in my Android app I am using the system Download Manager to download a photo, once recieved I process it and then I need to move it to another location. if I just copy it it works fine, if I try to move it/delete it I get an exception about it can't be moved.
Failed to delete original file '/data/user/0/com.android.providers.downloads/cache/a3133p2930-9.jpg' after copy to '/data/data/com.XXXXX.testharness/app_appdata/images/one/two/three/6/a3133p2930.jpg'
also tried:
1) remove it from download manager before trying to move it
2) set the destination directly to the target dir, but got an error I can only use public external folders.
3) tried using JAVA renameTo and Apache commons moveFile
this is a code snippet that show the relevant parts of what I am doing.
any ideas?
appreciated
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
String uriString = c.getString(
c.getColumnIndex(
DownloadManager.COLUMN_LOCAL_URI));
String uri2String = c.getString(
c.getColumnIndex(
DownloadManager.COLUMN_URI));
String localFileString = c.getString(
c.getColumnIndex(
DownloadManager.COLUMN_LOCAL_FILENAME));
File from = new File(localFileString);
File to = new File(appDataDir, localString);
File to2 = new File (appDataDir, localString + "/" + getFileNameFromUrl(uri2String));
if (!to.exists()) {
if (to.mkdirs()) {
Log.d(LCAT, "Directory Created");
}
}
dm.remove(downloadId);
//boolean a = from.renameTo(to2);
try {
FileUtils.copyFile(from, to2);
} catch (Exception e) {
Log.d(LCAT, "rename success? " + e.getMessage());
}
i think you can not delete the cache of downloadmanager, i think it clears itself automatically after you removed the downloadid from its database but if you like to have a control to your file you can set destination folder to your private external storage and then after download completed delete it.
File rootDirectory = new File(getActivity().getExternalFilesDir(null).getAbsoluteFile().toString());
if(!rootDirectory.exists()){
rootDirectory.mkdirs();
}
req.setDestinationInExternalFilesDir(getActivity(),null ,"/" + fileName);
and after your download completed you can delete it like:
from.delete();
and the doc says:
public int remove (long... ids)
Cancel downloads and remove them from
the download manager. Each download will be stopped if it was running,
and it will no longer be accessible through the download manager. If
there is a downloaded file, partial or complete, it is deleted.
http://developer.android.com/reference/android/app/DownloadManager.html#remove%28long...%29