Our team is creating a chatbot application this week. We finished coding the AIML files as well as the main codes in Android Studio. The only problem we have right now is the link between these two.
I've already placed the Ab.jar in the libs folder. Also, I've placed the AIML files in the assets folder.
Assets folder
The codes I think are relevant to linking are the following (from ChatActivity.class):
//checking SD card availability
boolean a = isSDCARDAvailable();
//receiving the assets from the app directory
AssetManager assets = getResources().getAssets();
File seedletDir = new File(Environment.getExternalStorageDirectory().toString() + "/bots/seedlet");
boolean b = seedletDir.mkdirs();
if (seedletDir.exists()) {
//Reading the file
try {
for (String dir : assets.list("seedlet")) {
File subdir = new File(seedletDir.getPath() + "/" + dir);
boolean subdir_check = subdir.mkdirs();
for (String file : assets.list("seedlet/" + dir)) {
File f = new File(seedletDir.getPath() + "/" + dir + "/" + file);
if (f.exists()) {
continue;
}
InputStream in = null;
OutputStream out = null;
in = assets.open("seedlet/" + dir + "/" + file);
out = new FileOutputStream(seedletDir.getPath() + "/" + dir + "/" + file);
//copy file from assets to the mobile's SD card or any secondary memory
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
//get the working directory
MagicStrings.root_path = Environment.getExternalStorageDirectory().toString() + "/seedlet";
System.out.println("Working Directory = " + MagicStrings.root_path);
AIMLProcessor.extension = new PCAIMLProcessorExtension();
//Assign the AIML files to bot for processing
bot = new Bot("seedlet", MagicStrings.root_path, "chat");
chat = new Chat(bot);
String[] args = null;
mainFunction(args);
}
When I ran the application and started to chat with the bot, the bot incorrectly replies "I have no answer for that"
Chat
How can I solve this problem?
Add these two permissions to manifest file
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
Related
I'm developing an app which stores few setting in two .xml files, saved on internal storage. I need to save them in there, so please don't answer me "Save them on SD-cards".
I try to uninstall an then re-install (from Android Studio) my app to see if the android:allowBackup="true" works also for internal stored file but the answer was no.
Is this because I done the re-install from the IDE or I need to add some code somewhere?
Thanks for help.
Starting API level 29 there is the "hasFragileUserData" manifest flag
The documentation states that
If true the user is prompted to keep the app's data on uninstall.
May be a boolean value, such as "true" or "false".
Sample code:
<application
....
android:hasFragileUserData="true">
You can save those file using Environment.getExternalStorageDirectory() This stores on the external storage device. Dont get confused with the term external storage as the SD card. SD card is the secondary external storage. But Environment.getExternalStorageDirectory() returns top-level directory of the primary external storage of your device which is basically a non removable storage.
So the file path can be /storage/emulated/0/YOURFOLDER/my.xml
So even if you uninstall the app, these files will not get deleted.
You can use this snippet to create a file in your primary external storage:
private final String fileName = "note.txt";
private void writeFile() {
File extStore = Environment.getExternalStorageDirectory();
// ==> /storage/emulated/0/note.txt
String path = extStore.getAbsolutePath() + "/" + fileName;
Log.i("ExternalStorageDemo", "Save to: " + path);
String data = editText.getText().toString();
try {
File myFile = new File(path);
myFile.createNewFile();
FileOutputStream fOut = new FileOutputStream(myFile);
OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut);
myOutWriter.append(data);
myOutWriter.close();
fOut.close();
Toast.makeText(getApplicationContext(), fileName + " saved", Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
}
}
Don't forget to add below permission in Android Manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
You can then read that file as below:
private void readFile() {
File extStore = Environment.getExternalStorageDirectory();
// ==> /storage/emulated/0/note.txt
String path = extStore.getAbsolutePath() + "/" + fileName;
Log.i("ExternalStorageDemo", "Read file: " + path);
String s = "";
String fileContent = "";
try {
File myFile = new File(path);
FileInputStream fIn = new FileInputStream(myFile);
BufferedReader myReader = new BufferedReader(
new InputStreamReader(fIn));
while ((s = myReader.readLine()) != null) {
fileContent += s + "\n";
}
myReader.close();
this.textView.setText(fileContent);
} catch (IOException e) {
e.printStackTrace();
}
Toast.makeText(getApplicationContext(), fileContent, Toast.LENGTH_LONG).show();
}
I've downloaded an OCR text recognizer from github.
My problem is: I want to launch my app without being online, but everytime I install the apk on my phone, it starts downloading the english language and the tesseract OCR engine.
I've found an online guide which says I have to create a folder in the assets folder called "tessdata" and put the eng.traineddata and the osd.traineddata in this folder.
I've tried but the download process still starts when I install the app for the first time.
What can I do to make this app completely offline?
First, in your project directory in computer (YourProjectDirectory\app\src\main) create assets folder, int this folder create another tessdata folder. In tessdata folder put your .traineddata files, these will be transferred in your phone when your project starts running. You can download .traineddata files for your language HERE.
For transferring .traineddata files into phone I use this code:
public class TessOCR {
public static final String PACKAGE_NAME = "com.example.dainius.ocr";
public static final String DATA_PATH = Environment
.getExternalStorageDirectory().toString() + "/AndroidOCR/";
public static final String lang = "eng";
private static final String TAG = "TESSERACT";
private AssetManager assetManager;
private TessBaseAPI mTess;
public TessOCR(AssetManager assetManager) {
Log.i(TAG, DATA_PATH);
this.assetManager = assetManager;
String[] paths = new String[] { DATA_PATH, DATA_PATH + "tessdata/" };
for (String path : paths) {
File dir = new File(path);
if (!dir.exists()) {
if (!dir.mkdirs()) {
Log.v(TAG, "ERROR: Creation of directory " + path + " on sdcard failed");
return;
} else {
Log.v(TAG, "Created directory " + path + " on sdcard");
}
}
}
if (!(new File(DATA_PATH + "tessdata/" + lang + ".traineddata")).exists()) {
try {
InputStream in = assetManager.open("tessdata/" + lang + ".traineddata");
OutputStream out = new FileOutputStream(new File(DATA_PATH + "tessdata/", lang + ".traineddata"));
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
in.close();
out.close();
Log.v(TAG, "Copied " + lang + " traineddata");
} catch (IOException e) {
Log.e(TAG, "Was unable to copy " + lang + " traineddata " + e.toString());
}
}
mTess = new TessBaseAPI();
mTess.setDebug(true);
mTess.init(DATA_PATH, lang);
}
public String getResults(Bitmap bitmap)
{
mTess.setImage(bitmap);
String result = mTess.getUTF8Text();
return result;
}
public void onDestroy() {
if (mTess != null)
mTess.end();
}
}
This code checks whether in your phone exists file with directory /AndroidOCR/tessdata/eng.traineddata and if not, creates one and puts .traineddata file here.
For this to occur, in your OnCreate you will have to create AssetManager, which will let you to access that .traineddata file you placed in your computer in your project.
So in your OnCreate in MainActivity:
AssetManager assetManager = getAssets();
TessOCR tess = new TessOCR(assetManager);
Also, to allow your Android project write data into your phone in AndroidManifest.xml file you need to add permision line:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
This is the method I use personally and it works without any errors. If you have any, search in google for answers and if you still can't find an answer, post in comments.
I have created a simple application to take some user data and write it to a text file which gets saved on the external storage of my device. However, I am unable to access those files using my computer until after I have rebooted my device. Can anyone tell me why this is and if there is something I can do to fix it?
Here is the code I use to write data.
private void commitToFile(String worldOrApp, String xPos, String yPos, String orient) {
Intent intent = getIntent();
String filename = intent.getStringExtra(MainActivity.FILENAME) + ".txt";
final String position = worldOrApp + " - x: " + xPos + "; y: " + yPos + "; alpha: " + orient + "\r\n";
File myPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File myFolder = new File(myPath.getAbsolutePath()+"/test_folder");
if (!myFolder.exists()) {
myFolder.mkdirs();
}
File myFile = new File(myFolder, filename);
try {
FileOutputStream fileOutputStream = new FileOutputStream(myFile, true);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream);
outputStreamWriter.write(position);
outputStreamWriter.flush();
outputStreamWriter.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Thanks to #CommonsWare for the direction. I found the following code at Android saving file to external storage
// Tell the media scanner about the new file so that it is
// immediately available to the user.
MediaScannerConnection.scanFile(this, new String[] { file.toString() }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
}
});
which I placed directly underneath the exception catch in my code, and updated file to myFile, which is the relevant File for my commitToFile method.
I have one requirement in my Android application. I need to download and save file in specific folder of SD card programmatically. I have developed source code, which is
String DownloadUrl = "http://myexample.com/android/";
String fileName = "myclock_db.db";
DownloadDatabase(DownloadUrl,fileName);
// and the method is
public void DownloadDatabase(String DownloadUrl, String fileName) {
try {
File root = android.os.Environment.getExternalStorageDirectory();
File dir = new File(root.getAbsolutePath() + "/myclock/databases");
if(dir.exists() == false){
dir.mkdirs();
}
URL url = new URL("http://myexample.com/android/");
File file = new File(dir,fileName);
long startTime = System.currentTimeMillis();
Log.d("DownloadManager" , "download url:" +url);
Log.d("DownloadManager" , "download file name:" + fileName);
URLConnection uconn = url.openConnection();
uconn.setReadTimeout(TIMEOUT_CONNECTION);
uconn.setConnectTimeout(TIMEOUT_SOCKET);
InputStream is = uconn.getInputStream();
BufferedInputStream bufferinstream = new BufferedInputStream(is);
ByteArrayBuffer baf = new ByteArrayBuffer(5000);
int current = 0;
while((current = bufferinstream.read()) != -1){
baf.append((byte) current);
}
FileOutputStream fos = new FileOutputStream( file);
fos.write(baf.toByteArray());
fos.flush();
fos.close();
Log.d("DownloadManager" , "download ready in" + ((System.currentTimeMillis() - startTime)/1000) + "sec");
int dotindex = fileName.lastIndexOf('.');
if(dotindex>=0){
fileName = fileName.substring(0,dotindex);
}
catch(IOException e) {
Log.d("DownloadManager" , "Error:" + e);
}
}
Now the issue is only empty file with filename myclock_db.db is saving in the path. but I need to download and save content of file in the specific folder. Tried several ways to get the file download, but I can't.
Your download URL is not a link to any file. It's a directory. Make sure its a file and exists. Also check your logcat window for error logs. One more suggestion, its always better to do a printStackTrace() in catch blocks instead of Logs. Its gives a more detailed view of the error.
Change this line:
URL url = new URL("http://myexample.com/android/");
to:
URL url = new URL("http://myexample.com/android/yourfilename.txt"); //some file url
Next, in catch block, add this line:
e.printStackTrace();
Also in the directory path, it should be something like this:
File dir = new File(root.getAbsolutePath() + "/mnt/sdcard/myclock/databases");
instead of
File dir = new File(root.getAbsolutePath() + "/myclock/databases");
Next, make sure you have acquired permission for writing to external storage in Android manifest.
I used a tutorial to download a zip into a subdirectory of my application's internal storage. I wrote the zip to /data/data/my.package.name/files/mySubDirectory/the.zip.
But, when I check to see whether the zip exists, it doesn't:
String fileDirectory = this.getFilesDir().getAbsolutePath() + "/mySubDirectory/the.zip";
File file = new File(fileDirectory);
if(file.exists()) {
Log.e(this.class.getName(), "file exists");
} else {
Log.e(this.class.getName(), "file doesn't exist");
}
I verified that fileDirectory is the same path as the File outFile for the FileOutputStream.
What could be the problem?
Try getting your file path as below :
String fileDirectory=Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "data" + File.separator + "data" + File.separator+ getActivity().getPackageName()+ File.separator +"mySubDirectory"+File.separator+"the.zip";
Using this SO question, I created a subdirectory using this example:
File mydir = context.getDir("mydir", Context.MODE_PRIVATE); //Creating an internal dir;
File fileWithinMyDir = new File(mydir, "myfile"); //Getting a file within the dir.
FileOutputStream out = new FileOutputStream(fileWithinMyDir); //Use the stream as usual to write into the file
The problem is that I didn't expect the subdirectory to be prepended with "app_", so I was looking for the zip in the wrong place.
Try using getFilesDir() + "/" subdirectory + "/" "the.zip"
Without the getabsolutepath().
That is what I used could be the issue.
OK maybe you problem is with permissions do you see the file in the DDMS under data/data/package/files ? Check the permissions for the files
Here is my code
String path = getFilesDir() + "/"
+ subDirName + "/";
File file = new File(path);
file.mkdirs();
setReadable(file);
I use the following to make the file readable
#TargetApi(9)
private void setReadable(File file) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
try {
Runtime.getRuntime().exec(
"chmod 777 " + file.getCanonicalPath());
} catch (IOException e1) {
e1.printStackTrace();
}
} else {
file.setReadable(true, false);
}
}
}