In my Android app, I'm trying to print a PDF document, and everything is working fine, here is my current snippet for printing the file
private void printFile(){
PrintManager printManager = (PrintManager) this.getSystemService(getApplicationContext().PRINT_SERVICE);
PrintDocumentAdapter pda = new PrintDocumentAdapter(){
#Override
public void onWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback){
OutputStream output = null;
try {
output = new FileOutputStream(destination.getFileDescriptor());
byte[] buf = _responseBody;
output.write(buf);
callback.onWriteFinished(new PageRange[]{PageRange.ALL_PAGES});
} catch (FileNotFoundException ee){
//Catch exception
} catch (Exception e) {
//Catch exception
} finally {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras){
if (cancellationSignal.isCanceled()) {
callback.onLayoutCancelled();
return;
}
PrintDocumentInfo pdi = new PrintDocumentInfo.Builder("Name of file").setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT).build();
callback.onLayoutFinished(pdi, true);
}
#Override
public void onFinish(){
System.out.println("PRINT IS FINISHED");
}
};
PrintAttributes printAttrs = new PrintAttributes.Builder().
setMediaSize(PrintAttributes.MediaSize.ISO_A6).
setMinMargins(PrintAttributes.Margins.NO_MARGINS).
build();
PrintJob printJob = printManager.print(labelID, pda, printAttrs);
}
But when the print is completed I want to run a method for going back to a previous view of the app, so I need to catch the event it fires when the print job is completed, can somebody explain how to do it or any code snippet will be greatly appreciated.
I agree with CommonsWare comment, print job can take a long time and in some cases may stay in "blocked" state indefinitely.
For the record, the onFinish() callback should work in normal print success cases.
Related
I am trying to download an apk file to update my application and apk is placed in ftp server and I am downloading that apk using FTP Client.
Even though I call mProgress.setProgress(percent);
the ProgressBar is not getting updated from the function where I download the apk file by ftp
public class UpdateAppByFTP extends AsyncTask<String,Void,Void> {
private Context context;
CopyStreamAdapter streamListener;
public void setContext(Context mContext){
context = mContext;
}
private ProgressDialog mProgress;
#Override
protected void onPreExecute(){
super.onPreExecute();
mProgress = new ProgressDialog(this.context);
mProgress.setMessage("Downloading new apk .. Please wait...");
mProgress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
//mProgress.setIndeterminate(true);
mProgress.show();
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
mProgress.dismiss(); //Dismiss the above Dialogue
}
#Override
protected Void doInBackground(String... arg0) {
try {
String serverName = arg0[0];
String userName = arg0[1];
String password = arg0[2];
String serverFilePath = arg0[3];
String localFilePath = arg0[4]; if(getFileByFTP(serverName,userName,password,serverFilePath,localFilePath)){
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(localFilePath)), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // without this flag android returned a intent error!
context.startActivity(intent);
}else{
//Do nothing could not download
}
String apkLocation="/download/"+"SmartPOS.apk";
Intent intent1 = new Intent(Intent.ACTION_VIEW);
intent1.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory() +apkLocation)), "application/vnd.android.package-archive");
intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // without this flag android returned a intent error!
context.startActivity(intent1);
} catch (Exception e) {
}
return null;
}
//Below code to download using FTP
public boolean getFileByFTP(String serverName, String userName,
String password, String serverFilePath, String localFilePath)
throws Exception {
FTPClient ftp = new FTPClient();
try {
ftp.connect(serverName);
int reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return false;
}
} catch (IOException e) {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException f) {
throw e;
}
}
throw e;
} catch (Exception e) {
throw e;
}
try {
if (!ftp.login(userName, password)) {
ftp.logout();
}
ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
ftp.enterLocalPassiveMode();
final int lenghtOfFile =(int)getFileSize(ftp,serverFilePath);
OutputStream output = new FileOutputStream(localFilePath);
CountingOutputStream cos = new CountingOutputStream(output) {
protected void beforeWrite(int n) {
super.beforeWrite(n);
int percent = Math.round((getCount() * 100) / lenghtOfFile);
Log.d("FTP_DOWNLOAD", "bytesTransferred /downloaded"+percent);
System.err.println("Downloaded "+getCount() + "/" + percent);
mProgress.setProgress(percent);
}
};
ftp.setBufferSize(2024*2048);//To increase the download speed
ftp.retrieveFile(serverFilePath, output);
output.close();
ftp.noop(); // check that control connection is working OK
ftp.logout();
return true;
}
catch (FTPConnectionClosedException e) {
Log.d("FTP_DOWNLOAD", "ERROR FTPConnectionClosedException:"+e.toString());
throw e;
} catch (IOException e) {
Log.d("FTP_DOWNLOAD", "ERROR IOException:"+e.toString());
throw e;
} catch (Exception e) {
Log.d("FTP_DOWNLOAD", "ERROR Exception:"+e.toString());
throw e;
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException f) {
throw f;
}
}
}
}
private static long getFileSize(FTPClient ftp, String filePath) throws Exception {
long fileSize = 0;
FTPFile[] files = ftp.listFiles(filePath);
if (files.length == 1 && files[0].isFile()) {
fileSize = files[0].getSize();
}
Log.d("FTP_DOWNLOAD", "File size = " + fileSize);
return fileSize;
}
}
Basically, the UI Does not get updated, also I am not sure whether the CountingOutputStream is the correct method to find the downloaded size of the file.
Thanks in advance.
I changed this retrieveFile section of the code and it is fine now
ftp.retrieveFile(serverFilePath, cos);
I tried your solution, it worked fine for me for file sizes up to 30 MB from FTP, going above, the download crashed every time. So I assumed the getCount() method as it is being called every time would result in some issue.
I even tried running the getCount() on separate thread, but still no use.
So finally I changed percent (for progress) variable to fraction of FileSize of local/FTP file size. So in above case it will be:
int percent = Math.round(output.length() * 100) / lenghtOfFile);
Works fine.
I am trying to come back to the Main Activity after taking a picture.
However, the finish() method is not taking me back to the Main Activity. Here is my code.
protected void takePicture() {
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader reader) {
Image image = null;
try {
image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
picture = bytes;
save(bytes);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (image != null) {
image.close();
}
}
}
private void save(byte[] bytes) throws IOException {
OutputStream output = null;
try {
output = new FileOutputStream(file);
output.write(bytes);
} finally {
if (null != output) {
output.close();
}
}
}
};
} catch (CameraAccessException e) {
e.printStackTrace();
}
while(picture == null);
sendImage(picture);
finish();
}
private void sendImage(byte[] bytes) {
Intent i = new Intent();
i.putExtra("picture", bytes);
setResult(1, i);
}
If I run this code, the result picture is not null, but the Activity does not finish. If I comment out the line with
while(picture == null);
the resulting picture is null but the activity finishes at the end of the method. I want to have both the picture not be null and the Activity to finish. Any help would be greatly appreciated;
I am writing an IRC Client. The socket connection to the IRC Server is handled via a service. I have managed to stabilize all the UI elements of the Activities in question during the orientation change, but somehow the socket that is maintained by the service is being closed during the change.
Here is what I believe to be the relevant code. Please let me know if you need to see more.
//This is the Service in question
public class ConnectionService extends Service{
private BlockingQueue<String> MessageQueue;
public final IBinder myBind = new ConnectionBinder();
public class ConnectionBinder extends Binder {
ConnectionService getService() {
return ConnectionService.this;
}
}
private Socket socket;
private BufferedWriter writer;
private BufferedReader reader;
private IRCServer server;
private WifiManager.WifiLock wLock;
private Thread readThread = new Thread(new Runnable() {
#Override
public void run() {
try {
String line;
while ((line = reader.readLine( )) != null) {
if (line.toUpperCase().startsWith("PING ")) {
SendMessage("PONG " + line.substring(5));
}
else
queueMessage(line);
}
}
catch (Exception e) {}
}
});
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(MessageQueue == null)
MessageQueue = new LinkedBlockingQueue<String>();
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
return myBind;
}
#Override
public boolean stopService(Intent name) {
try {
socket.close();
wLock.release();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return super.stopService(name);
}
#Override
public void onDestroy()
{//I put this here so I had a breakpoint in place to make sure this wasn't firing instead of stopService
try {
socket.close();
wLock.release();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
super.onDestroy();
}
public void SendMessage(String message)
{
try {
writer.write(message + "\r\n");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public String readLine()
{
try {
if(!isConnected())
return null;
else
return MessageQueue.take();
} catch (InterruptedException e) {
return "";
}
}
public boolean ConnectToServer(IRCServer newServer)
{
try {
//create a new message queue (connecting to a new server)
MessageQueue = new LinkedBlockingQueue<String>();
//lock the wifi
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, "LockTag");
wLock.acquire();
server = newServer;
//connect to server
socket = new Socket();
socket.setKeepAlive(true);
socket.setSoTimeout(60000);
socket.connect(new InetSocketAddress(server.NAME, Integer.parseInt(server.PORT)), 10000);
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//run basic login scripts.
if(server.PASS != "")
SendMessage("PASS " + server.PASS);
//write nickname
SendMessage("NICK " + server.NICK);
//write username login
SendMessage("USER " + server.NICK + " 0 * :Fluffy IRC");
String line;
while ((line = reader.readLine( )) != null) {
if (line.indexOf("004") >= 0) {
// We are now logged in.
break;
}
else if (line.indexOf("433") >= 0) {
//change to alt Nick
if(!server.NICK.equals(server.ALT_NICK) && !server.ALT_NICK.equals(""))
{
server.NICK = server.ALT_NICK;
SendMessage("NICK " + server.NICK);
}
else
{
queueMessage("Nickname already in use");
socket.close();
return false;
}
}
else if (line.toUpperCase().startsWith("PING ")) {
SendMessage("PONG " + line.substring(5));
}
else
{
queueMessage(line);
}
}
//start the reader thread AFTER the primary login!!!
CheckStartReader();
if(server.START_CHANNEL == null || server.START_CHANNEL == "")
{
server.WriteCommand("/join " + server.START_CHANNEL);
}
//we're done here, go home everyone
} catch (NumberFormatException e) {
return false;
} catch (IOException e) {
return false;
}
return true;
}
private void queueMessage(String line) {
try {
MessageQueue.put(line);
} catch (InterruptedException e) {
}
}
public boolean isConnected()
{
return socket.isConnected();
}
public void CheckStartReader()
{
if(this.isConnected() && !readThread.isAlive())
readThread.start();
}
}
//Here are the relevant portions of the hosting Activity that connects to the service
//NOTE: THE FOLLOWING CODE IS PART OF THE ACTIVITY, NOT THE SERVICE
private ConnectionService conn;
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
conn = ((ConnectionService.ConnectionBinder)service).getService();
Toast.makeText(main_tab_page.this, "Connected", Toast.LENGTH_SHORT)
.show();
synchronized (_serviceConnWait) {
_serviceConnWait.notify();
}
}
#Override
public void onServiceDisconnected(ComponentName name) {
conn = null;
}
};
#Override
protected void onSaveInstanceState(Bundle state){
super.onSaveInstanceState(state);
state.putParcelable("Server", server);
state.putString("Window", CurrentTabWindow.GetName());
unbindService(mConnection);
}
#Override
protected void onDestroy()
{
super.onDestroy();
if(this.isFinishing())
stopService(new Intent(this, ConnectionService.class));
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_tab_page);
localTabHost = (TabHost)findViewById(R.id.tabHostMain);
localTabHost.setup();
localTabHost.setOnTabChangedListener(new tabChange());
_serviceConnWait = new Object();
if(savedInstanceState == null)
{//initial startup, coming from Intent to start
//get server definition
server = (IRCServer)this.getIntent().getParcelableExtra(IRC_WINDOW);
server.addObserver(this);
AddTabView(server);
startService(new Intent(this, ConnectionService.class));
}
else
{
server = (IRCServer)savedInstanceState.getParcelable("Server");
String windowName = savedInstanceState.getString("Window");
//Add Needed Tabs
//Server
if(!(windowName.equals(server.GetName())))
AddTabView(server);
//channels
for(IRCChannel c : server.GetAllChannels())
if(!(windowName.equals(c.GetName())))
AddTabView(c);
//reset each view's text (handled by tabChange)
if(windowName.equals(server.GetName()))
SetCurrentTab(server.NAME);
else
SetCurrentTab(windowName);
ResetMainView(CurrentTabWindow.GetWindowTextSpan());
//Rebind to service
BindToService(new Intent(this, ConnectionService.class));
}
}
#Override
protected void onStart()
{
super.onStart();
final Intent ServiceIntent = new Intent(this, ConnectionService.class);
//check start connection service
final Thread serverConnect = new Thread(new Runnable() {
#Override
public void run() {
if(!BindToService(ServiceIntent))
return;
server.conn = conn;
conn.ConnectToServer(server);
server.StartReader();
if(server.START_CHANNEL != null && !server.START_CHANNEL.equals(""))
{
IRCChannel chan = server.FindChannel(server.START_CHANNEL);
if(chan != null)
{
AddTabView(chan);
}
else
{
server.JoinChannel(server.START_CHANNEL);
chan = server.FindChannel(server.START_CHANNEL);
AddTabView(chan);
}
}
}
});
serverConnect.start();
}
private boolean BindToService(Intent ServiceIntent)
{
int tryCount = 0;
bindService(ServiceIntent, mConnection, Context.BIND_AUTO_CREATE);
while(conn == null && tryCount < 10)
{
tryCount++;
try {
synchronized (_serviceConnWait) {
_serviceConnWait.wait(1500);
}
}
catch (InterruptedException e) {
//do nothing
}
}
return conn != null;
}
Im not entirely certain what I am doing wrong there. Obviously there's something I'm missing, haven't found yet, or haven't even thought to check. What happens though is that after the orientation change my Send command gives me this message and nothing happens:
06-04 22:02:27.637: W/System.err(1024): java.net.SocketException: Socket closed
06-04 22:02:27.982: W/System.err(1024): at com.fluffyirc.ConnectionService.SendMessage(ConnectionService.java:90)
I have no idea when the socket is getting closed, or why.
Update
I have changed the code so that rather than binding to the service and using that to start it, instead I call startService and stopService at appropriate points as well as binding to it, on the thought that the service was being destroyed when the binding was lost. This is working exactly like it was before I changed it. The socket still closes on an orientation change, and I have no idea why.
Update :- Code and description
I added the code changes recently made for Start/Stop service and START_STICKY. I also recently read a very good article explaining how the orientation change process flow works and why its NOT a bad idea to add the android:configChanges="orientation|screenSize" line to your manifest. So this fixed the orientation issue, but its still doing the same thing if I put the activity into background mode, and then bring it back to the foreground. That still follows the same Save/Destroy/Create process that the orientation does without that manifest line...and it still closes my socket, and I still don't know why.
I do know that it doesn't close the socket until the re-create process...I know this because the message queue will display messages that were received while the app was in the background, but once I bring it back forward it closes the socket and nothing else can be sent or received.
'Socket closed' means that you closed the socket and then continued to use it. It isn't a 'disconnect'.
You need to put something into that catch block. Never just ignore an exception. You might get a surprise when you see what the exception actually was.
NB Socket.isConnected() doesn't tell you anything about the state of the connection: only whether you have ever connected the Socket. You have, so it returns true.
I'm sure this is pretty simple but I can't figure out and it sucks I'm up on suck on (what should be) an easy step.
ok. I have a method that runs one function that give a response. this method actually handles the uploading of the file so o it takes a second to give a response. I need this response in the following method. sendPicMsg needs to complete and then forward it's response to sendMessage. Please help.
b1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(!uploadMsgPic.equalsIgnoreCase("")){
Log.v("response","Pic in storage");
sendPicMsg();
sendMessage();
}else{
sendMessage();
}
1st Method
public void sendPicMsg(){
Log.v("response", "sendPicMsg Loaded");
if(!uploadMsgPic.equalsIgnoreCase("")){
final SharedPreferences preferences = this.getActivity().getSharedPreferences("MyPreferences", getActivity().MODE_PRIVATE);
AsyncHttpClient client3 = new AsyncHttpClient();
RequestParams params3 = new RequestParams();
File file = new File(uploadMsgPic);
try {
File f = new File(uploadMsgPic.replace(".", "1."));
f.createNewFile();
//Convert bitmap to byte array
Bitmap bitmap = decodeFile(file,400);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.PNG, 0 /*ignored for PNG*/, bos);
byte[] bitmapdata = bos.toByteArray();
//write the bytes in file
FileOutputStream fos = new FileOutputStream(f);
fos.write(bitmapdata);
params3.put("file", f);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
params3.put("email", preferences.getString("loggedin_user", ""));
params3.put("webversion", "1");
client3.post("http://*******.com/apiweb/******upload.php",params3, new AsyncHttpResponseHandler() {
#Override
public void onSuccess(String response) {
Log.v("response", "Upload Complete");
refreshChat();
//responseString = response;
Log.v("response","msgPic has been uploaded"+response);
//parseChatMessages(response);
response=picurl;
uploadMsgPic = "";
if(picurl!=null){
Log.v("response","picurl is set");
}
if(picurl==null){
Log.v("response", "picurl no ready");
};
}
});
sendMessage();
}
}
2nd Method
public void sendMessage(){
final SharedPreferences preferences = this.getActivity().getSharedPreferences("MyPreferences", getActivity().MODE_PRIVATE);
if(preferences.getString("Username", "").length()<=0){
editText1.setText("");
Toast.makeText(this.getActivity(), "Please Login to send messages.", 2);
return;
}
AsyncHttpClient client = new AsyncHttpClient();
RequestParams params = new RequestParams();
if(type.equalsIgnoreCase("3")){
params.put("toid",user);
params.put("action", "sendprivate");
}else{
params.put("room", preferences.getString("selected_room", "Adult Lobby"));
params.put("action", "insert");
}
Log.v("response", "Sending message "+editText1.getText().toString());
params.put("message",editText1.getText().toString() );
params.put("media", picurl);
params.put("email", preferences.getString("loggedin_user", ""));
params.put("webversion", "1");
client.post("http://peekatu.com/apiweb/*********.php",params, new AsyncHttpResponseHandler() {
#Override
public void onSuccess(String response) {
refreshChat();
//responseString = response;
Log.v("response", response);
//parseChatMessages(response);
if(picurl!=null)
Log.v("response", picurl);
}
});
editText1.setText("");
lv.setSelection(adapter.getCount() - 1);
}
From what I understand, you need serial execution of background tasks.
What I do in the case is use a class that extends AsyncTask, takes some sort of listener in its constructor and calls the listener's callback in onPostExecute.
A quick example:
class ExampleTask<T,S,U> extends AsyncTask<T,S,U>
{
public interface ExampleListener
{
public void onTaskCompleted(boolean success);
}
private ExampleListener mListener;
public ExampleTask(ExampleListener listener)
{
mListener = listener;
}
...
#Override
protected void onPostExecute(U result)
{
...
if (mListener != null)
{
mListener.onTaskCompleted(yourBooleanResult);
}
}
}
Just pass a new ExampleListener implementation that calls the second method.
Here's an implementation of the listener:
ExampleListener sendMessageListener = new ExampleListener()
{
public void onTaskCompleted(boolean success)
{
if(success)
sendMessage();
}
}
Don't mix this IO and RPC intensive with your client thread. When your button is clicked, start another thread which handles the communication.
In that thread (potentially a separate class) you send the picture and wait for response; at the same time mark your button to be disabled to avoid clicking again. Then when you receive response, send the message again. Afterwards, raise an event back to the GUI thread, enable the button and display the message.
An easy way to solve this; call your method sendMessage() after the sendPicMsg() in the "onSuccess()" method
I have a naive problem, but I confused: I have made application which uses Facebook SDK, and it works good on my device and emulator, and it doesn't work on customer's device. He doesn't get any error or exceptions - when he press button for authorize he will see "loading" message, but progress bar will be closed, and authorization will be canceled. What problem is it? Thank you for anything hints
private void submitExec() {
/* if (SQLiteDbWrapper.getInstance().getBookCount()==0) {
Toast.makeText(this, "A list of books is empty", Toast.LENGTH_LONG).show();
return;
}*/
SQLiteDbWrapper.getInstance().makeFacebook(this, this.getApplicationContext());
if (SQLiteDbWrapper.getInstance().getConnector().getFacebook().isSessionValid()) {
//new SubmitClass().execute();
}
else {
SessionEvents.AuthListener listener = new SessionEvents.AuthListener() {
#Override
public void onAuthSucceed() {
//MyBookDroidActivity.this.executeSubmitClass();
}
#Override
public void onAuthFail(String error) {
}
};
SessionEvents.addAuthListener(listener);
SQLiteDbWrapper.getInstance().getConnector().login();
}
}
It is function for authorizating.
public void makeFacebook(Activity activity, Context context) {
if (mConnector==null||!mConnector.getFacebook().isSessionValid()) {
mConnector=new FacebookConnector(FACEBOOK_APPID, activity, context,
new String[] {"publish_stream", "read_stream", "email"});
}
}
It is function for making FacebookConnector.
Try adding logging:
public void appendLog(String text)
{
File logFile = new File("sdcard/log.file");
if (!logFile.exists())
{
try
{
logFile.createNewFile();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try
{
//BufferedWriter for performance, true to set append to file flag
BufferedWriter buf = new BufferedWriter(new FileWriter(logFile, true));
buf.append(text);
buf.newLine();
buf.close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
If you can't run some kind of LogCat or collect the stacktrace on the device yourself, you may want to look into:
http://code.google.com/p/microlog4android/