I'm currently writing a csv-file-importer for my app, but I have difficulties writing tests for it. What I'm trying to do is import a sample csv file and compare the results to the database.
public class CSVImportTest extends ProviderTestCase2<MyProvider> {
#Override
protected void setUp() throws Exception {
super.setUp();
mContentResolver = getMockContentResolver();
setContext(new IsolatedContext(mContentResolver, getContext()));
mContext = getContext();
mCSVImport = new CSVImportParker(mContext);
}
public void read() {
try {
// Fails here with "File not found."
InputStream input = mContext.getResources()
.openRawResource(my.package.R.raw.file);
...
} catch (Exception e) {
e.printStackTrace();
fail();
}
...
}
}
The test file is never found, although it is available at the correct location.
The issue is that resources in the raw directory are compressed unless they have an ogg or mp3 file extension. See this description:
Proguard breaking audio file in assets or raw
and from the docs
This function only works for resources that are stored in the package as uncompressed data, which typically includes things like mp3 files and png images.
So, the easiest way to solve the issue is by adding the mp3 or ogg file extension to your raw assets. It's not clean or pretty but it works.
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 added com.googlecode.libphonenumber:libphonenumber:8.8.2 in my project. In debug mode its works normally.But in signed apk its generating the following exception when a library method is called.
Caused by: java.lang.IllegalStateException: missing metadata: /com/google/i18n/phonenumbers/data/PhoneNumberMetadataProto_BD
at com.google.i18n.phonenumbers.e.getMetadataFromSingleFileName(SourceFile:188)
at com.google.i18n.phonenumbers.e.getMetadataFromMultiFilePrefix(SourceFile:116)
at com.google.i18n.phonenumbers.g.getMetadataForRegion(SourceFile:64)
at com.google.i18n.phonenumbers.PhoneNumberUtil.getMetadataForRegion(SourceFile:2211)
at com.google.i18n.phonenumbers.PhoneNumberUtil.getMetadataForRegionOrCallingCode(SourceFile:1330)
at com.google.i18n.phonenumbers.PhoneNumberUtil.parseHelper(SourceFile:3197)
at com.google.i18n.phonenumbers.PhoneNumberUtil.parse(SourceFile:3025)
at com.google.i18n.phonenumbers.PhoneNumberUtil.parse(SourceFile:3015)
at com.revesoft.itelmobiledialer.util.aq.b(SourceFile:697)ode here
Probably you have already fixed it, but it may help others. I had the same issue and I have fixed it as the library FAQs - How do I load libphonenumber resources in my Android app?
A possible problem can be that you are loading the metadata from the main thread. If this is not the case, then
you can copy the data folder with the metadata in your app. Create an assets folder src/main/assets/data.
In your application where you first want to read the data, create your own metadata loader that will read the metadata from its new destination. This is described in the link that I posted. The library FAQs suggest to delete the metadata files from the library in order not to duplicate files.
private static PhoneNumberUtil getPhoneNumberUtilInstance()
{
if(mPhoneNumberUtil == null)
{
mPhoneNumberUtil = PhoneNumberUtil.createInstance(new MetadataLoader()
{
#Override
public InputStream loadMetadata(String metadataFileName)
{
try
{
String[] stringPieces = metadataFileName.split("/");
String metadataName = stringPieces[stringPieces.length - 1];
InputStream is = Factory.get().getApplicationContext().getAssets().open("data/" + metadataName);
return is;
}
catch (IOException e)
{
// Handle somehow!
return null;
}
}
});
}
return mPhoneNumberUtil;
}
Help needed
I use the JID3 library to edit mp3 tags. This works fine as long as the music is on an internal sdcard. However, for api 19+ this no longer works for the external sdcard.
I understand I need to implement the Storage Access Framework but have no idea how to go about this.
The way JID3 works is it reads the mp3 file, extracts the tag(s) under consideration, say artist, updates the tag(s) with the new value.
the following steps need amendment:
create a .tmp file in the actual folder where the track resides, which ends up as the actual track with amended tag(s)
delete original track
rename the tmp file with the original track name.
I posted the relevant pieces of code
public class MP3File extends MediaFile
// create temporary file to work with
try
{
oTmpFileSource = m_oFileSource.createTempFile("id3.", ".tmp");
}
catch (Exception e)
{
throw new ID3Exception("Unable to create temporary file.", e);
}
m_oFileSource.delete();
oTmpFileSource.renameTo(m_oFileSource);
public class FileSource implements IFileSource
public IFileSource createTempFile(String sPrefix, String sSuffix)
throws IOException
{
File oTmpFile = File.createTempFile("id3.", ".tmp", m_oFile.getAbsoluteFile().getParentFile());
return new FileSource(oTmpFile);
}
public boolean delete()
{
return m_oFile.delete();
}
public boolean renameTo(IFileSource oFileSource)
throws IOException
{
if ( ! (oFileSource instanceof FileSource))
{
throw new IOException("Cannot rename between different file source types.");
}
return m_oFile.renameTo(((FileSource)oFileSource).m_oFile);
}
I have a Xamarin Forms project in which I need the user to be able to "load" an image. I can already press a button and search for a file using FilePicker like this:
async void OnUpload(object sender, EventArgs e)
{
try
{
FileData filedata = await CrossFilePicker.Current.PickFile();
// the dataarray of the file will be found in filedata.DataArray
// file name will be found in filedata.FileName;
//etc etc.
}
catch (Exception ex)
{
}
}
What I would need now is to copy that "filedata" (the image) to the resource folder of the project in order to access to the file easily. I have tried:
await CrossFilePicker.Current.SaveFile(filedata.FileName);
but it doesn't save any file into the project folder.
Moreover, I only need it to work on UWP and Android.
The SaveFile method saves it in a very specific folder.
If you want to save it somewhere of your choosing you have to implement it with the DependencyService. IO operations are very specific to the OS, so are the filepaths. I will give you a simple example for you to build on.
Start with defining an interface in your shared code, like so:
public interface IFileManager
{
void SaveFile(Stream stream);
}
Of course, it can have other methods as well, or extra parameters if you would like to specify things like filename, that is up to you. You would also probably like some kind of return value to know what happened.
Now, per platform implement this interface. For example for Android, it could look like this:
[assembly: Xamarin.Forms.Dependency (typeof (FileManager_Android))]
public class FileManager_Android : IFileManager
{
public void SaveFile(Stream stream)
{
var dir = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDcim);
string filename = System.DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".jpg";
string filePath = System.IO.Path.Combine(dir, name);
try
{
System.IO.File.WriteAllBytes(filePath, imageData);
}
catch (Exception ex)
{
System.Console.WriteLine(e.ToString());
}
}
}
(Saving code inspired by this link)
This will take the stream and save it to a path of your choosing.
For UWP you will need to implement it as well, which is quite similar, except for the implementation of SaveFile. As far as I know there is no plugin yet which makes this easier for you. There is PCLStorage, but this plugin only seems to work with text files. You could still look into it for inspiration though.
I'm using libGDX and face the problem that background music does not flawlessly loop on various Android devices (Nexus 7 running Lollipop for example). Whenever the track loops (i.e. jumps from the end to the start) a clearly noticeable gap is hearable. Now I wonder how the background music can be played in a loop without the disturbing gap?
I've already tried various approaches like:
Ensuring the number of Samples in the track are an exact multiple of the tracks sample rate (as mentioned somewhere here on SO).
Various audio formats like .ogg, .m4a, .mp3 and .wav (.ogg seems to be the solution of choice here at SO, but unfortunately it does not work in my case).
Used Androids MediaPlayer with setLooping(true) instead of libGDX Music class.
Used Androids MediaPlayer.setNextMediaPlayer(). The code looks like the following, and it plays the two tracks without a gap in between, but unfortunately, as soon as the second MediaPlayer finishes, the first does not start again!
/* initialization */
afd = context.getAssets().openFd(filename);
firstBackgroundMusic.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
firstBackgroundMusic.prepare();
firstBackgroundMusic.setOnCompletionListener(this);
secondBackgroundMusic.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
secondBackgroundMusic.prepare();
secondBackgroundMusic.setOnCompletionListener(this);
firstBackgroundMusic.setNextMediaPlayer(secondBackgroundMusic);
secondBackgroundMusic.setNextMediaPlayer(firstBackgroundMusic);
firstBackgroundMusic.start();
#Override
public void onCompletion(MediaPlayer mp) {
mp.stop();
try {
mp.prepare();
} catch (IOException e) { e.printStackTrace(); }
}
Any ideas what's wrong with the code snippet?
Just for the records:
It tuned out to be unsolvable. At the end, we looped the background music various times inside the file. This way the gap appears less frequently. It's no real solution to the problem, but the best workaround we could find.
This is an old question but I will give my solution in case anyone has the same problem.
The solution requires the use of the Audio-extension(deprecated but works just fine),if you cant find the link online here are the jars that I am using, also requires some external storage space.
The abstract is the following
Extract the raw music data with a decoder(VorbisDecoder class for ogg or Mpg123Decoder for mp3)and save them to the external storage(you can make a check to see if it already exists so that it only needs to be extracted once, cause it takes some time).
Create a RandomAccessFile using the file you just saved to the external storage
While playing set the RandomAccessFile pointer to the correct spot in the file and read a data segment
Play the above data segment with the AudioDevice class
Here is some code
Extract the music file and save it to the external storage,file is the FileHandle of the internal music file,here is an ogg and thats why we use VorbisDecoder
FileHandle external=Gdx.files.external("data/com.package.name/music/"+file.name());
file.copyTo(external);
VorbisDecoder decoder = new VorbisDecoder(external);
FileHandle extreactedDataFile=Gdx.files.external("data/com.package.name/music/"+file.nameWithoutExtension()+".mdata");
if(extreactedDataFile.exists())extreactedDataFile.delete();
ShortBuffer sbuffer=ByteBuffer.wrap(shortBytes).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer();
while(true){
if(LogoScreen.shouldBreakMusicLoad)break;
int num=decoder.readSamples(samples, 0,samples.length);
sbuffer.put(samples,0,num);
sbuffer.position(0);
extreactedDataFile.writeBytes(shortBytes,0,num*2, true);
if(num<=0)break;
}
external.delete();
Create an RandomAccessFile pointing to the file we just created
if(extreactedDataFile.exists()){
try {
raf=new RandomAccessFile(Gdx.files.external(extreactedDataFile.path()).file(), "r");
raf.seek(0);
} catch (Exception e) {
e.printStackTrace();
}
}
Create a Buffer so we can translate the bytes read from the file to a short array that gets feeded to the AudioDevice
public byte[] rafbufferBytes=new byte[length*2];
public short[] rafbuffer=new short[length];
public ShortBuffer sBuffer=ByteBuffer.wrap(rafbufferBytes).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer();
When we want to play the file we create an AudioDevice and a new thread where we read constantly read from the raf file and feed it to the AudioDevice
device = Gdx.audio.newAudioDevice((int)rate/*the hrz of the music e.g 44100*/,isthemusicMONO?);
currentBytes=0;//set the file to the beggining
playbackThread = new Thread(new Runnable() {
#Override
public synchronized void run() {
while (playing) {
if(raf!=null){
int length=raf.read(rafbufferBytes);
if(length<=0){
ocl.onCompletion(DecodedMusic.this);
length=raf.read(rafbufferBytes);
}
sBuffer.get(rafbuffer);
sBuffer.position(0);
if(length>20){
try{
device.writeSamples(rafbuffer,0,length/2);
fft.spectrum(rafbuffer, spectrum);
currentBytes+=length;
}catch(com.badlogic.gdx.utils.GdxRuntimeException ex){
ex.printStackTrace();
device = Gdx.audio.newAudioDevice((int)(rate),MusicPlayer.mono);
}
}
}
}
}
});
playbackThread.setDaemon(true);
playbackThread.start();
And when we want to seek at a position
public void seek(float pos){
currentBytes=(int) (rate*pos);
try {
raf.seek(currentBytes*4);
} catch (IOException e) {
e.printStackTrace();
}
}