I am trying to create an Android application created using Adobe Flash Actionscript 3. I wanted each user of the app to input their name in the beginning of the application, then they have the capability to save their progress in current frame (and it will be saved into a save slot or similar). However, the problem arises when another user is going to use the app, he/she must enter a distinct username, and he/she can save anytime (and load his/her distinct load progress, different from the previous user.). And it goes on.
I am a newbie in programming and I hope you could help me. Any suggestions will be appreciated. Thanks!
This my code for creating a username and saving it:
function handleClick(Event:MouseEvent):void
{
var myFirstVariable = boxOne.text;
boxTwo.text = myFirstVariable;
gotoAndStop("opening_scene")
}
myButton2.addEventListener(MouseEvent.MOUSE_UP, handleClick);
UPDATED EDIT 2: Here is my code for saving and loading. Still not working:
var so:SharedObject = SharedObject.getLocal("Test");
var userName:String = nameField.text;
if (so.data.users == null)
so.data.users = new Object();
btnSave.addEventListener(MouseEvent.CLICK, onClick);
function onClick(e:MouseEvent):void
{
if (so.data.users[userName] == null)
so.data.users[userName] = new Object();
so.data.users[userName].lastframe = currentFrame;
so.flush();
trace(userName);
}
btnLoad.addEventListener(MouseEvent.CLICK, reloadBtnClick);
function reloadBtnClick(e:MouseEvent):void
{
if (so.data.users[userName] == null)return;
if (so.data.users[userName].lastFrame == null) return;
gotoAndStop(so.data.users[userName].lastFrame);
trace(userName);
}
I recommend that you use a SQLite Data Base to save your data can find all the documentation here Manipulating SQL database data Well is a little bit more complicate but works like have tables in Excel.
As Vesper suggested, you need to have a storage with all the users you store. For example:
// Put user name here.
var userName:String;
var SO:SharedObject = SharedObject.getLocal("save");
// Create storage for users.
if (SO.data.users == null) SO.data.users = new Object();
// ...
function saveCurrentFrame(event:MouseEvent):void
{
// Create storage for current user by their name.
if (SO.data.users[userName] == null) SO.data.users[userName] = new Object();
SO.data.users[userName].lastframe = currentFrame;
SO.flush();
}
function getLastFrame(event:MouseEvent):void
{
trace(1);
// Skip this if there's no record for
if (SO.data.users[userName] == null) return;
trace(2);
if (SO.data.users[userName].lastFrame == null) return;
trace(3);
gotoAndStop(SO.data.users[userName].lastFrame);
trace(4);
}
Related
I am using Realm MongoDB for my android app, and I have a problem:
I have different users in my app, and each user has his "cards". The partition of each user's cards is:
"Card=userID".
So, I want to be able to send a card from one user to the other. I do it via a link that includes userID and specific cardID.
So my code looks something like:
Realm.init(this);
mainApp = new App(new AppConfiguration.Builder(APP_ID).defaultSyncErrorHandler((session, error) ->
Log.e("TAG()", "Sync error: ${error.errorMessage}")
).build());
//TEMP CODE
String partition = "Card=611d7n582w36796ce34af106"; //test partition of another user
if(mainApp.currentUser() != null) {
SyncConfiguration config = new SyncConfiguration.Builder(
mainApp.currentUser(),
partition)
.build();
Realm realmLinkCard = Realm.getInstance(config);
Log.d(TAG, "onCreate: cards found- " + realmLinkCard.where(Card.class).findAll().size());
}
The last log always shows 0. I know there are cards for sure because if the user that created the corresponding partition is signed in then it does find the cards.
permissions are set to true for both read and write for the whole sync.
What can the problem be?
You cannot access a Realm by a user who has a different partition.
Instead you can create a mongodb function and call it from your user.
Make your function here:
Check here on How to create a function
And call it by checking here on How to call a function from client
Quick example of a realm function:
exports = async function funcName(partition) {
const cluster = context.services.get('myclustername');
const mycollection = cluster.db('mydbname').collection('mycollectionname');
let result = [];
try {
result = mycollection.findOne({
_partition: partition,
});
} catch (e) {
result.push(e);
return result;
}
return result;
};
To call it, please see above for the documentation as I'm not an Android developper.
I´m trying to do an array to storage data with local storage. it works pretty well on google emulator. but isn´t working on my android device.
I found this code on the internet to put array in localstorage, and it works.
Storage.prototype.setArray = function (key, obj) {
return this.setItem(key, JSON.stringify(obj))
}
Storage.prototype.getArray = function (key) {
return JSON.parse(this.getItem(key))
}
then i create an function to get and set the data there.
function teste() {
var bd = [];
bd = window.localStorage.getArray("banco");
var nome = $('#name2').val();
alert(nome);
var area = $('#textarea2').val();
alert(area);
var meuservico = new servico(nome, area);
bd.push(meuservico);
alert(bd[0].nome);
window.localStorage.setArray("banco", bd);
}
and I also made an object called service.
function servico(nome,area){
this.nome = nome;
this.area = area;
}
this code work! but only on browser . how do I make it work on android? I don´t really wanna work with strings in localstorage. please help me!.
I tried with this too and didn´t work on device either.
localStorage.setItem('session', JSON.stringify(session));
var restoredSession = JSON.parse(localStorage.getItem('session'));
As the title states, my user's on iOS and Android are reporting their save data has been deleted when I push an update to the respected storefronts. The game saves and restores data properly on application load and exit. I have not changed any save information locations or package names... Just mere bug fixes, build, push.
Any clarification would be helpful, or proposed redundant data backup scheme's I should pursue to ensure the end-user experience is from henceforth not affected negatively. I would also like to understand better how I can test this as a release package is not allowed to update a market installed application.
var so:SharedObject = SharedObject.getLocal("storage");
var u:User;
if(so.data != null){
u = so.data.user;
}
trace("Loading application...");
if(u != null){
trace("LOADING SAVE DATA");
user = u;
}else{
trace("NO SAVE DATA EXISTS");
user = new User();
}
I have discovered the cause of this issue and it seems that Adobe has identified and fixed the issue as well (as of AIR 3.5). https://bugbase.adobe.com/index.cfm?event=bug&id=3347676
SharedObjects are stored within a directory named according to the SWF used by your application, so if your application is running off "myApp.swf" the SharedObject will be stored in a directory "myApp". If you change the name of this SWF (i.e. the corresponding XML build sheet configuration file for your AIR project) any subsequent builds will store their SharedObjects in a new location.
The issue described in this bug was specifically denoted for iOS, wherein the application was not storing the SharedObject in the corresponding SWF location as described above but in a separate location denoted by the "filename" attribute in your project's XML build sheet.
I have also discovered that Adobe does indeed condone the use of a SharedObject for persistent storage on a mobile platform.
I have developed a simple backup for future version save redundancy in case future updates fail to persist the SharedObject.
/** the last timestamp a deep save was completed */
private var mLastSave:Number = -1;
/**
* save the state of the globals object and all of its
* sub objects.
* #warning
* all objects must implement variables in a "public" state.
* Private variables are not saved within the persistance manager
*/
public function save():void{
var so:SharedObject = SharedObject.getLocal("storage");
so.data.user = user;
so.flush();
saveDeep();
}
/**
* Save the SharedObject to denoted mobile applicationStorageDirectory.
*/
public function saveDeep():void{
// save on first application save or after
// every 5 minutes
if(mLastSave == -1 || mLastSave < getTime() + 300000){
mLastSave = getTime();
var file:File = File.applicationStorageDirectory.resolvePath("userSave");
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
var ba:ByteArray = new ByteArray();
ba.writeObject(user);
fileStream.writeBytes(ba);
fileStream.close();
}
}
/**
* Load the application from the SharedObject be default
* if the SharedObject DNE attempt to load from the
* applicationStorageDirectory, if neither exist
* create new User object
*/
public function load():void{
registerClassAlias("user", User);
// Create/read a shared-object named "userData"
var so:SharedObject = SharedObject.getLocal("storage");
var u:User;
if(so.data != null){
u = so.data.user;
}
trace("Loading application...");
if(u != null){
trace("LOADING SAVE DATA");
user = u;
}else{
trace("NO SAVE DATA EXISTS");
var file:File = File.applicationStorageDirectory.resolvePath("userSave");
if(file.exists){
trace("Found userSave backup -attempting to load");
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.READ);
var ba:ByteArray = new ByteArray();
fileStream.readBytes(ba);
fileStream.close();
try{
user = (ba.readObject() as User);
}catch( e : EOFError ){
trace("SharedObject did not exist, attempted userSave load, failed");
}
}else{
user = new User();
trace("created New user...");
}
}
}
I have a really weird scenario that I'm stuck on. I have a ASP.Net MVC 4 app where I'm authenticating a user and creating an authCookie and adding it to the response's cookies then redirecting them to the target page:
if (ModelState.IsValid)
{
var userAuthenticated = UserInfo.AuthenticateUser(model.UserName, model.Password);
if (userAuthenticated)
{
var userInfo = UserInfo.FindByUserName(model.UserName);
//SERIALIZE AUTHENTICATED USER
var serializer = new JavaScriptSerializer();
var serializedUser = serializer.Serialize(userInfo);
var ticket = new FormsAuthenticationTicket(1, model.UserName, DateTime.Now, DateTime.Now.AddMinutes(30), false, serializedUser);
var hash = FormsAuthentication.Encrypt(ticket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash) {Expires = ticket.Expiration};
Response.Cookies.Add(authCookie);
if (Url.IsLocalUrl(model.ReturnUrl) && model.ReturnUrl.Length > 1 && model.ReturnUrl.StartsWith("/") && !model.ReturnUrl.StartsWith("//") && !model.ReturnUrl.StartsWith("/\\"))
{
return Redirect(model.ReturnUrl);
}
var url = Url.Action("Index", "Course");
return Redirect(url);
}
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
This is working just fine in all browsers. I can login and access the secure pages in my app.
My client is requesting an android version of this app. So, I'm trying to figure out how to convert this app into an APK file. My first attempt is to create a simple index.html page with an iframe that targets the application. This works just fine in Firefox and IE 9. However, when accessing the index.html page that contains the iframe that points to the app via Chrome, I get past the login code above and the user gets redirected to the secure controller, but the secure controller has a custom attribute to make sure the user is authenticated:
public class RequiresAuthenticationAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.User.Identity.IsAuthenticated) return;
if (filterContext.HttpContext.Request.Url == null) return;
var returnUrl = filterContext.HttpContext.Request.Url.AbsolutePath;
if (!filterContext.HttpContext.Request.Browser.IsMobileDevice)
{
filterContext.HttpContext.Response.Redirect(FormsAuthentication.LoginUrl + string.Format("?ReturnUrl={0}", returnUrl), true);
}
else
{
filterContext.HttpContext.Response.Redirect("/Home/Home", true);
}
}
}
My app is failing on: filterContext.HttpContext.User.Identity.IsAuthenticated. IsAuthenticated is always false, even though the user was authenticated in the code above.
Keep in mind this only happens when accessing the app via iframe in Chrome. If I access the app directly instead of via iframe, then everything works just fine.
Any ideas?
UPDATE:
My controller extends SecureController. In the constructor of SecureController I have the code that deserializes the user:
public SecureController()
{
var context = new HttpContextWrapper(System.Web.HttpContext.Current);
if (context.Request.Cookies[FormsAuthentication.FormsCookieName] != null)
{
var serializer = new JavaScriptSerializer();
var cookie = context.Request.Cookies[FormsAuthentication.FormsCookieName].Value;
var ticket = FormsAuthentication.Decrypt(cookie);
CurrentUser = serializer.Deserialize<UserInfo>(ticket.UserData);
}
else
{
CurrentUser = new UserInfo();
}
//if ajax request and session has expired, then force re-login
if (context.Request.IsAjaxRequest() && context.Request.IsAuthenticated == false)
{
context.Response.Clear();
context.Response.StatusCode = 401;
context.Response.Flush();
}
}
First, you should be deriving from AuthorizeAttribute, not an ActionFilterAttribute. Authorization attributes execute before the method is even called at a higher level of the pipeline, while ActionFilters execute much further down, and other attributes can execute before yours.
Secondly, you aren't showing the code you use to decrypt the ticket and set the IPrincipal and IIdentity. Since that's where the problem is, it's odd that you didn't include it.
I am currently developing an Android application using Flex 4.5.1 and I am having an issue when trying to pass data that I have stored in a SharedObject array to my Web Service for a Database query. the code below shows how I am storing the data in the SharedObject:
var so:SharedObject = SharedObject.getLocal("app");
public var prefsArray:ArrayCollection = new ArrayCollection(so.data.prefs);
protected function prefs_btn_click(event:MouseEvent):void
{
prefsArray.source.push(getFrsByIDResult.lastResult.id);
so.data.prefs = [prefsArray];
var flushStatus:String = so.flush();
if (flushStatus != null) {
switch(flushStatus) {
case SharedObjectFlushStatus.PENDING:
so.addEventListener(NetStatusEvent.NET_STATUS,
onFlushStatus);
break;
case SharedObjectFlushStatus.FLUSHED:
trace("success");
break;
}
}
}
protected function onFlushStatus(event:NetStatusEvent):void
{
trace(event.info.code);
}
I have tested the SharedObject to see if the information is being entered into it correctly and all seems fine. Now I have used the code below in order to retrieve the data from the SharedObject and try and send it to the PHP web Service to run the DB query.
var so:SharedObject = SharedObject.getLocal("app");
var arrCol:ArrayCollection = new ArrayCollection(so.data.prefs);
var str:String = new String(arrCol.toString());
protected function list_creationCompleteHandler(event:FlexEvent):void
{
getPrefsByprefIdsResult.token = prefsService.getPrefsByPrefIds(so.data.prefs);
}
I have tested the Webservice in Flex and have it configured to recieve an Array of Ints (int[]) and it works when i run a test operation on it with two dummy values. However when I try to use the code above to pass the Web Service the Shared Object data I get this error:
TypeError: Error #1034: Type Coercion failed: cannot convert []#97e97e1 to mx.collections.ArrayCollection.
at views::**************/list_creationCompleteHandler()[C:\Users\Jack\Adobe Flash Builder 4.5\****************\src\views\*******************.mxml:25]
at views::*********************/__list_creationComplete()[C:\Users\Jack\Adobe Flash Builder 4.5\****************\src\views\***************.mxml:94]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at mx.core::UIComponent/dispatchEvent()[E:\dev\4.5.1\frameworks\projects\framework\src\mx\core\UIComponent.as:13128]
at mx.core::UIComponent/set initialized()[E:\dev\4.5.1\frameworks\projects\framework\src\mx\core\UIComponent.as:1818]
at mx.managers::LayoutManager/validateClient()[E:\dev\4.5.1\frameworks\projects\framework\src\mx\managers\LayoutManager.as:1090]
at mx.core::UIComponent/validateNow()[E:\dev\4.5.1\frameworks\projects\framework\src\mx\core\UIComponent.as:8067]
at spark.components::ViewNavigator/commitNavigatorAction()[E:\dev\4.5.1\frameworks\projects\mobilecomponents\src\spark\components\ViewNavigator.as:1878]
at spark.components::ViewNavigator/commitProperties()[E:\dev\4.5.1\frameworks\projects\mobilecomponents\src\spark\components\ViewNavigator.as:1236]
at mx.core::UIComponent/validateProperties()[E:\dev\4.5.1\frameworks\projects\framework\src\mx\core\UIComponent.as:8209]
at mx.managers::LayoutManager/validateProperties()[E:\dev\4.5.1\frameworks\projects\framework\src\mx\managers\LayoutManager.as:597]
at mx.managers::LayoutManager/doPhasedInstantiation()[E:\dev\4.5.1\frameworks\projects\framework\src\mx\managers\LayoutManager.as:783]
at mx.managers::LayoutManager/doPhasedInstantiationCallback()[E:\dev\4.5.1\frameworks\projects\framework\src\mx\managers\LayoutManager.as:1180]
I have replaced certain filenames and locations with *'s to protect the work i am doing, but can someone please help me with this issues as I believe it has to be something simple???
Thanks
ok so let me explain in more detail. This is being designed for an Android app like I said, but image what I am trying to do is to store Bookmarks persistently using the Local Shared Object.
The first chunck of code you see above is designed to create the LSO attribute for the bookmark i want to create and imagine that there can be more than one bookmark set at different times like in a web browser. The only way i could find to do this was to store these items/details in an array which I retrieve and then update before saving back to the LSO and saving.
The second piece of code related to imagine a "Bookmarks Page" with a list of all the content that I have bookmarked. Now what I wanted to happen was thta I would be able to call up the LSO attribute which held the id's of the bookmarks and then load up thier details in a list format.
I have managed to create the LSO and store the bookmark deatils in and allow them to be updated and entries added. Also I have made sure that the PHP code that I have pulls back all the database objects relating to the array of id's and this has been tested using flex. The only thing that I cant seem to do is to pass the id's to the PHP web service file. The code in the Web Service file is below if that helps:
public function getPrefsByPrefIds($PrefIds) {
$stmt = mysqli_prepare($this->connection, "SELECT * FROM $this->tablename WHERE $this->tablename.id IN(" .implode(",", $PrefIds). ")");
$this->throwExceptionOnError();
mysqli_stmt_execute($stmt);
$this->throwExceptionOnError();
$rows = array();
mysqli_stmt_bind_result($stmt, $row->id, $row->name, $row->desc);
while (mysqli_stmt_fetch($stmt)) {
$rows[] = $row;
$row = new stdClass();
mysqli_stmt_bind_result($stmt, $row->id, $row->name, $row->desc);
}
mysqli_stmt_free_result($stmt);
mysqli_close($this->connection);
return $rows;
}
Yes I had already tried that but thanks. I have made some more progress on my own as I have been experimenting with the different types of objects that can be stored in SharedObjects. I have managed to get the solution part working with this code:
This code is designed to capture the boomark info and store it in an arrayCollection before transferring it to a bytesArray and saving
var so:SharedObject = SharedObject.getLocal("app");
public var prefArray:ArrayCollection = new ArrayCollection(so.data.prefs);
protected function prefs_btn_click(event:MouseEvent):void
{
prefArray.source.push(getCompaniesByIDResult.lastResult.id);
so.data.prefs = [prefArray];
var bytes:ByteArray = new ByteArray();
bytes.writeObject(prefArray);
so.data.ac = bytes;
var flushStatus:String = so.flush();
if (flushStatus != null) {
switch(flushStatus) {
case SharedObjectFlushStatus.PENDING:
so.addEventListener(NetStatusEvent.NET_STATUS,
onFlushStatus);
break;
case SharedObjectFlushStatus.FLUSHED:
trace("success");
break;
}
}
}
protected function onFlushStatus(event:NetStatusEvent):void
{
trace(event.info.code);
}
This next code is the designed to retrieve that information from the SahredObjects bytesArray and put it back into an Array Collection
var so:SharedObject = SharedObject.getLocal("app");
var ba:ByteArray = so.data.ac as ByteArray;
var ac:ArrayCollection;
protected function list_creationCompleteHandler(event:FlexEvent):void
{
ba.position = 0;
ac = ba.readObject() as ArrayCollection;
getPrefsByPrefIdsResult.token = prefsService.getPrefsByPrefIds(ac);
}
however as I have said this works in a small way only as if I store only one Bookmark (id) for an item and then go to the bookmarks list the details for that bookark are successfully retrieved, however if I save more than one Bookmark(2 or more id's) the page will not load the details, i do not get an error but I believe it is hanging because it is looking for say id's "1,2" instead of "1" and "2" but i dont know why this is or how to resolve this. I appreciate the advice I have been given but am finding it hard there is no one who can help me with this issue and I am having to do various experiemnts with the code. Can someone please help me with this I would really appreciate it :-) Thanks