I am developing software that loads information from XML files using Android's implementation of java.xml.parsers.DocumentBuilder and DocumentBuilderFactory. I am writing unit tests of my objects and I need to be able to provide a variety of xml files that will exercise the code under test. I am using Eclipse and have a separate Android Test Project. I cannot find a way to put the test xml into the test project such that the code under test can open the files.
If I put the files in /assets of the test project, the code under test cannot see it.
If I put the files in the /assets of the code under test, it can of course see the files, but now I'm cluttering up my actual system with test only data files.
If I hand copy the files to the /sdcard/data directory, I can open them from the code under test, but that interferes with automating my tests.
Any suggestions of how to have different xml test files reside in the test package but be visible to the code under test would be greatly appreciated.
Here is how I tried to structure the unit test:
public class AppDescLoaderTest extends AndroidTestCase
{
private static final String SAMPLE_XML = "sample.xml";
private AppDescLoader m_appDescLoader;
private Application m_app;
protected void setUp() throws Exception
{
super.setUp();
m_app = new Application();
//call to system under test to load m_app using
//a sample xml file
m_appDescLoader = new AppDescLoader(m_app, SAMPLE_XML, getContext());
}
public void testLoad_ShouldPopulateDocument() throws Exception
{
m_appDescLoader.load();
}
}
This did not work as the SAMPLE_XML file is in the context of the test, but AndroidTestCase is providing a context for the system under test, which cannot see an asset from the test package.
This is the modified code that worked per answer given:
public class AppDescLoaderTest extends InstrumentationTestCase
{
...
protected void setUp() throws Exception
{
super.setUp();
m_app = new Application();
//call to system under test to load m_app using
//a sample xml file
m_appDescLoader = new AppDescLoader(m_app, SAMPLE_XML, getInstrumentation().getContext());
}
Option 1: Use InstrumentationTestCase
Suppose you got assets folder in both android project and test project, and you put the XML file in the assets folder. in your test code under test project, this will load xml from the android project assets folder:
getInstrumentation().getTargetContext().getResources().getAssets().open(testFile);
This will load xml from the test project assets folder:
getInstrumentation().getContext().getResources().getAssets().open(testFile);
Option 2: Use ClassLoader
In your test project, if the assets folder is added to project build path (which was automatically done by ADT plugin before version r14), you can load file from res or assets directory (i.e. directories under project build path) without Context:
String file = "assets/sample.xml";
InputStream in = this.getClass().getClassLoader().getResourceAsStream(file);
For Android and JVM unit tests I use following:
public final class DataStub {
private static final String BASE_PATH = resolveBasePath(); // e.g. "./mymodule/src/test/resources/";
private static String resolveBasePath() {
final String path = "./mymodule/src/test/resources/";
if (Arrays.asList(new File("./").list()).contains("mymodule")) {
return path; // version for call unit tests from Android Studio
}
return "../" + path; // version for call unit tests from terminal './gradlew test'
}
private DataStub() {
//no instances
}
/**
* Reads file content and returns string.
* #throws IOException
*/
public static String readFile(#Nonnull final String path) throws IOException {
final StringBuilder sb = new StringBuilder();
String strLine;
try (final BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(path), "UTF-8"))) {
while ((strLine = reader.readLine()) != null) {
sb.append(strLine);
}
} catch (final IOException ignore) {
//ignore
}
return sb.toString();
}
}
All raw files I put into next path: ".../project_root/mymodule/src/test/resources/"
Try this for Kotlin:
val json = File("src\\main\\assets\\alphabets\\alphabets.json").bufferedReader().use { it.readText() }
Related
I have MainClass
public class MainClass extends Application {
#Override
public void start(Stage primaryStage) {
try{
Image img = new Image(getClass().getResourceAsStream(".\\build\\resources\\main\\img\\h1.jpg"));
System.out.println("ok");
}
catch(Exception ex){
System.out.println(ex.getMessage());
}
}
public static void main(String[] args) {
launch(args);
}
}
and my image is in \build\resources\main\img\h1.jpg directory
my project files:
When I run project it gives Input stream must not be null exception.
Resource paths are not separated by \ Furthermore they start at the resource root. In this case the path "/img/h1.jpg" should do the trick assuming your IDE properly includes the resources in the classpath at runtime.
getResource(AsStream) does not access the data via file path; The data may not be available as file at all, but as entry in a JAR file. If you need to refer to a file that is not included in the classpath, use File's functionality to convert to a URI or use a FileInputStream:
new Image(new File(".\\build\\resources\\main\\img\\h1.jpg").toURI().toString())
I've read every SO post regarding use of fonts in Android and I still can't get mine to work. I'm getting the following exception:
java.lang.RuntimeException: native typeface cannot be made
Here's my code (this class and static method is taken from here):
public class SafeTypefaces {
private static final Hashtable<String, Typeface> cache = new Hashtable<String, Typeface>();
public static Typeface get(Context c) {
final String assetPath = "fonts/robotobold.ttf";
synchronized (cache) {
if (!cache.containsKey(assetPath)) {
try {
AssetManager assetManager = c.getAssets();
Typeface t = Typeface.createFromAsset(assetManager, assetPath); //Throws exception on this line!
cache.put(assetPath, t);
} catch (Exception e) {
L.p("Could not get typeface '" + assetPath + "' because " + e.getMessage());
return null;
}
}
return cache.get(assetPath);
}
}
}
The font is in the assets/fonts folder:
(this is still Eclipse. I know, I know).
Things I've tried:
I've tried moving the font to the root of the assets folder and updating the assetPath.
I checked folder and file permissions.
I tried using the application context instead of the activity context I'm getting.
I tried using different font files (one send via email, another downloaded from the Internet).
As I was creating this question I ran into the solution. I've spend a few hours on this so I guess its worth keeping.
My problem was that I was working on a library project. According to this (Android Library assets folder doesn't get copied), assets in library projects aren't available to the main project, which is why the font file wasn't being found. (Again, this project is still using Eclipse. Possibly not the case using Gradle+AS).
The solution is to copy the fonts into the main project, and voila!
I have a problem with this line of code. Want to create sqlite database on the device.
string dbPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal) + "\\test.db";
if (!System.IO.File.Exists(dbPath))
using (System.IO.Stream sr = ***Assets***.Open("test.db"))
{
using (System.IO.Stream srTo = System.IO.File.Create(dbPath))
{
sr.CopyTo(srTo);
}
}
This message gives the:
The name 'Assets' does not exist in the current context
have a similar project, but more comprehensive than big. There is no error. They Assets Where I'm following definition defines a cs file in c drive gives reference to Android.Content.ContextWrapper.
is not on The project the path.
[How the file was added application?
If you aren't doing this in an activity you need a reference to the Activity/Context. You will need to pass this in to your helper class in the constructor.
public yourClass(Activity context.......){
context.Assets.Open("your.db");
}
You can do like this:
using (System.IO.Stream sr = Android.App.Application.Context.Assets.Open("test.db"))
{
using (System.IO.Stream srTo = System.IO.File.Create(dbPath))
{
sr.CopyTo(srTo);
}
}
I currently have a compiled jar file that I would like to use on an android device. The code outputs to the command line using System.out.println().
How would I create a wrapper to grab the stdout and put it in a text view on an android device? Would I need to make any changes to the jar (I do have all the source code) to allow the wrapper?
Thanks in advance.
I think you'll need to make some changes. You can set standart output by calling
System.setOut(PrintStream out)
// Reassigns the "standard" output stream.
Where out is your own class that will print data to text view. See swing solution. Just set appending to text view and you can use this code.
Or just create one method
void log(String message);
where you appending text to your view. Then change all println() calls to this.
First you should consider that Android has a specific Java VM called Dalvik and not any jar can be ran under it.
If there's one point in your jar where output occurs, the best option would be to create a usual application with a TextView, include your jar to it's build path and replace a call to println() with output to it:
public void print(String msg) {
mTextView.setText(msg);
}
If there're many sources of output you could run you jar using java.lang.Process and use it's getInputStream() method to read printed messages:
public static final String XBOOT_CLASS_PATH = "-Xbootclasspath:/system/framework/core.jar"
public static final String CLASS_PATH = "-classpath /path/to/your/file.jar com.your.package.name"
...
Process p = new ProcessBuilder("dalvikvm", XBOOT_CLASS_PATH, CLASS_PATH).start();
BufferedReader reader = new BufferedReader (new InputStreamReader(p.getInputStream()));
String msg = reader.readLine();
if (msg != null) {
mTextView.setText(msg);
}
// Cleanup omitted for simplicity
If it's an executable jar file here is a working example
Add this simple executable HelloWorld jar file to your Android Project's build path
If the jar file doesn't have a package, then you will have to use Reflection to invoke methods in it.Other wise you can just import the class files and invoke the main method directly.(This example jar has a package "psae")
eg:
TextView tv = (TextView)findViewById(R.id.textv);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
System.setOut(ps);
String[] params = {"Aneesh","Joseph"};
psae.HelloWorld.main(params);
String output = baos.toString();
tv.setText(output)
If the jar file just has a default package, then you won't be able to import class files from that jar, and hence you will have to use Reflection to invoke the method.
TextView tv = (TextView)findViewById(R.id.textv);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
System.setOut(ps);
try {
//pick the entry class from the jar Manifest
//Main-Class: psae.HelloWorld
Class myClass = Class.forName("psae.HelloWorld");
//since this has a package, there is no need of reflection.This is just an example
//If the jar file had just a default package, the it would have been something like the below line (and this is where it would be useful)
//Class myClass = Class.forName("Main");
Method myMethod = myClass.getMethod("main", String[].class);
//parameters to the main method
String[] params = {"Aneesh","Joseph"};
myMethod.invoke(null, (Object) params);
String output = baos.toString();
tv.setText(output);
}
catch(Exception d)
{
tv.setText(d.toString());
}
I'm facing a kind of curse about asset accessing with Android. I'm using NetBeans 6.9.1 and testing on a 2.3 Android Virtual Device. I'm trying to access a database file ("database.db") stored in the assets folder (though I've had to make the directory by myself because it didn't even existed in my project folder) and I'm simply unable to do it after more than 3 days lost looking for a solution. Here a summary of my tragic process:
I've created a directory called "assets" in my NetBeans project directory (just where the "res" or the "src" folders are).
I've copied the "database.db" file inside and even a "sample.txt", which I've also stored in the "assets/sub" subdirectory as I'm testing everything humanly possible.
I have a class that inherits from "SQLiteOpenHelper" where I'm simply trying to access my database file and, after seeing that it's nearly impossible, I'm just trying to see what my assets folder contains:
public class DataBaseHelper extends SQLiteOpenHelper{
private static String DB_PATH = "/data/data/org.me.androidbt/databases/";
private static String DB_NAME = "database.db";
private SQLiteDatabase myDataBase;
private final Context myContext;
public DataBaseHelper(Context context) {
super(context, DB_NAME, null, 1);
this.myContext = context;
}
private void myFunction() throws IOException{
//Firs try, explodes terribly at the first line
InputStream is = myContext.getAssets().open("sub/sample.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = null;
int number = 0;
while ((line = br.readLine()) != null) {
// Just used to check the "line" value when debugging
number++;
}
br.close();
// Second try, didn't explodes
AssetManager mngr = myContext.getResources().getAssets();
String[] str = mngr.list("");
// String only contains three elements: "images", "sounds" and "webkit"
// (an there aren't such things in my assets folder)
// Real try to open the DB, dies horribly and blowns up my PC
InputStream myInput = myContext.getAssets().open(DB_NAME);
I've also tried to access it from the MainActivity itself:
try{
AssetManager mng = this.getAssets();
String[] str = mng.list("");
// The same three elements...
// And this explodes in a nuclear toxic cloud that kills a thousand birds
InputStream is = this.getAssets().open("sub/sample.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = null;
int number = 0;
while ((line = br.readLine()) != null) {
number++;
}
br.close();
}catch(Exception e){
// Life is sad...
}
And now, some questions: What I'm doing wrong? Is my assets folder correctly placed? Are my files correclty copied? Is my code correctly placed?
To fix:
Create a directory called ‘assets’ at your project root (same dir that AndroidManifest.xml lives)
In /nbproject/project.properties, change
*add these two lines (it wont exist)*
assets.dir=assets
assets.available=true
In /nbproject/build-impl.xml,
there is line in the “if=assets.available” target that reads
that needs to be changed to
That’s it – you should be all set and “file:///android_asset/” should be accessible to your application and contain the contents of your project’s assets directory.
Got this link and it worked for me!!...
http://blog.yetisoftware.com/2009/04/02/android-netbeans-and-the-assets-directory/
i had this problem and i suggest you check couple of things:
If the directory name is written in english.
you have just one directory in your assets root (in this one directory you can insert couple of drectories).
For example: assets -> app -> image, assets -> app -> another dir. In this example the app dir is the only dir in the asssete root.