File download on button click? - android

So im new to android development and i have been going about everything in a trial and error manner with a lot of searching a long the way. My question is: I have a button that I want to link to a exert of code that will start a download from a particular site. my code is as follows.
public void Download(View Button) {
public void DownloadFromUrl(){
try {
URL url = new URL("www.generic-site.html");
HttpURLConnection c = (HttpURLConnection)
url.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
String Path = Environment.getExternalStorageDirectory()
+"/download/";
Log.v("PortfolioManger", "PATH: "+Path);
File file = new File(Path);
file.mkdirs();
FileOutputStream fos = new FileOutputStream("site.html");
InputStream is = c.getInputStream();
byte[] buffer = new byte[702];
int len1 = 0;
while ((len1 = is.read(buffer)) != -1) {
fos.write(buffer, 0, len1);
}
fos.close();
is.close();
} catch (IOException e) {
Log.d("PortfolioManger", "Error: "+e);
}
Log.v("PortfolioManger", "Check: ");
}
What I was attempting to do was use the "public void Download(View Button)" command to launch the download, however im getting the errors:
Multiple markers at this line
- Syntax error, insert "EnumBody" to complete BlockStatements
- Syntax error on token "void", # expected
- Syntax error, insert "enum Identifier" to complete
EnumHeaderName" error under "Public void DownloadFromUrl()
I know its probably a silly question but can anyone shed some light?

You can't place one function inside another function
public void Download(View Button) {
public void DownloadFromUrl(){

You really need to sort out your Java syntax, but for now, this will work, assuming that you put in a correct url (I was not able to test as you used a demo url):
public class DownloadExampleActivity extends Activity {
/** Called when the activity is first created. */
Button button;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button = (Button) findViewById(R.id.download_button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
DownloadFromUrl();
}
});
}
public void DownloadFromUrl() {
try {
URL url = new URL("www.generic-site.html");
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
String Path = Environment.getExternalStorageDirectory() + "/download/";
Log.v("PortfolioManger", "PATH: " + Path);
File file = new File(Path);
file.mkdirs();
FileOutputStream fos = new FileOutputStream("site.html");
InputStream is = c.getInputStream();
byte[] buffer = new byte[702];
int len1 = 0;
while ((len1 = is.read(buffer)) != -1) {
fos.write(buffer, 0, len1);
}
fos.close();
is.close();
} catch (IOException e) {
Log.d("PortfolioManger", "Error: " + e);
}
Log.v("PortfolioManger", "Check: ");
}
}

#mibollma is right, you are actually not respecting the structure of classes in java.
A class file in java
- must contain one and only one public class
- the name of this class and the name of the file must match
there can be others classes, but either not public or inner classes like
//in A.java
public class A
{
public class B
{}//inner class B
}//class A
class C
{}//class C
In a class, you are allowed to use
- data member definitions
- inner class definitions (see above, so yes this structure is recursive / fractal)
- methods
like in
public class A
{
//data member
int a = 0;
//other data member, static and private, why not
private static String b = "toto";
//methods
private void met( int b )
{}//met
//...
}//class A
This is the big picture. And inside a method you can't add anything but instructions. No method nesting is allowed. Note that those examples don't talk about anonymous inner classes, it's a bit more advanced.
Please also take some time to review java naming conventions, your code doesn't respect naming standards, it's harder to follow.
Regards,
stéphane

Related

Writing an audio file to websocket using IBM Watson Android sdk

I realized after going through a post in the IBM developer forums that the android sdk reads bytes from the mic recording and writes them to the websocket. I am now trying to read bytes from an audio file on memory and write them to the websocket. How should I do this? So far I have:
public class AudioCaptureThread extends Thread{
private static final String TAG = "AudioCaptureThread";
private boolean mStop = false;
private boolean mStopped = false;
private int mSamplingRate = -1;
private IAudioConsumer mIAudioConsumer = null;
// the thread receives high priority because it needs to do real time audio capture
// THREAD_PRIORITY_URGENT_AUDIO = "Standard priority of the most important audio threads"
public AudioCaptureThread(int iSamplingRate, IAudioConsumer IAudioConsumer) {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
mSamplingRate = iSamplingRate;
mIAudioConsumer = IAudioConsumer;
}
// once the thread is started it runs nonstop until it is stopped from the outside
#Override
public void run() {
File path = Activity.getContext.getExternalFilesDir(null);
File file = new File (path, "whatstheweatherlike.wav");
int length = (int) file.length();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[length];
FileInputStream in = null;
try {
in = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
for (int readNum; (readNum = in.read(b)) != -1;) {
bos.write(b, 0, readNum);
}
} catch (IOException e) {
e.printStackTrace();
}
byte[] bytes = bos.toByteArray();
mIAudioConsumer.consume(bytes);
}
However, Activity.getContext is not recognized. I can convert the file to bytes in MainActivity but how do I then write it to the websocket? Am I on the right track or is this not the right way? If it is, how do I solve this problem?
Any help is appreciated!
Activity.getContext is not recognized because there's no reference to Activity, since it's just a Thread. You would have to pass in the Activity, although it would likely make more sense just to pass in the Context if you need it.
You've got the right idea that you can create a FileInputStream and use that. You might like to use our MicrophoneCaptureThread as a reference. It'd be a very similar situation, except you'd be using your FileInputStream instead of reading from the microphone. You can check it out (and an example project that uses it) here: https://github.com/watson-developer-cloud/android-sdk/blob/master/library/src/main/java/com/ibm/watson/developer_cloud/android/library/audio/MicrophoneCaptureThread.java

How to listen for an activity and change a setting

I want to write a simple android application that listens for a command such as long press menu button or press home button 3 times and then changes value in /sys/class/mdnie/mdnie/negative to 1 or 0. I have no idea where to begin, I know modifying this value requires root access and I can successfully do this by echo > 1 /sys/class/mdnie/mdnie/negative
Any guidance is appreciated, I need this for a friend who is visually impaired. This application will toggle negative colors for himon some samsung devices and he would like to press the home key 3 times to toggle the negative colors on and off from anywhere on the device.
It shouldn't be difficult. It would be an activity with no associated display that toggles the value and finishes immediately afterwards. The code would look like this (not it is untested code - if you face issues, post them as new StackOverflow questions different from this one):
public class ToggleNegativeColorsActivity extends Activity {
private static final String FILEPATH = "/sys/class/mdnie/mdnie/negative";
#Override
public void onCreate(Bundle savedInstanceState) {
super(savedInstanceState);
try {
String value = readFileAsString(FILEPATH);
if ("1".equals(value.trim())) {
writeStringToFile(FILEPATH, "0");
} else {
writeStringToFile(FILEPATH, "1");
}
catch (IOException e) {
e.printStackTrace();
}
finish();
}
// Grabbed from http://stackoverflow.com/questions/1656797/how-to-read-a-file-into-string-in-java
private String readFileAsString(String filePath) throws IOException {
StringBuffer fileData = new StringBuffer();
BufferedReader reader = new BufferedReader(
new FileReader(filePath));
char[] buf = new char[1024];
int numRead;
while((numRead=reader.read(buf)) != -1){
String readData = String.valueOf(buf, 0, numRead);
fileData.append(readData);
}
reader.close();
return fileData.toString();
}
// Grabbed from http://stackoverflow.com/questions/1053467/how-do-i-save-a-string-to-a-text-file-using-java
private void writeStringToFile(String filePath, String value) throws IOException {
PrintWriter out = new PrintWriter(filePath);
out.print(value);
out.close();
}
}

Need help debugging my code

I need some input about my code.
Basically, I have a method to load music from Class A
public void onListItemClick(ListView parent, View v, int position, long id){
musicIndex = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
cursor.moveToPosition(position);
filePath = cursor.getString(musicIndex);
fileName = new File(filePath).getName();
playMusic();//Play the selected music
}
public void playMusic(){
if(mPlayer.isPlaying()){
mPlayer.reset();
}
try{
mPlayer.setDataSource(filePath);
mPlayer.prepare();
mPlayer.start();
BeatDetection beatDetect = new BeatDetection();
beatDetect.init();
}catch (Exception e){
}
}
That method will call the init() method in Class B
public void init() throws Exception{
energy = 0;
variance = 0;
constant = 0;
isBeat = false;
sensitivity = 0;
dBuffer = new float[sampleRate / bufferSize];
eBuffer = new float[sampleRate / bufferSize];
timer = System.currentTimeMillis();
MusicLoad msc = new MusicLoad();
totalMs = 0;
seeking = true;
//msc.printText();
decode(msc.fileName, 25, 40);
}
In that method, it initializes everything and call the decode() method
public void decode(String path, int startMs, int maxMs)
throws IOException, javazoom.jl.decoder.DecoderException {
debug();
File in = new File(path);
InputStream inStream = new BufferedInputStream(new FileInputStream(in), 8 * 1024);
ByteArrayOutputStream outStream = new ByteArrayOutputStream(1024);
try {
Bitstream bitstream = new Bitstream(inStream);
Decoder decoder = new Decoder();
boolean done = false;
while (! done) {
Header frameHeader = bitstream.readFrame();
if (frameHeader == null) {
done = true;
} else {
totalMs += frameHeader.ms_per_frame();
if (totalMs >= startMs) {
seeking = false;
}
if (! seeking) {
SampleBuffer output = (SampleBuffer) decoder.decodeFrame(frameHeader, bitstream);
if (output.getSampleFrequency() != 44100 || output.getChannelCount() != 2) {
throw new javazoom.jl.decoder.DecoderException("mono or non-44100 MP3 not supported", null);
}
short[] pcm = output.getBuffer();
for (short s : pcm) {
outStream.write(s & 0xff);
outStream.write((s >> 8 ) & 0xff);
}
}
if (totalMs >= (startMs + maxMs)) {
done = true;
}
}
bitstream.closeFrame();
}
byte[] abAudioData = outStream.toByteArray();
calculation(abAudioData);
} catch (BitstreamException e) {
throw new IOException("Bitstream error: " + e);
} catch (DecoderException e) {
Log.w("Decoder error", e);
throw new javazoom.jl.decoder.DecoderException("Error",e);
} finally {
inStream.close();
}
}
Don't mind reading all the code lines. If you guys notice I put debug() in the beginning to see whether the method is called or not. At this point, the debug() is properly called. However, if I put the debug() after the line File in = new File(path);, the debug() will not be called anymore. It seems like the code is stop running at that point.
The ultimate result is, I can load and play the song without any problem. However, the decode() is not called and there is no error whatsoever. I'm stuck at pointing out the problem at this point. So if there's any input please help me.
EDIT: After I tried tracing the "path" variable, it returns NULL so the error is NullPointerException. Seems like the "fileName" variable from Class A is not passed to Class B. Any suggestion?
If you are using Eclipse with ADT then it's very easy to debug your Android apps, just add a breakpoint (probably in the new File(...) line) and see what happens.
My guess here is that File in = new File(path); probably is throwing a IOException in your decode method, that exception is bubbling first to init() and then to playMusic(), where it is caught by try catch block. Your catch is empty so you are not seeing anything. Try debugging as I said or add some logging info in the catch block.
This is just something to look at, but from the doc page
http://developer.android.com/reference/java/io/File.html#File%28java.lang.String%29
"The actual file referenced by a File may or may not exist. It may also, despite the name File, be a directory or other non-regular file."
If you had the path wrong, it may be trying to create the file and you may not have the correct permission to do so. Perhaps: WRITE_EXTERNAL_STORAGE.
I know this post is old, but I just wanted to show how to get the file path to read/write files for others that come across this post as I have:
String filePath = myContext.getFilesDir().getPath().toString() + "/sysout.log";
File file = new File(filePath);
These two lines will create (open if it exists, and overwrite) a file named "sysout.log" in the folder /data/data/com.app.name/files/; myContext is just the current context. Using this technique alleviates problems with defining your own path name. Hope this helps someone.

Simultaneous downloads result in corrupted files

I'm downloading sets of images in separated threads and saving them to the SD card. The problem is that when I run two or more downloading threads the saved images are corrupted. If just one thread is running the images are ok. I'm downloading it from the same domain but different url, e.g. www.test.com/set1/img1.jpg, www.test.com/set2/img1.jpg etc.
I'm saving them to different folders by the name of the set. I noticed that mostly larger images are corrupted (over 500 KB), smaller are usually ok, but not always.
Do you have any clue why the files get corrupted when multiple threads are running?
Here's a part of the code I'm using:
protected class DownloadTask extends DownloadRunnable {
#Override
public void run() {
InputStream is = null;
OutputStream os = null;
File bitmapFile = null;
/** some more declarations and preparations are here */
for (int pg=getDownloadedPages(); pg < numPages; ++pg) {
for (char ch='a'; ch <= 'e'; ++ch) {
/* check for pause */
synchronized (pauseLock) {
while (paused && !aborted) {
try {
pauseLock.wait();
} catch (InterruptedException e) {
}
}
}
fileName = "page-" + df.format(pg) + "-" + ch;
url = MainApp.getRestrictedUrl(MainApp.tstcode, urlFile + fileName+ ".jpg");
is = new BufferedInputStream(new URL(url).openStream());
if(android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
bitmapFile = new File(pathToSave, fileName + MagazinePage.FILE_EXT);
MainApp.encryptToFile(bitmapFile, is);
dwnlSize += bitmapFile.length();
}
is.close();
}
}
}
public static void encryptToFile(File file, InputStream is) throws IOException {
BufferedOutputStream os = null;
try {
if (file.exists()) {
file.delete();
} else {
file.getParentFile().mkdirs();
}
file.createNewFile();
os = new BufferedOutputStream(new FileOutputStream(file));
IkioskContentProvider.getInstance().encrypt(is, os);
} finally {
os.close();
}
}
}
DownloadRunnable is custom abstract class implementing Runnable. And I'm using it in thread the regular way:
protected void downloadIssuePages() {
dwnlTask = new DownloadTask();
new Thread(dwnlTask).start();
}
I'm calling downloadIssuePages() on two different objects to download two sets for example.
Using SDK version 11 (Android 3.0), device Acer Iconia Tab A500 with Android 3.1
I've tried to disable writing for the second thread, only the first thread was saving files to find out if there's a problem in reading from the stream or writing. Apparently writing was the problem as data was correct in this case.
So I decided to use lock around writing to the file and looks like it's working fine:
synchronized (MainApp.fileWritingLockObj) {
while (MainApp.fileWritingLocked) {
try {
MainApp.fileWritingLockObj.wait();
} catch (InterruptedException e) {
}
}
MainApp.fileWritingLocked = true;
if(android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
bitmapFile = new File(pathToSave, fileName + MagazinePage.FILE_EXT);
MainApp.encryptToFile(bitmapFile, is);
dwnlSize += bitmapFile.length();
}
is.close();
MainApp.fileWritingLocked = false;
MainApp.fileWritingLockObj.notifyAll();
}

dalvik.system.PathClassLoader not loading multiple JARs

I am attempting to load a set of JAR files that go together to make up an API. For some reason I can only load classes not dependent on definitions in other JARs. I am beginning to suspect that the Android classloaders simply do not handle implementing an interface from one JAR file in another. For this reason I've also unpacked the classes into a common dir however this doesn't work either.
Please see the following code. Apologies for any anomalies, but I've tried to ensure it will compile straight up if pasted into an ADT project called MyProj.
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
import dalvik.system.PathClassLoader;
import android.content.Context;
// IPluginSource simply defines the method here at the top.
public class AndroidPluginSource implements IPluginSource
{
#Override
public void doSearching(ArrayList<ClassLoader> classLoaders, ArrayList<String> classNames)
{
String jarPaths = "";
// For each of the raw resources, JARs compiled into the 'res/raw' dir...
for (Field str : R.raw.class.getFields())
{
String resName = str.getName();
Logger.log(Level.FINE, "Resource: " + str);
try
{
// Copy the JAR file to the local FS.
InputStream is = MyProj.self.getResources().openRawResource(str.getInt(this));
OutputStream os = MyProj.self.openFileOutput(resName + ".jar", Context.MODE_PRIVATE);
copyData(is, os);
is.close();
os.close();
// Get JAR location.
String jarLoc = MyProj.self.getFilesDir() + File.separator + resName + ".jar";
// First attempt is just single classloaders, so we aren't suprised this won't work.
classLoaders.add(new PathClassLoader(jarLoc, MyProj.self.getClassLoader()));
//Logger.log(Level.FINE, " LOC: " + jarLoc);
// Keep running list of JAR paths, will that work?
if (jarPaths.length() > 0) jarPaths += File.pathSeparator;
jarPaths += jarLoc;
// We have to go through the JARs to get class names...
JarFile jar = new JarFile(jarLoc);
Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements())
{
JarEntry entry = entries.nextElement();
String entryName = entry.getName();
if (entryName.endsWith(".class"))
{
classNames.add(toClassName(entryName));
Logger.log(Level.FINE, " ENT: " + entryName);
// ...while we're here lets get the class out as a file.
String classLoc = MyProj.self.getFilesDir() + File.separator + entryName;
Logger.log(Level.FINER, " CLS: " + classLoc);
File classFile = new File(classLoc);
classFile.delete();
classFile.getParentFile().mkdirs();
InputStream jis = jar.getInputStream(entry);
//OutputStream jos = MyProj.self.openFileOutput(classLoc, Context.MODE_PRIVATE);
OutputStream jos = new FileOutputStream(classFile);
copyData(jis, jos);
jos.close();
jis.close();
}
}
}
catch (Exception ex)
{
Logger.log(Level.SEVERE, "Failed plugin search", ex);
}
}
File f = MyProj.self.getFilesDir();
recursiveList(f, 0);
// So we have a class loader loading classes...
PathClassLoader cl = new PathClassLoader(VermilionAndroid.self.getFilesDir().getAbsolutePath(), ClassLoader.getSystemClassLoader());
classLoaders.add(cl);
// A JAR loader loading all the JARs...
PathClassLoader jl = new PathClassLoader(jarPaths, ClassLoader.getSystemClassLoader());
classLoaders.add(jl);
// And if edited as below we also have a DexLoader and URLClassLoader.
}
// This is just so we can check the classes were all unpacked together.
private void recursiveList(File f, int indent)
{
StringBuilder sb = new StringBuilder();
for (int x = 0; x < indent; x++) sb.append(" ");
sb.append(f.toString());
Logger.log(Level.INFO, sb.toString());
File[] subs = f.listFiles();
if (subs != null)
{
for (File g : subs) recursiveList(g, indent+4);
}
}
// Android helper copy file function.
private void copyData(InputStream is, OutputStream os)
{
try
{
int bytesRead = 1;
byte[] buffer = new byte[4096];
while (bytesRead > 0)
{
bytesRead = is.read(buffer);
if (bytesRead > 0) os.write(buffer, 0, bytesRead);
}
}
catch (Exception ex) {}
}
// Goes from a file name or JAR entry name to a full classname.
private static String toClassName(String fileName)
{
// The JAR entry always has the directories as "/".
String className = fileName.replace(".class", "").replace(File.separatorChar, '.').replace('/', '.');
return className;
}
}
The following code is where this is called from.
public void enumeratePlugins(IPluginSource source)
{
ArrayList<ClassLoader> classLoaders = new ArrayList<ClassLoader>();
ArrayList<String> classNames = new ArrayList<String>();
source.doSearching(classLoaders, classNames);
logger.log(Level.FINE, "Trying discovered classes");
logger.log(Level.INFO, "Listing plugins...");
StringBuilder sb = new StringBuilder();
// Try to load the classes we found.
for (String className : classNames)
{
//boolean loadedOK = false;
Throwable lastEx = null;
for (int x = 0; x < classLoaders.size(); x++)
{
ClassLoader classLoader = classLoaders.get(x);
try
{
Class dynamic = classLoader.loadClass(className);
if(PluginClassBase.class.isAssignableFrom(dynamic) &&
!dynamic.isInterface() && !Modifier.isAbstract(dynamic.getModifiers()))
{
PluginClassBase obj = (PluginClassBase) dynamic.newInstance();
String classType = obj.getType();
String typeName = obj.getName();
classes.put(typeName, new PluginClassDef(typeName, classType, dynamic));
logger.log(Level.FINE, "Loaded plugin: {0}, classType: {1}", new Object[] {typeName, classType});
sb.append(typeName).append(" [").append(classType).append("], ");
if (sb.length() > 70)
{
logger.log(Level.INFO, sb.toString());
sb.setLength(0);
}
}
lastEx = null;
break;
}
catch (Throwable ex)
{
lastEx = ex;
}
}
if (lastEx != null)
{
logger.log(Level.INFO, "Plugin instantiation exception", lastEx);
}
}
if (sb.length() > 0)
{
logger.log(Level.INFO, sb.substring(0, sb.length()-2));
sb.setLength(0);
}
logger.log(Level.FINE, "Finished examining classes");
}
Thanks for your help.
EDIT: I have also tried adding
URLClassLoader ul = null;
try
{
URL[] contents = new URL[jarURLs.size()];
ul = new URLClassLoader(jarURLs.toArray(contents), ClassLoader.getSystemClassLoader());
}
catch (Exception e) {}
classLoaders.add(ul);
...which gives rise to a new exception - UnsupportedOperationException: Can't load this type of class file.
AND:
DexClassLoader dl = new DexClassLoader(jarPaths, "/tmp", null, getClass().getClassLoader());
classLoaders.add(dl);
Also didn't work correctly, but thanks for the suggestion Peter Knego
I should clarify that in the JAR files I have:
JAR1:
public interface IThing
public class ThingA implements IThing
JAR2:
public class ThingB implements IThing
I'm not entirely sure what you're trying to do, but I suspect what you want isn't supported by the Java language's definition of a class loader.
Class loaders are arranged in a hierarchy. If you ask class loader CL1 for a copy of class Foo, it will ask its parent if it knows what Foo is. That goes up the chain to the bootstrap loader, and as things fail it comes back down, until eventually CL1 gets a chance to go out and find a copy. (It doesn't have to work this way, and there's a test case that deliberately does it "wrong", but it's almost always done like this.)
Suppose CL1 does define Foo. Foo implements IBar, so when preparing that class the VM will ask CL1 to find IBar. The usual search is done.
If IBar is defined in CL2, and CL2 is not a parent of CL1, then nothing in CL1 will be able to see IBar.
So if you're creating a bunch of "peer" class loaders for various jar files, you can't directly reference classes between them.
This is not unique to Android.
If you create a single class loader and put the whole set of jars in the path, you can mix and match however you want.
There was no solution to this problem, I have so-far worked around it.

Categories

Resources