×
Namespaces

Variants
Actions

Como capturar a saída de System.out de um MIDlet e salvá-lo em um arquivo em dispositivos S60

From Nokia Developer Wiki
Jump to: navigation, search
Article Metadata

Exemplo de código
Artigo
Tradução:
Por maiconherverton
Última alteração feita por hamishwillee em 31 Jul 2013

Contents

Resumo

Ao desenvolver um MIDlet, que é muito útil para obter a saída do MIDlet de alguma forma visível. Isto pode ser feito, por exemplo, simplesmente adicionando System.out.println() linhas de código. No entanto, esse método só funciona normalmente, quando você usa um emulador ou utilizem recursos do dispositivo de depuração do SDK S60.


Em dispositivos S60 (S60 3ª edição e mais recentes), há também um método de redirecionamento, que foi anteriormente não documentado. É possível usar o esquema de URI "redirect", criar um InputStream e ler a saída do MIDlet do outro a partir do fluxo de processamento. Por exemplo, é possível criar uma String de fora da saída e mostrá-la ao usuário em um TextBox, como é feito no exemplo do MIDlet abaixo. Essa saída pode ser salva em um arquivo (se a API FileConnection estiver disponível) ou para um RecordStore para ser visto mais tarde. Neste exemplo, atualizar a saída também pode ser enviada como mensagem MMS para um destinatário.


A forma exata da URL varia de si um pouco, dependendo de qual versão de plataforma S60 está em uso. No caso da S60 3ª Edição FP1 ou mais velhas, a URL a ser usada é "redirect://" e, no caso da S60 3ª Edição FP2 ou mais recente é "redirect://test".

Redirecionando o fluxo de entrada pode ser feito em dispositivos diferentes da plataforma S60 da seguinte forma:

 
// Para dispositivos S60 3ª Edição FP1 ou superiores
InputConnection inputConnection = (InputConnection) Connector.open("redirect://",
Connector.READ);
inputStream = inputConnection.openInputStream();
 
// Para dispositivos S60 3ª Edição FP2 ou mais recentes
InputConnection inputConnection = (InputConnection) Connector.open("redirect://test",
Connector.READ);
inputStream = inputConnection.openInputStream();

Quando a conexão é aberta, o fluxo pode ser lido como segue o código:

while (keepLogging) {
try { // Se não há dados, este irá bloquear
len = inputStream.read(data);
} catch (IOException ioe) {
ioe.printStackTrace();
}
if(len > 0){
String str = new String(data, 0, len);
// faz algo com a String
}
}

Aqui está um trabalho completo mostrando o código do MIDlet abaixo. O MIDlet MIDPLogger é lançado primeiro e, em seguida, o MIDlet, que é para ser seguido. Todos os System.out.println(), System.err.println() e Throwable.printStackTrace() deve ser mostrado no texto do MIDlet MIDPLogger. A saída pode ser salva em um arquivo ou enviada como mensagem MMS. Nesta aplicação, a saída é salva por padrão em C:/Dados/Imagens de arquivo/log.txt. Existe um comando em Configurações para abrir um formulário para editar o endereço da mensagem MMS e o caminho do arquivo de saída.

Nota: Este é conhecido por ser não funcionar em alguns dispositivos. Por exemplo, atualmente nenhuma saída é proveniente de um MIDlet executado no N78 (sw 12,046).

Código fonte: MIDPLogger.java

/**
* Title: MIDPLogger
* Description: Redirect para MIDlet para dispositivos S60
* Copyright: Copyright (c) 2008
*
* @author Nokia
* @version 1.10
*/

 
import java.io.IOException;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.TextBox;
import javax.microedition.lcdui.TextField;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.io.Connector;
import javax.microedition.io.InputConnection;
import java.io.InputStream;
import java.io.OutputStream;
import javax.microedition.io.file.FileConnection;
import javax.wireless.messaging.MessageConnection;
import javax.wireless.messaging.SizeExceededException;
import javax.wireless.messaging.MessagePart;
import javax.wireless.messaging.MultipartMessage;
 
public class MIDPLogger extends MIDlet implements Runnable, CommandListener {
private static final int READ_BUFFER = 256;
private static final String URL_S60_3_2 = "redirect://test";
private static final String URL_S60_3_1 = "redirect://";
private boolean isAppStarted = false;
private boolean keepLogging = true;
private Command clearCommand;
private Command saveCommand;
private Command sendCommand;
private Command settingsCommand;
private Command exitCommand;
private TextBox logTextBox;
private SettingsForm form;
private InputStream inputStream;
private WriteData writeData;
private Alert messageAlert;
private Display display;
private boolean s60_3_2 = true;
private String platform;
protected String address = "mms://";
protected String filepath = "file:///C:/Data/Images/log.txt";
private MessagePart textPart;
private MultipartMessage message;
private MessageConnection connection;
private SettingsForm settingsForm;
 
/**
* startApp
*
* @throws MIDletStateChangeException
*/

protected void startApp() throws MIDletStateChangeException {
if (!isAppStarted) {
Thread t = new Thread(this);
t.start();
isAppStarted = true;
}
}
 
/**
* pauseApp é chamado quando o MIDlet é pausado
*/

protected void pauseApp() {
}
 
/**
* destroyApp
*
* @param b
* @throws MIDletStateChangeException
*/

protected void destroyApp(boolean b)throws MIDletStateChangeException {
}
 
/**
* Inicializa a interface do MIDlet: cria e adiciona os comandos e define o
* LogTextBox como Displayable corrente.
*/

private void initUI() {
display = Display.getDisplay(this);
logTextBox = new TextBox("MIDPLogger", "", 10000, TextField.ANY);
saveCommand = new Command("Save in file", Command.SCREEN, 1);
logTextBox.addCommand(saveCommand);
sendCommand = new Command("Send log as MMS", Command.SCREEN, 2);
logTextBox.addCommand(sendCommand);
settingsCommand = new Command("Settings", Command.SCREEN, 3);
logTextBox.addCommand(settingsCommand);
clearCommand = new Command("Clear", Command.CANCEL, 1);
logTextBox.addCommand(clearCommand);
exitCommand = new Command("Exit", Command.EXIT, 1);
logTextBox.addCommand(exitCommand);
logTextBox.setCommandListener(this);
display.setCurrent(logTextBox);
writeData = new WriteData();
}
 
/**
* Cria o fluxo de entrada e também verifica se o dispositivo é S60 3ª ed. FP2
* ou mais recente. Nota: A informação "java_build_version" foi adicionada ao
* "Valor da propriedade microedition.platform" nos dispositivos da série S60 3ª ed. FP2.
*/

private void createInputStream() {
platform = System.getProperty("microedition.platform");
if(platform != null && platform.indexOf("java_build_version") > 0){
s60_3_2 = true; // S60 3.2 ou superiores
}
else if (platform != null) {
s60_3_2 = false; // S60 3.1 ou outras versões
}
else return;
createRedirectInputStreamCon();
}
 
/**
* Este método seleciona a url a ser utilizada e informa o usuário sobre
* a plataforma de lançamento do aparelho S60.
*/

private void createRedirectInputStreamCon() {
try {
if (s60_3_2) {
InputConnection inputConnection = (InputConnection) Connector.open(URL_S60_3_2,
Connector.READ);
inputStream = inputConnection.openInputStream();
logTextBox.insert("Platform S60 3rd Ed. FP2 or newer.\n", logTextBox.size());
}
else {
InputConnection inputConnection = (InputConnection) Connector.open(URL_S60_3_1,
Connector.READ);
inputStream = inputConnection.openInputStream();
logTextBox.insert("Platform S60 3rd Ed. FP1 or older.\n", logTextBox.size());
}
} catch (IOException ioe) {
logTextBox.insert("IOException: " + ioe.getMessage() + "\n", logTextBox.size());
}
}
 
public void commandAction(Command command, Displayable displayable) {
if (command == clearCommand) {
logTextBox.setString("");
}
else if (command == saveCommand) {
Thread thread = new Thread(writeData);
thread.start();
}
else if (command == sendCommand) {
try {
connection = (MessageConnection)Connector.open(address);
String text = logTextBox.getString(); // Message text from TextBox
String textContentId = "text"; // Mandatory contentId
textPart = new MessagePart(text.getBytes(), 0, text.length(), "text/plain",
textContentId, null, null);
message = (MultipartMessage)connection.newMessage("multipart");
// "multipart" equals MessageConnection.MULTIPART_MESSAGE
message.setSubject("Log from MIDPLogger");
message.setAddress(address);
message.addMessagePart(textPart);
sendMMS(message);
} catch (SizeExceededException see) {
logTextBox.insert("SizeExceededException: " + see.getMessage() + "\n",
logTextBox.size());
} catch (IOException ioe) {
logTextBox.insert("IOException: " + ioe.getMessage() + "\n", logTextBox.size());
}
}
else if (command == settingsCommand) {
settingsForm = new SettingsForm("Settings", this);
Display.getDisplay(this).setCurrent(settingsForm);
}
else if (command == exitCommand) {
keepLogging = false;
this.notifyDestroyed();
}
}
 
private void sendMMS(final MultipartMessage message) {
// Envia a mensagem em sua thread de execução
logTextBox.insert("sending MMS message to: " + address + "\n", logTextBox.size());
Thread messageThread = new Thread() {
public void run() {
try {
connection.send(message);
} catch (IOException ioe) {
logTextBox.insert("IOException: " + ioe.getMessage() + "\n",
logTextBox.size());
} catch (IllegalArgumentException iae) {
logTextBox.insert("IllegalArgumentException: " + iae.getMessage() + "\n",
logTextBox.size());
} catch (SecurityException se) {
logTextBox.insert("SecurityException: " + se.getMessage() + "\n",
logTextBox.size());
}
}
};
messageThread.start();
}
 
public void run() {
initUI();
createInputStream();
readData();
}
 
/**
* Lê os dados do fluxo de entrada e os exibe
*/

private void readData() {
if(inputStream == null){
if (platform == null) showAlert("Error", "microedition.platform = null!",
AlertType.ERROR);
else showAlert("Error", "A URL: redirect:// não é suportada", AlertType.ERROR);
return;
}
readDataAndDisplay();
}
 
/**
* Lê os dados do sistema fora do MIDlet, o fluxo de erro e mostra-o usuário
*/

private void readDataAndDisplay() {
// Lê os dados de fluxo e exibi na caixa de texto
byte[] data = new byte[READ_BUFFER];
int len = -1;
while (keepLogging) {
try { // Se não há dados bloquei
len = inputStream.read(data);
} catch (IOException ioe) {
logTextBox.insert("IOException: " + ioe.getMessage() + "\n", logTextBox.size());
}
if(len > 0){
String str = new String(data, 0, len);
int maxSize = logTextBox.getMaxSize();
if (logTextBox.size() >= maxSize) {
logTextBox.setMaxSize(maxSize + READ_BUFFER * 10);
}
logTextBox.insert(str, logTextBox.size());
}
}
}
 
private void showAlert(String title, String message, AlertType alertType){
if(null == messageAlert){
messageAlert = new Alert(message);
}
messageAlert.setTitle(title);
messageAlert.setString(message);
messageAlert.setType(alertType);
 
if(alertType == AlertType.ERROR) {
messageAlert.setTimeout(Alert.FOREVER);
}
else {
messageAlert.setTimeout(3000);
}
display.setCurrent(messageAlert);
}
 
protected void showTextBox() {
logTextBox.insert("Address is now: " + address + "\n", logTextBox.size());
logTextBox.insert("Log file path is now: " + filepath + "\n", logTextBox.size());
Display.getDisplay(this).setCurrent(logTextBox);
if (form != null) form = null;
}
 
class WriteData implements Runnable {
WriteData() {}
 
public void run() {
saveData();
}
 
/**
* Salva os dados em um arquino no sistema
*/

private void saveData() {
try {
String data = logTextBox.getString();
FileConnection fileOutputConnection = (FileConnection) Connector.open(filepath);
// Cria um arquivo especificado na URL, se ele não existir
if (!fileOutputConnection.exists()) {
// create the directory if it does not exist
String path = "file://" + fileOutputConnection.getPath();
FileConnection fc = (FileConnection) Connector.open(path);
if (!fc.exists()) {
fc.mkdir();
}
fc.close();
// Cria o arquivo se ele não existir
fileOutputConnection.create();
}
OutputStream outputStream = fileOutputConnection.openOutputStream();
outputStream.write(data.getBytes());
outputStream.close();
fileOutputConnection.close();
logTextBox.insert("Log saved to " + filepath.substring(8) + "\n",
logTextBox.size());
} catch (IOException ioe) {
logTextBox.insert("IOException: " + ioe.getMessage() + "\n",
logTextBox.size());
} catch (SecurityException se) {
logTextBox.insert("SecurityException: " + se.getMessage() + "\n",
logTextBox.size());
}
}
}
}


Código fonte: SettingsForm.java

/**
* Title: SettingsForm
* Descrição: Um formulário para editar o caminho do arquivo de log e o número de telefone para mensagem MMS.
* Copyright: Copyright (c) 2008
*
* @author Nokia
* @version 1.10
*/

 
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.TextField;
 
public class SettingsForm extends Form implements CommandListener {
private MIDPLogger midlet;
private Command backCommand;
private Command exitCommand;
private TextField mmsField;
private TextField fileField;
 
public SettingsForm(String title, MIDPLogger midlet) {
super(title);
this.midlet = midlet;
backCommand = new Command("Back", Command.BACK, 1);
exitCommand = new Command("Exit", Command.EXIT, 1);
this.addCommand(backCommand);
this.addCommand(exitCommand);
this.setCommandListener(this);
mmsField = new TextField("Phone number", "+358", 50, TextField.PHONENUMBER);
this.append(mmsField);
fileField = new TextField("Log file path", "file:///C:/Data/Images/log.txt",
100, TextField.ANY);
this.append(fileField);
}
 
public void commandAction( Command c, Displayable d) {
if (c == backCommand) {
midlet.address = "mms://" + mmsField.getString();
midlet.filepath = fileField.getString();
midlet.showTextBox();
}
if (c == exitCommand) {
midlet.notifyDestroyed();
}
}
}


Há também os arquivos MIDPLogger.jad e MIDPLogger.jar disponíveis aqui, eles são considerados confiáveis para 3 partes do domínio. Devido a isso, é possível desligar o aviso de segurança, que é mostrado, quando o log é gravado em um arquivo. A configuração de segurança pode ser alterada no Gerenciador de Aplicativos (MIDPLogger -> Open -> Set "Ler dados do usuário Read user data" e "Editar dados do usuário Edit data user" para "Sempre permitir Always allowed").

Nota: O registo para enviar como mensagem MMS pode ser salvo em um arquivo como segue: Na aplicação de Mensagens abra uma mensagem MMS. Selecione "Objetos" no menu Opções. O texto de log deve ser exibido algo como "midp_wma20_attachment1". Parte da mensagem de texto pode então ser guardado em Notas ou ser enviada para alguém.

Exemplo da aplicação

This page was last modified on 31 July 2013, at 10:47.
60 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×