air for android - Cant upload to FTP - android

I'm trying to upload a simple text file to ftp, the code works on the pc.
On android the app connects successfully to the ftp but when I try to upload the file I get "2031:Error #2031: Socket Error."
Any ideas?
The code (from http://suzhiyam.wordpress.com/2011/04/) is:
import flash.events.ProgressEvent;
import flash.events.Event;
import flash.net.Socket;
import flash.events.IOErrorEvent;
import flash.errors.IOError;
import flash.filesystem.FileStream;
import flash.filesystem.File;
import flash.utils.ByteArray;
import flash.events.MouseEvent;
msg.text="Wait! Connecting to ftp server!"
//
var ftp_host:String = "*"; //FTP settings are correct in the original code...
var ftp_port:Number = 21;
var ftp_username:String = "*";
var ftp_password:String = "*";
//
//in this demo we will be manually entering the remote servers folder from which upload or download should happen
var remoteFolderStr:String;
var localFolderStr:String;
var remoteFile:String;
//Socket instance which will be used to connect to ftp server
var s = new Socket(ftp_host,ftp_port);
s.addEventListener(IOErrorEvent.IO_ERROR,onIOERR);
s.addEventListener(ProgressEvent.SOCKET_DATA, onReturnData);
s.addEventListener(Event.CONNECT, onConnectHandler);
//
//Socket instance which will be used to connect to receive data sent by ftp server
var r:Socket = new Socket();
r.addEventListener(ProgressEvent.SOCKET_DATA, onServData);
r.addEventListener(Event.CONNECT, onPasvConn);
r.addEventListener(IOErrorEvent.IO_ERROR,onIOERR);
//For every command the client sends to ftp server the server returns message with return codes
function onReturnData(evt:ProgressEvent)
{
var d = s.readUTFBytes(s.bytesAvailable);
trace(d);
//check here for complete list of return codes and their meaning
//- http://en.wikipedia.org/wiki/List_of_FTP_server_return_codes
// the return message will have a 3 digit return code followed by a space and related message
// if the 3 digit return code is followed by "-" the it will be a multiline message
//-wait until the line with 3 digit code followed by space is delivered
if (d.indexOf("220 ") > -1)
{
msg.text="Logging in to ftp server!"
//connected to ftp server send user name to server
s.writeUTFBytes("USER "+ftp_username+"\n");
s.flush();
}
if (d.indexOf("331 ") > -1)
{
//Username accepted now send password to server
s.writeUTFBytes("PASS "+ftp_password+"\n");
s.flush();
}
if (d.indexOf("230") > -1 && d.indexOf("OK.") > -1)
{
msg.text="Log in successful!"
//Password accepted - lets enetr passive mode and retrive a list of files from a directory
//first enetr passive mode
//s.writeUTFBytes("PASV \n");
//s.flush();
}
var a = d.indexOf('227');
if (a > -1)
{
//Entering passive mode message will be returned along with it details of ip and port address will be returned
//-we have to connect to that address to receive the data
//format of the message will be: 227 Entering Passive Mode (209,190,85,253,148,206)
//the data inside brackets is the ip and port address, first four numbers represent IP and last 2 PORT
//the port value have to be calculated by multiplying the 5th number with 256 and adding the 6th number to it
//here in this example IP is 209.190.85.253 , PORT is (148*256)+206 = 38094
var st = d.indexOf("(",a);
var en = d.indexOf(")",a);
var str;
str = d.substring(st + 1,en);
var a2 = str.split(",");
var p1 = a2.pop();
var p2 = a2.pop();
var ip:String = a2.join(".");
var port:int=(p2*256)+(p1*1);
r.connect(ip, port);
}
if (d.indexOf("226 ") > -1)
{
//Data Transfer completed
//s.writeUTFBytes("QUIT \n");
//s.flush();
if (process=='download')
{
msg.text="DOWNLOAD_COMPLETE"
}
if (process=='upload')
{
msg.text="UPLOAD_COMPLETE"
}
dispatchEvent(new Event("dataReceived"))
}
if (d.indexOf("221 ") > -1)
{
//LOGGED OUT from server
}
//Response code 150 will be sent by server whenever a data connection is established after we send 'PASV' command
if (d.indexOf("150 ") > -1)
{
if (process == 'upload')
{
//Once data connection is established we can start sending the data to the server
startSendingData();
}
}
}
function onConnectHandler(evt:Event)
{
msg.text="CONNECTED TO FTP SERVER!"
trace("CONNECTED TO FTP SERVER");
//Client has connected to ftp server
}
function onPasvConn(evt:Event):void
{
trace("CONNECTED TO DATA PORT");
//s.writeUTFBytes("LIST /your/folder/path\n");
if (process=='upload')
{
//To Upload a file send following command
//STOR is the command followed by a space and path wher to store the file in remote server
//-with the name of the file to be saved as..you can provide any name with extension
s.writeUTFBytes("STOR /test.txt\n");
}
s.flush();
}
function onServData(evt:ProgressEvent):void
{
//DATA RECEIVED FROM SERVER THRO DATA PORT
}
function onIOERR(evt:IOErrorEvent)
{
trace(evt.errorID+":"+evt.text);
}
//
var process:String = "";// variable to store what action is being performed
var writeToStream:Boolean;//not used here
var localFile:File;//local file which it to be uploaded
var localFolder:File;// local folder to which the downloaded file to be stored
var interval:Number;
var bufferSize:int;
//
BTN_Upload.addEventListener(MouseEvent.CLICK,initUpload);
function initUpload(evt:MouseEvent=null):void
{
//called when upload event is triggered
startUploadProcess();
}
function startUploadProcess():void
{
process = "upload";
//You need to pass this command 'TYPE I' to set data transfer mode as binary
s.writeUTFBytes("TYPE I\n");
s.writeUTFBytes("PASV \n");
s.flush();
}
function startSendingData():void
{
var textToUpload:String = "This is a test";
bufferSize = textToUpload.length;
var ba:ByteArray = new ByteArray();
//Store the info you want to upload in ByteArray HERE
ba.writeMultiByte(textToUpload, "iso-8859-1");
r.writeBytes(ba, 0, ba.bytesAvailable);
r.flush();
}

Related

Sending response to generated session

I'm wiriting my application in Android, but i don't know how to send response only to device whos generated session with special ID in express-session. For example, i have 3 phones and click at the same time button login with difference data in pools, all 3 devices captured the same object instead of 3 different destined ( first response object from express was caught by 3 devices rest 2 object ignored, i want to sent object every one of them ).
....
var express = require('express');
var session = require('express-session');
var crypto = require('crypto');
var uuid = require('node-uuid');
var app = express();
app.use(session({
secret: 'DFGDFG',
resave: false,
saveUninitialized:false,
genid:function(req){
return crypto.createHash('sha256').update(uuid.v1()).update(crypto.randomBytes(256)).digest("hex");
},
}));
app.post('/login', (request,response)=> {
var post_data = request.body;
request.session.user = post_data.user;
request.session.password = post_data.password;
if(err){
console.log("error");
}
else{
var db= client.db('test');
db.collection('object').findOne({'user':request.session.user}, function(error,user){
if(user.password == request.session.password){
request.session.amount = user.amount; // if password was correct, sending amount account
console.log('Success');
res.send(request.session.amount);
}
else{
console.log('Password invalid');
}
}
});

converting buffer message to readable utf8 using node

Question:
how can I make my sensor data come in as proper x,y,z coordinates or something more human readable??
Background:
I have packets of sensor data (eg. Gravity, Rotation etc..) coming from my android phone
Ok so I've a UDP server using nodeJS. It is open and listening for a message data.
server.js
var PORT = 33333;
var HOST = '0.0.0.0';
var dgram = require('dgram');
var server = dgram.createSocket('udp4');
server.on('listening', function () {
var address = server.address();
console.log('UDP Server listening on ' + address.address + ":" + address.port);
});
server.on('message', function (message, remote) {
console.log(message);
});
server.bind(PORT, HOST);
This message is formatted as a buffer((?) what is it really called binary?).
This is what happens when i do console.log(message.toString("utf8"));

as3 air Upload issue with Android Upload file more than 400 KB

i am trying to upload a zip file using FTP, on Android when the file size less than 400 KB it is uploaded correctly, when it is more than 400 KB only 414 KB got uploaded and the result file is corrupted.
I tried same code from Windows and it is working with all sizes.
here is my code:
public function uploadZipFile() {
//Socket instance which will be used to connect to ftp server
s.addEventListener(IOErrorEvent.IO_ERROR,onIOERR);
s.addEventListener(ProgressEvent.SOCKET_DATA, onReturnData);
s.addEventListener(Event.CONNECT, onConnectHandler);
s.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
//
//Socket instance which will be used to connect to receive data sent by ftp server
r.addEventListener(ProgressEvent.SOCKET_DATA, onServData);
r.addEventListener(Event.CONNECT, onPasvConn);
r.addEventListener(IOErrorEvent.IO_ERROR,onIOERR);
dtimer = new Timer(10,1);
dtimer.addEventListener(TimerEvent.TIMER_COMPLETE,function(){checkForStream();});
this.addEventListener('dataReceived',onDataReceived);
var file:File = new File("XXX.zip");
initUpload(file)
}
private function onReturnData(evt:ProgressEvent)
{
var d = s.readUTFBytes(s.bytesAvailable);
trace(d);
//check here for complete list of return codes and their meaning
//- http://en.wikipedia.org/wiki/List_of_FTP_server_return_codes
// the return message will have a 3 digit return code followed by a space and related message
// if the 3 digit return code is followed by "-" the it will be a multiline message
//-wait until the line with 3 digit code followed by space is delivered
if(d.indexOf("220 ")>-1){
//connected to ftp server send user name to server
s.writeUTFBytes("USER "+ftp_username+"\n");
s.flush()
}
if(d.indexOf("331 ")>-1){
//Username accepted now send password to server
s.writeUTFBytes("PASS "+ftp_password+"\n");
s.flush()
}
if (d.indexOf("230") > -1 && d.indexOf("OK.") > -1)
{
//Password accepted - lets enter passive mode and retrieve a list of files from a directory
//first enter passive mode
trace("Log in successful!");
s.writeUTFBytes("PASV \n");
s.flush();
}
var a = d.indexOf('227');
if (a > -1)
{
//Entering passive mode message will be returned along with it details of ip and port address will be returned
//-we have to connect to that address to receive the data
//format of the message will be: 227 Entering Passive Mode (209,190,85,253,148,206)
//the data inside brackets is the ip and port address, first four numbers represent IP and last 2 PORT
//the port value have to be calculated by multiplying the 5th number with 256 and adding the 6th number to it
//here in this example IP is 209.190.85.253 , PORT is (148*256)+206 = 38094
var st = d.indexOf("(",a);
var en = d.indexOf(")",a);
var str;
str = d.substring(st + 1,en);
var a2 = str.split(",");
var p1 = a2.pop();
var p2 = a2.pop();
var ip:String = a2.join(".");
var port:int=(p2*256)+(p1*1);
r.connect(ip, port);
}
if(d.indexOf("226 ")>-1){
//Data Transfer completely lets disconnect from server
if (process=='download')
{
trace("DOWNLOAD_COMPLETE");
}
if (process=='upload')
{
trace("UPLOAD_COMPLETE");
informServer();
}
dispatchEvent(new Event("dataReceived"))
}
if(d.indexOf("221 ")>-1){
//LOGGED OUT from server
}
if (d.indexOf("150 ") > -1)
{
if (process == 'upload')
{
//Once data connection is established we can start sending the data to the server
startSendingData();
}
}
}
private function onConnectHandler(evt:Event)
{
trace("CONNECTED TO FTP SERVER");
//Client has connected to ftp server
//you can also send multiple commands at same time like below or send step by step based on return code
//-!
//s.writeUTFBytes("USER username\n");
//s.writeUTFBytes("PASS password\n");
//s.flush();
}//
private function onPasvConn(evt:Event):void
{
trace("CONNECTED TO DATA PORT");
//Now send LIST command to retrieve directory listings
if (process == 'getDirList')
{
//To retrive directory listings send following command
s.writeUTFBytes("LIST "+remoteFolderStr+"\n");
}
else if (process=='download')
{
//To Download a file send following command
//RETR is the command followed by a space and path to file in remote server
s.writeUTFBytes("RETR "+remoteFolderStr+"/"+remoteFile+"\n");
}
else if (process=='upload')
{
//To Upload a file send following command
//STOR is the command followed by a space and path wher to store the file in remote server
//-with the name of the file to be saved as..you can provide any name with extension
s.writeUTFBytes("STOR /"+localFile.name+"\n");
}
s.flush();
}
private function onServData(evt:ProgressEvent):void
{
//DATA RECEIVED FROM SERVER THRO DATA PORT
var d = r.readUTFBytes(r.bytesAvailable);
if (process == 'getDirList')
{
d = r.readUTFBytes(r.bytesAvailable);
trace(d);
}
else if (process=='download')
{
//As the data connection is established start writing the data to the fileStream
fileData = new ByteArray();//temporary bytearray object to write the incoming data
r.readBytes(fileData, 0, r.bytesAvailable);//write data to the temp bytearray
fileStream.writeBytes(fileData, 0, fileData.bytesAvailable);//now write the bytearray to file stream
//instead you can directly write the data to file stream drom socket
}
}
private function onIOERR(evt:IOErrorEvent):void
{
trace(evt.errorID+":"+evt.text);
}
private function checkForStream():void
{
//this function is used to check if the incoming data is fully written to the filestream and then close the filestream
//-even if the ftp server dispatches that the file has been transfered...you application cn be still writing them to the filestream
if(!r.connected){
fileStream.close()
}else{
//if the file is still been writing restart the timer
dtimer.reset()
dtimer.start()
}
}
//
public function initUpload(fileToUpload:File):void
{
//called when upload event is triggered
localFile = fileToUpload;
if (localFile.exists)
{
// this.remoteFolderStr=remote_folder.text
startUploadProcess();
}
}
private function startUploadProcess():void
{
//create and open a fileStream
fileStream=new FileStream();
fileStream.open(localFile, FileMode.READ);
process = "upload";
fileData = new ByteArray();
//You need to pass this command 'TYPE I' to set data transfer mode as binary
s.writeUTFBytes("TYPE I\n");
s.writeUTFBytes("PASV \n");
s.flush();
}
private function startDownloadProcess():void
{
localFile = localFolder.resolvePath(remoteFile);
fileStream=new FileStream();
fileStream.open(localFile, FileMode.WRITE);
process = "download";
fileData = new ByteArray();
s.writeUTFBytes("TYPE I\n");
s.writeUTFBytes("PASV \n");
s.flush();
}
private function startSendingData():void
{
interval = setInterval(sendData,300);
}
private function sendData():void
{
//file to be uploaded is sent as binary data
if (fileStream.bytesAvailable <= 0)
{
clearInterval(interval);
r.close();
return;
}
if (fileStream.bytesAvailable < bufferSize)
{
bufferSize = fileStream.bytesAvailable;
}
var ba:ByteArray = new ByteArray();
fileStream.readBytes(ba, 0, bufferSize);
r.writeBytes(ba, 0, ba.bytesAvailable);
r.flush();
}
private function onDataReceived(evt:Event):void
{
if(process=='download'){
dtimer.start();
}
}
If anyone have this issue, i solved it by using small bufferSize, i set it to 100KB,
i found it is attempt to close the connection before all data is sent when the buffer is big.
You can add event OutputProgressEvent.OUTPUT_PROGRESS to check the number of bytes that has been written in the dataChannelConnection.

Air android/mobile: same sharedobject for different apps?

I have two apps, one is a trial version the other the full version of a game, both made with adobe air. While saving data via the sharedobjects solution is no problem, I would like to use "one" savegame for both appsm, so users can keep their progress when upgrading to the full version. I tried around a little. But code like e.g. ...:
SharedObject.getLocal("myApp","/");
... doesnt work. So the question is, is there a way to have two Air apps using the same shared object? Or maybe if not using, at least "read" the shared object of another Air app?
Thanks in advance,
ANB_Seth
The answer is yes, I actually made a game transfer system for iOS and Android via network connection and 6 digit hash the user has to enter in the newly installed app to fetch the SO from the server. You could do this with a simple file stored locally on the SD card or other local storage device.
/**
* send this user's current save data to the server
*/
public function send():void{
var ba:ByteArray = new ByteArray();
// Main.sv.user - is the registerClassAlias object we write/read locally via SharedObject
ba.writeObject(Main.sv.user);
var name:String = Crypto.hash("Random Secrect Salt - typically user score, name, etc.");
// create 6 digit hash
var key:String = Crypto.hash(name).slice(0, 6).toUpperCase();
var request:URLRequest = new URLRequest ( 'https://sharedobject.com/transfer/save/name/'+name+'/key/'+key );
var loader: URLLoader = new URLLoader();
request.contentType = 'application/octet-stream';
request.method = URLRequestMethod.POST;
request.data = ba;
loader.addEventListener(IOErrorEvent.IO_ERROR, function (evt:Event) {
trace("error - network");
onSaveRestoreEvent(1);
});
loader.addEventListener(Event.COMPLETE, function (evt:Event) {
addChild(new BaseDialog("Save Sent To Server", "Your data has been sent to the server. To get this data back from the server " +
"you will need your secret key. Please write this six digit key down:\n"+name));
});
loader.load( request );
}
/**
* create a GET SO dialog
*/
public function receive():void{
var text:Sprite = new Sprite();
var textInput:TextInput = new TextInput();
textInput.width = Constants.SCREEN_WIDTH-100;
textInput.y = -50;
text.addChild(textInput);
var dialog:BaseDialog = new BaseDialog("Enter Secret Save Key", "Please enter your six digit secret save key in the field below, then press \"Get\".\n\n",
"Get", function():void{
text.removeChildren();
var url:String = "https://sharedobject.com/transfer/get/name/"+textInput.text; //servlet url
var request:URLRequest = new URLRequest(url);
//get rid of the cache issue:
var urlVariables:URLVariables = new URLVariables();
urlVariables.nocache = new Date().getTime();
request.data = urlVariables;
request.method = URLRequestMethod.GET;
var loader:URLLoader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(Event.COMPLETE, function (evt:Event) {
var loader:URLLoader = URLLoader(evt.target);
var bytes:ByteArray = loader.data as ByteArray;
bytes.position = 0;
if(bytes.length <= 10 || !(bytes.readObject() is User)){
onSaveRestoreEvent(2);
}else{
try{
bytes.position = 0;
Main.sv.user = (bytes.readObject() as User);
Main.sv.save();
onSaveRestoreEvent(0);
}
catch( e : EOFError ){
onSaveRestoreEvent(3);
}
}
});
loader.addEventListener(IOErrorEvent.IO_ERROR, function (evt:Event) {
trace("error - network");
onSaveRestoreEvent(1);
});
loader.load(request);
},
"Close", function():void{text.removeChildren();}, null, null, text);
dispatchEvent(new CreateBaseDialogEvent(dialog));
}
/**
* called after the restore save system is done
* #param prompt int [0 = complete][1 = error network][2 = error key][3 = error EOF]
*/
private function onSaveRestoreEvent(prompt:int):void{
var dialog:BaseDialog;
if(prompt == 0){
dialog = new BaseDialog("Restore Complete!", "All save data has been restored.");
}else if(prompt == 1){
dialog = new BaseDialog("Network Error!", "Please seek an internet connection and try again.");
}else if(prompt == 2){
dialog = new BaseDialog("Invalid Secret Key!", "The key you've entered seems to be invalid, or the save data has expired on the server. " +
"Data only lasts on the server for 24 hours.");
}else{
dialog = new BaseDialog("Error!", "There was an issue getting the file from the server. Please try the transfer again.");
}
dispatchEvent(new CreateBaseDialogEvent(dialog));
}

Real-time Status Update on Client Android Phonegap App

I'm trying to find the best way to send my users a real-time status update of a process that's running on my server - this process is broken up into five parts. Right now I'm just 'pulling' the status using an Ajax call every few seconds to a PHP file that connects to MySQL and reads the status, but as you can imagine, this is extremely hard on my database and doesn't work so well with users that don't have a strong internet connection.
So I'm looking for a solution that will 'push' data to my client. I have APE push-engine running on my server now, but I'm guessing Socket.IO is better for this? What if they're on 3G and they miss a status update?
Thanks in advance :)
I guess my answer may match what you need.
1st: You Have to Get Node.js to run the socket.io
BELOW IS SAMPLE CODE FOR SERVER:
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
app.listen(8800); //<---------Port Number
//If No Connection / Page Error
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
//If there is connection
io.sockets.on('connection', function (socket) {
//Set Varible
var UserID;
var Old_FieldContent = "";
socket.on('userid', function (data) {
if(data.id){
UserID = data.id;
StartGetting_FileName(UserID)
}
});
//Checking New Status
function StartGetting_FileName(UserID){
//Create Interval for continues checking from MYSQL database
var myInterval = setInterval(function() {
//clearInterval(myInterval);
//MySQL Connection
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
port : '3306',
user : 'root',
password : 'ABCD1234',
database : 'test',
});
//Setup SQL Query
var SQL_Query = "SELECT FileName FROM status WHERE UserID = '"+UserID+"'";
connection.connect();
connection.query(SQL_Query, function(err, rows, fields) {
//Do if old result is, different with new result.
if(Old_FieldContent !== rows[0].FileName){
if (err) throw err;
//Display at Server Console
console.log('------------------------------------------');
console.log('');
console.log('Fields: ', fields[0].name);
console.log('Result: ', rows[0].FileName);
console.log('');
console.log('------------------------------------------');
//Send Data To Client
socket.emit('news', { FieldName: fields[0].name });
socket.emit('news', { FieldContent: rows[0].FileName });
//Reset Old Data Variable
Old_FieldContent = rows[0].FileName;
}
});
connection.end();
}, 500 );
}
});
BELOW IS CLIENT HTML & JS:
<!doctype html>
<html>
<head>
<title>web sockets</title>
<meta charset="utf-8">
<!-- URL PATH TO LOAD socket.io script -->
<script src="http://15.17.100.165:8800/socket.io/socket.io.js"></script>
<script>
//Set Variable
var UserID = "U00001";
var socket = io.connect('http://15.17.100.165:8800');
var Field_Name = "No Data";
var Field_Content = "No Data";
// Add a disconnect listener
socket.on('connecting',function() {
msgArea.innerHTML ='Connecting to client...';
console.log('Connecting to client...');
//Once Connected Send UserID to server
//for checking data inside MYSQL
socket.emit('userid', { id: UserID });
});
// Get data that push from server
socket.on('news', function (data) {
console.log(data);
writeMessage(data);
});
// Add a disconnect listener
socket.on('disconnect',function() {
msgArea.innerHTML ='The client has disconnected!';
console.log('The client has disconnected!');
});
//Function to display message on webpage
function writeMessage(msg) {
var msgArea = document.getElementById("msgArea");
if (typeof msg == "object") {
// msgArea.innerHTML = msg.hello;
if(msg.FieldName !== undefined){
Field_Name = msg.FieldName;
}
if(msg.FieldContent !== undefined){
Field_Content = msg.FieldContent;
}
}else {
msgArea.innerHTML = msg;
}
msgArea.innerHTML = Field_Name +" = "+ Field_Content;
}
</script>
</head>
<body>
<div id="msgArea">
</div>
</body>
</html>
You should consider using push notifications, with the service provided for Android by Google as C2DM: https://developers.google.com/android/c2dm/
You will need to implement a PhoneGap plugin to handle the native notifications, and communicate them to your PhoneGap project that will then (and only then) query your server .
As K-ballo above points out, using a push notification plugin would be best.
Luckily, some good citizen on GitHub has done this already!
https://github.com/awysocki/C2DM-PhoneGap
Please note: the above C2DM plugin was built for PhoneGap v1.2, so if you are running a more up-to-date version you will have to tweak the native code a bit to get it working better.

Categories

Resources