Android: Application closing unexpectedly - android

I have an activity with a listview that displays the products registered with the images of the SDCARD. Some users are reporting that they receive the error "The application closed" while on this activity.
I've done all the tests to try to simulate it, and the error did not occur.
I thought it might be something with the device memory or something.

Here's a class I developed long ago for catching errors in a jar file I had distributed to several friends. It catches output to std out and stderr and writes it to a file.
If your users can use a file manager to find the file that is written they could send it to you. I've done some preliminary testing on an app and it worked for me.
if you use it and have problems, please let me know.
package com.normstools;
import java.io.*;
//------------------------------------------------------------------------
public class SaveStdOutput extends PrintStream {
final static boolean debug = false; // controls debug output
static OutputStream logfile;
static PrintStream oldStdout = null;
static PrintStream oldStderr = null;
private boolean echoOutput = true; //Also output to old setting
// Constructor - we're the only one that can use it!
private SaveStdOutput(PrintStream ps, boolean echoOutput) {
super(ps);
this.echoOutput = echoOutput;
// System.out.println("SaveStdOutput constructor called");
} // end Constructor
//------------------------------------------------------------
// Starts copying stdout and stderr to the file f.
public static void start(String f) throws IOException {
// Create/Open logfile.
OutputStream os = new PrintStream(
new BufferedOutputStream(
new FileOutputStream(f, true))); // append to current
doCommon(os, true);
} // end start()
// Copy STDOUT and STDERR to an output stream
public static void start(OutputStream os) {
doCommon(os, true);
} // end start()
public static void start(OutputStream os, boolean eO) {
doCommon(os, eO);
} // end start()
//-------------------------------------------------------
// Finish up
private static void doCommon(OutputStream os, boolean echoOutput) {
// Only allow to be called once
if (oldStdout != null) {
if (debug)
System.err.println("SaveStdOutput start() called twice");
return; // Exit if already open
}
logfile = os;
// Save old settings.
oldStdout = System.out;
oldStderr = System.err;
// Start redirecting the output.
System.setOut(new SaveStdOutput(System.out, echoOutput));
System.setErr(new SaveStdOutput(System.err, echoOutput));
} // end doCommon()
//--------------------------------------
// Restores the original settings.
public static void stop() {
if (oldStdout == null) {
if (debug)
System.err.println("SaveStdOutput stop() called before start()");
return;
}
System.setOut(oldStdout);
oldStdout = null; //Clear
System.setErr(oldStderr);
try {
logfile.close();
} catch (Exception ex) {
System.err.println("SaveStdOutput stop() ex " + ex.getMessage());
ex.printStackTrace();
}
} // end stop()
// Override the PrintStream write methods
public void write(int b) {
try {
logfile.write(b);
} catch (Exception e) {
e.printStackTrace();
setError();
}
if (echoOutput)
super.write(b);
} // end write()
// PrintStream override.
public void write(byte buf[], int off, int len) {
try {
logfile.write(buf, off, len);
} catch (Exception e) {
e.printStackTrace();
setError();
}
if (echoOutput)
super.write(buf, off, len);
} // end write()
//-------------------------------------------------------------------
// Following for testing SaveStdOutput class: Comment out when done!
public static void main(String[] args) {
try {
// Start capturing characters into the log file.
SaveStdOutput.start("log.txt");
// Test it.
System.out.println("Here's is some stuff to stdout. "
+ new java.util.Date());
System.err.println("Here's is some stuff to stderr.");
System.out.println("Let's throw an exception...");
new Exception().printStackTrace();
throw new Exception("this is thrown");
} catch (Exception e) {
e.printStackTrace();
} finally {
// Stop capturing characters into the log file
// and restore old setup.
SaveStdOutput.stop();
}
System.out.println("This should be to console only!");
} // end main() */
} // end class SaveStdOutput
The main() method has sample usage.
Call the start() method in onStart() and the close() method in onStop(),
or add menu items to control it. Add a few calls to System.out.println()
and some try{}catch blocks with printStackTrace().

Error "The application closed" occurs most of the time when Android detects your application is not loading or responding within 3-5 Seconds, you should try to check the availability of the SD card, space available, permission or even run some of the process in the background. Rewrite your code to handle these situations and it should work.

Related

Send continuous bluetooth stream from Android to Arduino

I'm working on a simple vehicle project, made with Arduino Uno and controlled by an Android App.
My matter is to send continuous stream from the app to my bluetooth module (HC-06) on Arduino.
I did it with onTouch events and a new thread called from my main activity, but something is obviously wrong because the app seems to send each command as i want it to do, but the Arduino waits until the finger is off the button and receives all data (from action.down to action.up) at a time.
To understand :
I update a small string like this "1255090" each time a command button is action.down or action_move, convert it to bytes and send it via bluetooth.
If i briefly click on the button, Arduino will receive the correct string "1255090", but if i maintain my finger on the button, Arduino waits for the string, and when i release the button, Arduino receives for example "125509012540901253090125209012510901252090" (depending on how long i clicked).
Android activity (partial)
drive.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent m) {
if (m.getAction() != MotionEvent.ACTION_UP) {
accelerer(); // inscreases the speed
str_flux(); // constructs the string
byte[] bytes = new byte[0];
try { bytes = flux.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); }
sendReceiveBT.write(bytes); // calls the thread's method
} else{ralentir();}
return true;
}
});
Thread
package com.*.vehicle.util;
import android.bluetooth.BluetoothSocket;
import android.util.Log;
import java.io.IOException;
import java.io.OutputStream;
public class SendReceiveBytes implements Runnable {
private BluetoothSocket btSocket;
private OutputStream btOutputStream = null;
String TAG = "SendReceiveBytes";
public SendReceiveBytes(BluetoothSocket socket) {
btSocket = socket;
try { btOutputStream = btSocket.getOutputStream(); } catch (IOException streamError) { Log.e(TAG, "Error when getting input or output Stream"); }
}
public void run() {
byte[] buffer = new byte[1024];
int bytes;
}
public void write(byte[] bytes) {
try {
btOutputStream.write(bytes); // Send the bytes to Arduino
btOutputStream.flush(); // don't know if it really does something...
Log.e(TAG, "SUCCESS !");
}
catch (IOException e) {
Log.e(TAG, "Error when writing to btOutputStream");
}
}
}
Arduino loop
void loop() {
s = Serial.readString(); // 1255090
if (s!=""){
Serial.println(s);
bt_direction = s.substring(0,1).toInt();
bt_speed = s.substring(1,4).toInt();
bt_angle = s.substring(4,7).toInt();
s = "";
} else{
if (bt_speed>0){
for(int i=bt_speed;i>=0;i--){bt_speed--;}
}
else{ bt_speed = 0; }
}
if (bt_direction==1){bt_dir = true;} else{bt_dir = false;}
if (bt_speed==0){stop_motor();} else{dc_motor(bt_speed, bt_dir);}
Serial.println(bt_direction);
servo_turn(bt_angle);
}
If I am getting you correctly, you can easily handle it using multiple states.
For example,
State1: 123456: is for tap,
State2: 123457: is for press & hold,
State3: 123458: is for release,
And so on.
And in you ui detect whether user is tapping or press and hold.
If press and hold , instruct arduino to do something until receives release.
In this way you can even handle the situation without continuously sending bit, And as per my understanding you don't need this.
Correct me if I am wrong.
Thanks !!!

DataOutputStream throws IOException when i exec shell commands second time in android

My problem is how get root access once while app start in android.The first time i run this code,it's very correct.But the second time i run this code,it throws a IOException.
I init process with root access in onCreate()
#Override
public void onCreate() {
super.onCreate();
// get root access
try {
process = Runtime.getRuntime().exec("su");
} catch (IOException e) {
e.printStackTrace();
}
}
then,i execute shell with this method.
/**
* execute Shell commands
*
* #param commands
* the commands to execute
*/
public static void execShell(String[] commands) {
DataOutputStream os = null;
try {
// get DataOutputStream
os = new DataOutputStream(
process.getOutputStream());
for (String command : commands) {
if (command == null) {
continue;
}
// donnot use os.writeBytes(commmand), avoid chinese charset
// error
// The first time i run this code,it's very correct.But the
// second time i run this code,it throws a IOException
os.write(command.getBytes());
os.writeBytes("\n");
os.flush();
}
//exit
os.writeBytes("exit\n");
os.flush();
//wait process complete
process.waitFor();
} catch (Exception e) {
e.printStackTrace();
} finally {
//close os
}
}
how to avoid IOException?this is my first time to ask question in stackoverflow,so tried!Because my english is very poor

cordova 3.0 FileWriter THREAD WARNING: exec() call to File.write blocked the main thread...should use CordovaInterface.getThreadPool()

I'm using the FileWriter and it works fine except for these messages in the logcat when I write largish files of various sizes upto about 3MB.
I had a look at the FileUtils.java source and the write function doesn't use the getThreadPool() interface (the reader does).
As a test I thought I'd adapt the filewriter to use the runnable interface and was able to get the code to compile and execute - unfortunately the logcat messages still show up...
The blocking times I get are anything between 25ms and 1200ms so far. I haven't run any serious comparison tests to determine if this change makes any real difference - I was just looking for the absence of logcat messages.
Would these changes as below make any real difference?
Are these message something I should worry about?
My java is pretty basic - but here are the changes I made - following the reader implementation.
else if (action.equals("write")) {
this.write(args.getString(0), args.getString(1), args.getInt(2), args.getBoolean(3), callbackContext);
}
/* this is the original code
else if (action.equals("write")) {
long fileSize = this.write(args.getString(0), args.getString(1), args.getInt(2), args.getBoolean(3));
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, fileSize));
}
*/
And in the write function as below...
public void write(String filename, final String data, final int offset, final boolean isBinary, final CallbackContext callbackContext) throws FileNotFoundException, IOException, NoModificationAllowedException {
if (filename.startsWith("content://")) {
throw new NoModificationAllowedException("Couldn't write to file given its content URI");
}
final String fname = FileHelper.getRealPath(filename, cordova);
this.cordova.getThreadPool().execute(new Runnable() {
public void run() {
Log.d(LOG_TAG, "Starting write");
try {
boolean append = false;
byte[] rawData;
if (isBinary) {
rawData = Base64.decode(data, Base64.DEFAULT);
} else {
rawData = data.getBytes();
}
ByteArrayInputStream in = new ByteArrayInputStream(rawData);
FileOutputStream out = new FileOutputStream(fname, append);
byte buff[] = new byte[rawData.length];
in.read(buff, 0, buff.length);
out.write(buff, 0, rawData.length);
out.flush();
out.close();
Log.d(LOG_TAG, "Ending write");
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, rawData.length));
} catch (IOException e) {
Log.d(LOG_TAG, e.getLocalizedMessage());
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, NOT_READABLE_ERR));
}
}
});
}
Yes, these messages are important and you should use background thread for complicated tasks, such as file writing. The reason of this problem is that these tasks are blocking cordova and you could experience for example UI lags.
If your next actions are dependent on this task being completed, I recommend you using callback method.

Android - ObjectInputStream keeps on reading the previous value even with .reset()

I'm building an application for sending files between two Android phones, now i have a ListActivity that retrieves the sdcard and lists the files, when the ListActivity first starts on the two devices a ServerSocket is set up and listening with .accept() ...
this thread starts when the ListActivity starts :
ReceiveFileSendRequestThread ReceiveFileSendRequestThread = new ReceiveFileSendRequestThread();
ReceiveFileSendRequestThread.start();
and here is the full thread class:
static public class ReceiveFileSendRequestThread extends Thread {
public void run() {
ServerSocket serverSocket;
try {
serverSocket = new ServerSocket(6789, 200);
connectionServ = serverSocket.accept();
requestFileInServer = new ObjectInputStream(
connectionServ.getInputStream());
requestFileString = (String) requestFileInServer.readObject();
handler.post(new AcceptFileSendAlertDialogRunnable());
while (okToSend == null) {
}
if (okToSend == true) {
requestFileOutServer = new ObjectOutputStream(
connectionServ.getOutputStream());
requestFileOutServer.writeObject("oktosend");
requestFileOutServer.flush();
serverSocket.close(); // // Receive File
} else if (okToSend == false) {
requestFileOutServer = new ObjectOutputStream(
connectionServ.getOutputStream());
requestFileOutServer.reset();
requestFileOutServer.writeObject("notosend");
requestFileOutServer.flush();
serverSocket.close();
ReceiveFileSendRequestThread ReceiveFileSendRequestThread = new ReceiveFileSendRequestThread();
ReceiveFileSendRequestThread.start();
}
} catch (IOException e) {
Log.d("Connection Error:", "Error binding port!");
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
And when onLongClick on an item (to send file) the following thread starts:
public boolean onItemLongClick(AdapterView<?> parentView, View childView,
int position, long id) {
// TODO Auto-generated method stub
fileClickedName = (((TextView) childView).getText()).toString();
fileClickedPath = file.toString() + "/" + fileClickedName;
fileClickedFile = new File(fileClickedPath);
SendFileThread SendFileThread = new SendFileThread();
SendFileThread.start();
return true;
}
SendFile Thread:
static public class SendFileThread extends Thread {
public void run() {
Socket socket = new Socket();
try {
socket.connect(new InetSocketAddress(sharedIp, 6789), 200);
requestFileOutClient = new ObjectOutputStream(
socket.getOutputStream());
requestFileOutClient.writeObject(fileClickedName);
requestFileOutClient.flush();
requestFileInClient = new ObjectInputStream(
socket.getInputStream());
toSendOrNot = (String) requestFileInClient.readObject();
if (toSendOrNot.equals("oktosend")) {
socket.close();
} else if (toSendOrNot.equals("notosend")) {
socket.close();
ReceiveFileSendRequestThread ReceiveFileSendRequestThread = new ReceiveFileSendRequestThread();
ReceiveFileSendRequestThread.start();
handler.post(new ClientFileSendAlertDialogRunnable());
}
// //
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Now, when I launch the ListActivity and longClick on an item, the the file name is sent to the second device, the second device pops up an alertDialog asking the user if to accept the file or not, (accepting file is still not ready for now) if the user presses on CANCEL (on the ReceiveFileSendRequestThread) a string is sent to the first device "notosend", the first user receives the string "notosend" and depending on that the thread closes the socket and re invoke the thread to listen to the second peer if he wants to send another file , AND pops up an alertDialog telling the first user that your file was refused to be received ... >>>> this is totally works >>>> but when the first device attempts to send another file (long press again on a file [item on the list] ) the second user receives the new file name selected by the first user successfully and alertDialog pops up if to accept or cancel BUT the first user receives that the file send was refused ... without having the second user pressing on the cancel button !!! ... i don't know why toSendOrNot = (String) requestFileInClient.readObject(); keeps on taking the previous value without even waiting for the second device to write the new object.
I would appreciate it if someone could help me with this , Many thanks.
AFTER HOURS OF DEBUGGING >>> I FINALLY FOUND THE BUG!
in thread ReceiveFileSendRequestThread() the Boolean variable okToSend is null when first receiving a request from the second device, when the second device cancels the request the oKtoSend will be set to notosend, so whenever the second device attempts to send another file the variable okToSend will always has the previously assigned value. So I simply added okToSend = null; before the while loop, and now is working perfectly.

commumicating between windows app and android app

I'm sorry if this is a very general question but I don't know where to start so I'm looking for ideas.
I have a windows app (music score editing) and I'm currently porting it to Andriod which is coming along well.
I would like to add the feature than documents created in the windows app can be sent to the users android tablet. I was wondering, how would I write some kind of listener on Android that the windows side could open a socket or something to and send data across to it, assuming both are on the same local network.
thanks
I think sending files directly over a local network isn't the best approach. You are prone to many user complaints that the sharing isn't working.. and this will mostly be due to their own network configuration issues.
Why not use a service like DropBox to implement file sharing?
Services like DropBox offer simple API that can be used in apps in order to save files into a remote folder, and read files from a remote folder.
This way, users will not have to be in the same network at all.. and most of the heavy-lifting of implementing file sharing will be done by a service that is focused around that.
Addition:
If you don't want to require an account for a separate service like DropBox, consider this approach: Implement a very simple DropBox-like service on your own web server. Make a simple script that will allow users to upload a file to your server anonymously via HTTP. After upload, they will receive a 5 digit id for this file, or some other link they could share. When using this id or link from the 2nd app, the file could be downloaded (again via HTTP). If you delete files automatically from the server after a few hours, you will not run out of space.
You can implement such a service with about 20 lines of PHP code. And the required apps code is extremely simple (since it only relies on HTTP). If you're worried about the costs of a web server, you can get one from about $5/month or even use a free service like Google App Engine (free if your bandwidth+space requirements are low).
Code example for the file upload. Downloading should be simple enough to do alone. Regarding the periodical file delete - the obvious approach is cron but I think it's easy to manage without it. Whenever you accept a new upload (in the PHP script), go over all the downloads and delete old ones.
i wrote a small thing so my windows app can find an instance of my android app running on the local network, here it is. this is the android code first
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import android.os.AsyncTask;
import android.util.Log;
public class TabSyncServer extends AsyncTask<Void, Void, Void> {
ServerSocket mServerSocket = null;
Socket mSocket = null;
DataInputStream mDataInputStream = null;
DataOutputStream mDataOutputStream = null;
#Override
protected void onPreExecute() {
try {
mServerSocket = new ServerSocket(2112);
//System.out.println("Listening :2112");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
protected Void doInBackground(Void... args) {
byte[] bytebuf = new byte[1024];
while (true) {
try {
mSocket = mServerSocket.accept();
mDataInputStream = new DataInputStream(mSocket.getInputStream());
mDataOutputStream = new DataOutputStream(mSocket.getOutputStream());
Log.d("TabSyncServer", "ip: " + mSocket.getInetAddress());
mDataInputStream.read(bytebuf);
String str = new String(bytebuf, "UTF8");
Log.d("TabSyncServer", "message: " + str);
if(str.contains("Hello Android")) {
Log.d("TabSyncServer", "sending reply");
mDataOutputStream.writeBytes("Hello Windows");
}
//
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (mSocket != null) {
try {
mSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (mDataInputStream != null) {
try {
mDataInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (mDataOutputStream != null) {
try {
mDataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
and the windows MFC code
void CMainFrame::OnBrowseMobile() {
CMobileSync* con = new CMobileSync();
CString ipaddr_base;
int my_last_digit;
if(!con->getMyIP(ipaddr_base, my_last_digit)) {
setMobilePath("Can't find local network");
return;
}
for(int i=1 ; i<98 ; i++) {
if(i==my_last_digit)
continue; // don;t check self
CString ipaddr; ipaddr.Format("%s.%d", ipaddr_base, i);
bool res = con->ConnectToHost(ipaddr);
if(res) {
res = con->SendMsg ("Hello Android");
if(res) {
TRACE1("send ok %s\n",ipaddr.GetBuffer());
#define RD_BUF_LEN 80
char buffer[RD_BUF_LEN];
if(con->ListenOnPortBlocking(buffer, RD_BUF_LEN)) {
if(strncmp(buffer, "Hello Windows", 12)==0) {
TRACE1("reply ok %s", buffer);
setMobilePath(ipaddr);
con->CloseConnection ();
return;
}
}
} else {
TRACE("send FAILED\n");
}
}
con->CloseConnection ();
}
setMobilePath("No TabTrax on local network");
}
#include "stdafx.h"
#include <winsock.h>
#include "MobileSync.h"
#define TTPORT 2112
bool CMobileSync::getMyIP(CString& ipaddr_front, int& ipaddr_lastdigit)
{
char szBuffer[1024];
#ifdef WIN32
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 0);
if(::WSAStartup(wVersionRequested, &wsaData) != 0)
return false;
#endif
if(gethostname(szBuffer, sizeof(szBuffer)) == SOCKET_ERROR)
{
#ifdef WIN32
WSACleanup();
#endif
return false;
}
struct hostent *host = gethostbyname(szBuffer);
if(host == NULL)
{
#ifdef WIN32
WSACleanup();
#endif
return false;
}
//Obtain the computer's IP
unsigned char b1, b2, b3, b4;
b1 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b1;
b2 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b2;
b3 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b3;
b4 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b4;
ipaddr_front.Format("%d.%d.%d", b1, b2, b3);
ipaddr_lastdigit = b4;
#ifdef WIN32
WSACleanup();
#endif
return true;
}
//CONNECTTOHOST – Connects to a remote host
bool CMobileSync::ConnectToHost(const char* IPAddress)
{
//Start up Winsock…
WSADATA wsadata;
int error = WSAStartup(0x0202, &wsadata);
//Did something happen?
if (error)
return false;
//Did we get the right Winsock version?
if (wsadata.wVersion != 0x0202)
{
WSACleanup(); //Clean up Winsock
return false;
}
//Fill out the information needed to initialize a socket…
SOCKADDR_IN target; //Socket address information
target.sin_family = AF_INET; // address family Internet
target.sin_port = htons (TTPORT); //Port to connect on
target.sin_addr.s_addr = inet_addr (IPAddress); //Target IP
mSocket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); //Create socket
if (mSocket == INVALID_SOCKET)
{
return false; //Couldn't create the socket
}
//Try connecting...
if (connect(mSocket, (SOCKADDR *)&target, sizeof(target)) == SOCKET_ERROR)
{
return false; //Couldn't connect
}
return true; //Success
}
//CLOSECONNECTION – shuts down the socket and closes any connection on it
void CMobileSync::CloseConnection ()
{
//Close the socket if it exists
if (mSocket)
closesocket(mSocket);
mSocket=0;
WSACleanup(); //Clean up Winsock
}
int CMobileSync::SendMsg (char* szpText, int buflen)
{
if(buflen==0)
buflen = strlen(szpText);
int ret = send(mSocket, szpText, buflen, 0);
TRACE1("CMobileSync::SendMsg sent %d bytes\n", ret);
return ret;
}
WSADATA w;
//LISTENONPORT – Listens on a specified port for incoming connections
//or data
bool CMobileSync::ListenOnPortBlocking(char* buffer, int buflen)
{
//Now we can start listening (allowing as many connections as possible to
//be made at the same time using SOMAXCONN). You could specify any
//integer value equal to or lesser than SOMAXCONN instead for custom
//purposes). The function will not //return until a connection request is
//made
// listen(s, SOMAXCONN);
memset(buffer, 0, sizeof(buffer)); //Clear the buffer
int iTimeout = 1600;
setsockopt( mSocket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&iTimeout, sizeof(iTimeout));
//Put the incoming text into our buffer
int ret = recv (mSocket, buffer, buflen-1, 0);
//Don't forget to clean up with CloseConnection()!
if(ret != SOCKET_ERROR)
return true;
int err = WSAGetLastError();
return false;
}
its not tested extensively but it is running
this maybe useful to someone

Categories

Resources