Extract file from .apk? - java

in my android app I'm using an own java library that extracts a .db-file from jar. In Java desktop it works well, but when I try to do it on android, the inputstream blocks forever. The copy method looks like this:
InputStream in = classloader.getResourceAsStream(...);
OutputStream out = new FileOutputStream(new File(...));
try {
while ((read = in.read()) != -1) {
out.write(read);
}
} finally {
try {
in.close();
} catch (final Exception e) {
LOGGER.debug("Error", e);
}
try {
out.close();
} catch (final Exception e) {
LOGGER.debug("Error", e);
}
}
I want to copy this file to the external files dir and android.permission.WRITE_EXTERNAL_STORAGE is granted.
Is there a way to access the file in /data/app/...apk? If not, how can I detect that it can not be accessed without blocking forever?

You should put the database-file in the /assets-folder and copy it to the /databases-folder on first run. A tutorial on this can be found here.
However, if you only want to create the tables and some sample-entry's, you might want to use the onCreate()-method from the SQLiteOpenHelper to do so.

Maybe you should store your data in the raw folder, you access it then :)
http://developer.android.com/guide/topics/resources/index.html

Answering to the question : we can only extract the class files from the apk that we have got, we will not get the layout/xml files or any other files.
There are ways by which we can extract the class files from the apk.

Related

Web Service to Display a PDF, deleting the file once displayed

I am attempting to display PDFs to the user in their browser using a web service. Once they pass in the URL containing the variables needed. My program first downloads the PDF to local storage then proceeds to copy it to the stream and displays it. Once the viewer is able to view the PDF we wish to delete the file locally so that we do not wind up storing every file searched for. I have managed to accomplish most of this task however I am having issues deleting the file once it is displayed to the user.
Even when I attempt to manually delete the file I receive the "Currently in use in the Java SE Binary" message
Code below:
File testFile = new File("C:\\Users\\stebela\\workspace\\my-app\\invoice"+invNum+".pdf");
try
{
ServletOutputStream os = res.raw().getOutputStream();
FileInputStream inputStr = new FileInputStream(testFile);
IOUtils.copy(inputStr, os);
os.close();
inputStr.close();
//finished settings
res.status(200);
testFile.delete();
} catch (IOException e)
{
System.out.println(e.getMessage());
}
If you don't write to the file, you'r code should work.
If you call inputStr.close(); the file is no longer used by java and it can be deleted.
Pleace check, if your file is not used by any other programm. It's the best if you reboot your PC.
If it still not works, it would be interessting to know, what res is and if your file get's sendet.
I've read this part of the documentation and i think this should solve your problem.
It reads the file into a String and change the header for png images. As the http Body it uses the String of the file.
Make sure, if you change the response type, you have to change the line res.type("image/png"); to the new one.
Here you find the most common ones
File testFile = null;
try {
testFile = new File("C:\\Users\\stebela\\workspace\\my-app\\invoice"+invNum+".png");
FileInputStream fin = new FileInputStream(testFile);
int charAsInt = 0;
String httpBody = "";
while((charAsInt = fin.read()) != -1){
httpBody +=(char)charAsInt;
}
fin.close();
res.body(httpBody);
res.type("image/png");
res.status(200);
testFile.delete();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

Java BufferedImage throwing NullPointerException

I am making a space shooter in Java, but when I try to load up the image resources, I get a null pointer exception. Everything works fine except the images. Am I coding the directory wrong? How can I fix it?
Here is my code:
BufferedReader highScoreReader;
BufferedWriter highScoreWriter;
try {
playerImage = ImageIO.read(this.getClass().getResourceAsStream("src/res/player.png"));
bulletImage = ImageIO.read(this.getClass().getResourceAsStream("src/res/bullet.png"));
enemyImage = ImageIO.read(this.getClass().getResourceAsStream("src/res/enemy.png"));
highScoreReader = new BufferedReader(new FileReader("/files/HIGH_SCORE.txt"));
highScoreWriter = new BufferedWriter(new FileWriter("/files/HIGH_SCORE.txt"));
} catch (Exception e) {
e.printStackTrace();
}
Here is a screenshot of my file directories:
Most probably, you need to copy your images into the build directory of your project. If you want them treated as classpath resources, which it seems you do, make sure they're in a source folder in eclipse (or, if you use maven or similar, in the src/main/resources folder. The point is, they need to be copied to the place where the .class file lives when it's running.
Remember: class.getResourceAsStream(...) returns things from the classpath not from your source path.
I've never seen it done that way.
Try this
try {
playerImage = ImageIO.read(getClass().getClassLoader().getResourceAsStream("src/res/player.png"));
catch(IOException e) {
}
or
try {
playerImage = ImageIO.read(new File("src/res/player.png"));
catch (IOException e) {
}
Arnav Garg has discovered the problem.
When your code says something like:
file("src/res/player.png")
the file is not there, i.e.
file.exists()
will return false
Find out where java thinks the file is.
try using
file.getAbsolutePath()
and compare that to your directory structure.

Writing multiple files to one file (like a file system)

I'm trying to store multiple data files that I have created into one file. Each file has an ID# (0-35) and each holds some data. But what I want is to be able to store all the files in one file called 'data.xx', then be able to access the each of the files data inside the data.xx file.
public static void pack(int id) {
try {
RandomAccessFile raf = new RandomAccessFile("./data/data.xx", "rw");
ByteArrayInputStream bis = null;
try {
byte[] data = toByteArray(id);
bis = new ByteArrayInputStream(data);
raf.seek(raf.length());
System.out.println(raf.length());
while (bis.read(data, 0, data.length) >= 0) {
raf.write(data, 0, data.length);
}
} finally {
bis.close();
raf.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
toByteArray(id) calls the separate data files then puts it into byte array. All the files seem to write fine to the data.xx file. The problem I'm having is I'm not really sure how to read the data.xx file so I can get the data from the files that are stored in it. I hope this makes sense. Also I don't need any compression and I don't want to use a library for this.
Thank you
The simplest way is use markup:
<id_0> content of file 0 </id_0>
...
<id_35> content of file 35 </id_35>
You write file like that and read content inside tags with substring
I would prepend the output file with the offsets of the start of each contained file. A special "token" is a nice idea, but files can contain any byte or bytes; making the idea not realistic. That way your "index" will terminate with something you can't confuse with file data because the information occurres before you expect arbitrary data ... say, 0? Please comment if I misunderstood this question.

Copying file without creating a FileOutputStream

I am making an application that includes file copying, but when I go through a large directory (1000+) files and copy them to another folder, it uses 290+ MB of RAM.
So, is there any way to change the File of FileOutputStream without creating a new instance of the FileOutoutStream class?
EDIT:
Here is my Java 7 API version.
Path source = FileSystems.getDefault().getPath(Drive.getAbsolutePath(), files[i].getName());
Path destination = FileSystems.getDefault().getPath(Save);
try {
Files.copy(source, destination);
} catch (FileAlreadyExistsException e) {
File file = new File(Save + files[i]);
file.delete();
}
Keep in mind, that this is in a for loop that is being tested on 1000+ file counts.
With the current method I am using 270+ MB of RAM
No, you can't redirect a FileOutputStream to a different file.
If you're using Java 7, you can use the new Files class to copy files. The Files.copy() methods can do most of the work for you.
Otherwise, verify that you're closing your streams. Prior to Java 7's try-with-resources, it could look something like this:
FileOutputStream out = null;
try {
// Create the output stream
// Copy the file
} catch (IOException e) {
// Do something
} finally {
if ( null != out ) {
try { out.close(); } catch ( IOException ) { }
}
}
Have a look at this question: Standard concise way to copy a file in Java?
specifically
..., Apache Commons IO is the way to go, specifically FileUtils.copyFile(); it handles all the heavy lifting for you.
How about some nio2 from Java 7?
Path source = // ...
Path target = // ...
Files.copy(source, target);
See javadoc of Files.copy(...) for details. See also the optional parameter CopyOption.

Java: Error when save file in Resource after Deployment

My program has a function that read/write file from resource. This function I have tested smoothly.
For example, I write something to file, restart and loading again, I can read that data again.
But after I export to jar file, I faced problems when write file. Here is my code to write file:
URL resourceUrl = getClass().getResource("/resource/data.sav");
File file = new File(resourceUrl.toURI());
FileOutputStream output = new FileOutputStream(file);
ObjectOutputStream writer = new ObjectOutputStream( output);
When this code run, I has notice error in Command Prompt:
So, My data cannot saved. (I know it because after I restarted app, nothing changed !!!)
Please help me solve this problem.
Thanks :)
You simply can't write files into a jar file this way. The URI you get from getResource() isn't a file:/// URI, and it can't be passed to java.io.File's constructor. The only way to write a zip file is by using the classes in java.util.zip that are designed for this purpose, and those classes are designed to let you write entire jar files, not stream data to a single file inside of one. In a real installation, the user may not even have permission to write to the jar file, anyway.
You're going to need to save your data into a real file on the file system, or possibly, if it's small enough, by using the preferences API.
You need to read/write file as an input stream to read from jar file.
public static String getValue(String key)
{
String _value = null;
try
{
InputStream loadedFile = ConfigReader.class.getClassLoader().getResourceAsStream(configFileName);
if(loadedFile == null) throw new Exception("Error: Could not load the file as a stream!");
props.load(loadedFile);
}
catch(Exception ex){
try {
System.out.println(ex.getMessage());
props.load(new FileInputStream(configFileName));
} catch (FileNotFoundException e) {
ExceptionWriter.LogException(e);
} catch (IOException e) {
ExceptionWriter.LogException(e);
}
}
_value = props.getProperty(key);
if(_value == null || _value.equals("")) System.out.println("Null value supplied for key: "+key);
return _value;
}

Categories