I have 4 txt files in my desktop.
I create an android app where I will read these files and print these in an EditText, but
these files are drug drop in ddms -> myapp -> data -> files.
So with emulator my app play correctly, but in my mobile phone, don't read these files and close the app.
This is my code:
public String ReadFileTrack1()
{
FileInputStream fIn = null;
InputStreamReader isr = null;
char[] inputBuffer = new char[900];
String data = null;
try
{
fIn = openFileInput(tracks[0]+".txt");
isr = new InputStreamReader(fIn);
isr.read(inputBuffer);
data = new String(inputBuffer);
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
try
{
isr.close();
fIn.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
return data;
}
The code is correct, but don't play in my mobile phone.
What I can do for this problem?
How can i load these 4 txt files in my mobile phone so that my app play correctly?
You cannot write to an app's private storage directory on a secured device, unless the application first makes a subdirectory and grants others write access to it (which is generally a bad idea).
Put the files on the external storage (sdcard) instead, or package them as assets in the apk when you build it.
(There is an exception: if the application is built debuggable, then one can use the adb shell's run-as tool to copy something into the private directory as the appliction user, but that's obscure and not something you'd want to use as it does not apply to finalized apps. Generally that capability is used in the other direction, to examine what an app under development has done to its files or database when it is not working correctly)
Related
I had to port my game from Cocos2dX to Unity for various reasons.
I have now ported the project successfully but to launch it I have to make a mechanism to get old user data and store it in new structure, like number of levels locked, high score of users etc.
While searching I came to know that COCOS2dX stored data on user's device on following path
system/data/data/mygamepackage/shared_prefs/Cocos2dxPrefsFile.xml
Is there anyway to get data from above mentioned path?
The above path should be accessible by the app it self.
I am not able to read that file I get following error.
ENOENT No Such file or Directory
The file is there I can see that on rooted device via Root Browser but I get the error when I run the app on same device.
All I need is to access the file programmatically and later I will parse it and will store it via Unity for future use.
Looking forward for a positive and quick response.
I dont know why I am unable to get the file through Unity Engine, I had to write custom plugin is Java and use that in Unity Project and that some how has worked.
Following is the code which return string after reading the file on both rooted and non rooted devices
public static String getCocos2DPrefsFile(String mPackageName)
{
//Get the text file
File file = new File("/data/data/"+mPackageName+"/shared_prefs/","Cocos2dxPrefsFile.xml");
//Read text from file
StringBuilder text = new StringBuilder();
try {
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
while ((line = br.readLine()) != null) {
text.append(line);
text.append('\n');
}
br.close();
}
catch (IOException e) {
//You'll need to add proper error handling here
Log.d("Error", e.toString());
}
return text.toString();
}
Having a problem writing out to a file, this code is taken directly from the android developer page and then tweaked a bit by me. Is there something i am missing? Quite new to Android development so sorry if it's something blatantly obvious.
send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FileOutputStream outputStream;
String data = "hello";
File fileDir = new File("data.txt");
if (!fileDir.exists())
fileDir.mkdirs();
try {
outputStream = openFileOutput("data.txt",Context.MODE_PRIVATE);
outputStream.write(data.getBytes());
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
});
Basically, your problem is that you are trying to do it twice, once in a way that won't work, and once in a way that will, but hides the result.
File fileDir = new File("data.txt");
if (!fileDir.exists())
fileDir.mkdirs();
This would create a Java File object connected to a hypothetical file called "data.txt" located in the current working directory, which for an Android app is the root directory of the device - a place you most definitely are not allowed to write to. However, this may not obviously cause any errors, as the root directory exists so mkdirs() will do nothing, and you only create a File object, you don't actually try to create a file on "disk". Effectively this code does nothing for you - get rid of it.
Next you try something basically workable:
try {
outputStream = openFileOutput("data.txt",Context.MODE_PRIVATE);
outputStream.write(data.getBytes());
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
openFileOutput() is a method of a Context (Activity or Service) which creates an output stream to write to an actual file located in the private internal storage area of your app. This is all fine and good, and normally a good choice for storing typical data. However, it is not a place that you will be able to examine when running a release app on a secured device, as neither ADB based tools nor Mass Storage or MTP access over USB have rights to it. So it's entirely possible that this code worked, but you had no way to discover that fact. If you are on an emulator, you can access this location with ADB or the DDMS browser, and if your apk is a debug one, you can use the run-as command line tool in the shell.
If you want to share the data, you might consider putting it on the External Storage instead.
First: see my question Reading XML online and Storing It (Using Java). Read the approved answers and the comments underneath that answer.
So, what my question here is: even though I've run through the process described in the linked question, and the .xml file saves to the /res/values folder in my Android App, its not showing up at all - not when I'm running the app, nor after I close the app.
Does anyone have any ideas on how to fix this so that when I generate the file, it will be available right away, even while the app is running, to read and use?
just use this code,
FileOutputStream fOut = null;
try {
fOut = this.openFileOutput("your xml file name.xml", MODE_PRIVATE);
try {
InputStream is = new FileInputStream("your source file");
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
fOut.write(buffer);
} catch(Exception e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
fOut.close();
} catch (IOException e) {
e.printStackTrace();
}
}
and you can see your xml file at the data/data/packagename/file folder Thnx. Hope this will help you.
I'm not 100% sure if you're running the XML parsing in Java or actually in your Android app.
If you're running in Java, be aware that your project structure isn't live in the emulator - the .apk was packaged up and installed before running. You need to use adb to push files into the emulator (or your Android device) before your app can see the file.
If you're accessing the file in the app:
If you use file access methods such as openFileOutput() it will show up in the private directory on the device, which would be /data/data//files/
However, if you're using "new File(" rather than "context.openFileOutput" then the file is wherever you put it.
My app has .txt files in subdirectories in the assets folder. It reads those .txt files and puts them in a textview. It's working great and no problems.
Should I be concerned about the files in the assets folder getting deleted by the user or missing. If this ever could happen, my app would get an error because the file would not be there when it tried to read it into the stream.
Is there a need for me to check the existence of an asset file before I read it or does the asset manager take care of it all? I also was wondering if there's a chance that a user would or could delete and asset file.
Like I say, everything works fine without me inserting code to check for file existence. I just wondered if people use the .exists() statement every time they go to read in a stream from assets.
You may be concerned that the file have been removed and the apk resigned
You can check using:
Arrays.asList(getResources().getAssets().list("")).contains("myFile")
if you really want to check for the file existence:
AssetManager mg = getResources().getAssets();
InputStream is = null;
try {
is = mg.open(pathInAssets);
//File exists so do something with it
} catch (IOException ex) {
//file does not exist
} finally {
if (is != null) {
is.close();
}
}
If your file is located in assets/folder/file.ext, then pathInAssets would be
"folder/file.ext"
Ideally after apk is built, nobody can remove any assets from it, but if someone decompiled it and recompiles than it may be possible.
Though for other scenarios also when an asset is not present in apk at Runtime, we can check the existence of asset.
In our app, we have a provision to build app using gradle, ant and eclipse, and for each build mechanism some of our assets file are bundled in apk and some are not, so to identify if any asset file is present in current build apk at runtime,
we do this as follows:
private boolean isAssetExists(String pathInAssetsDir){
AssetManager assetManager = AppContext.get().getResources().getAssets();
InputStream inputStream = null;
try {
inputStream = assetManager.open(pathInAssetsDir);
if(null != inputStream ) {
return true;
}
} catch(IOException e) {
e.printStackTrace();
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
Yes and No.
A normal user would not be able to delete them, but a user on a rooted phone who doesn't know what they're doing… that's a different situation.
If you ask me, the extra code is not needed. Also if you try and open a file that doesn't exist, you will get an exception thrown at some point, catch that and display a dialog if you really want to.
AssetManager am = getAssets();
try {
List<String> mapList = Arrays.asList(am.list("path/in/assets/folder"));
if (mapList.contains("file_to_check")) {
Log.e("ERROR", "exists");
} else {
Log.e("ERROR", "not exists");
}
} catch ( IOException ex){
ex.printStackTrace();
}
Convert to function or method can be easy ;)
I think you should be OK. From having a root around in my phone I can't see any way of deleting the assests without deleting the app as it all seems to be wrapped up in the .apk file. You can do it but I think you need to be rooted or use adb.
I would personally surround any reading/writing with a try/catch block anyway, just to be safe.
The problem is this:
I make an internet connection to some url and receive an HttpResponse with an app_example.apk.
Then I want to create a file (an .apk)
in the sdcard with this data so that this downloaded application
can be installed later.
How can I convert the HttpResponse to an .apk file?
Let's clear some details:
I have to get this apk file through an internet connection to my server
I don't want to install this applications I receive on the sdcard
All of this has to be done in my code, I cannot use android market
I am currently writing to that file.
What I'm doing is converting the HttpResponse to a byte[ ],
then that byte[ ] is written to a file (an .apk) using an ObjectOutputStream.
Like this:
// byte[] appByteArray - already has the internet response converted in bytes
try {
file = new File(Environment.getExternalStorageDirectory()+"/"+appName+".apk");
file.createNewFile();
FileOutputStream stream = null;
stream = new FileOutputStream(file, false);
ObjectOutputStream objectOut =
new ObjectOutputStream(new BufferedOutputStream(stream));
objectOut.writeObject(appByteArray);
objectOut.close();
} catch (Exception e) {
e.printStackTrace();
}
In the end, the file is created
and has the received content.
When I try to install it,
through a VIEW intent (using the default installer)
I get a parse error saying that it could not find the AndroidManifest.xml.
I think that in some step along the way, the received data is being corrupted.
Do you have another method to solve this?
Many thanks
Don't use an ObjectOutputStream, byte array is serialized as Object, not written as raw data.
Are you sure that you have SD card write permission? android.permission.WRITE_EXTERNAL_STORAGE
Don't write into SD card root directory. Number of files in root dir can be limited. Instead create you app subdirectory on SD CARD.
This code works for me:
try {
String filePath = Environment.getExternalStorageDirectory()
+ "/myappdir/" + appName + ".apk";
File file = new File(filePath);
file.getParentFile().mkdirs();
file.createNewFile();
BufferedOutputStream objectOut = new BufferedOutputStream(
new FileOutputStream(file));
objectOut.write(appByteArray);
objectOut.close();
} catch (Exception e) {
e.printStackTrace();
}
This may not be the core problem, but I don't think you want to wrap stream in an ObjectOutputStream, since that is used for object serialization. It could be that it is adding extra data to the file so it can be deserialized with ObjectInputStream.
I would try pulling the apk off of the emulator (or device) and check it's MD5 versus the file on the server to make sure that the bits are being written out correctly.
Take a look at Pavel P's answer.
Also, I would note that your idea of installing the APK using the VIEW intent action does work, as I have tested this technique in the past.
However, unless the user has explicitly gone into Settings → Applications and selected "Allow non-Market applications", your installation will fail and the user will just see a screen telling them that for security reasons the installation has been blocked.
Basically you really need to rely on having fairly tech-savvy users who are willing to overlook a scary security warning and go and disable that setting.