Writing via content pipeline in Xbox game project - xna

I'm creating an Xbox application and I have this problem with the content pipeline.
Loading .xnb files is not a problem but I can't seem to find any helpful tutorials on writing via the content pipeline. I want to write an XML whenever the user presses a custom made "save" button.
I've searched the web for "saving game sate" etc. but so far I haven't found a solution for my case.
So, summarized: is there a way to write data (in XML format) via the content pipeline, if my Save() method is called?

Saving and loading during an XNA game involves a series of asynchronous method calls. You'll find the objects you need in the Microsoft.Xna.Framework.Storage namespace.
Specifically, you need a StorageDevice and a StorageContainer;
private static StorageDevice mStorageDevice;
private static StorageContainer mStorageContainer;
To Save:
public static void SaveGame()
{
// Call this static method to begin the process; SaveGameDevice is another method in your class
StorageDevice.BeginShowSelector(SaveGameDevice, null);
}
// this will be called by XNA sometime after your call to BeginShowSelector
// SaveGameContainer is another method in your class
private static void SaveGameDevice(IAsyncResult pAsyncResult)
{
mStorageDevice = StorageDevice.EndShowSelector(pAsyncResult);
mStorageDevice.BeginOpenContainer("Save1", SaveGameContainer, null);
}
// this method does the actual saving
private static void SaveGameContainer(IAsyncResult pAsyncResult)
{
mStorageContainer = mStorageDevice.EndOpenContainer(pAsyncResult);
if (mStorageContainer.FileExists("save.dat"))
mStorageContainer.DeleteFile("save.dat");
// in my case, I have a BinaryWriter wrapper that I use to perform the save
BinaryWriter writer = new BinaryWriter(new System.IO.BinaryWriter(mStorageContainer.CreateFile("save.dat")));
// I save the gamestate by passing the BinaryWriter
GameProgram.GameState.SaveBinary(writer);
// then I close the writer
writer.Close();
// clean up
mStorageContainer.Dispose();
mStorageContainer = null;
}
Loading is very similar:
public static void LoadGame()
{
StorageDevice.BeginShowSelector(LoadGameDevice, null);
}
private static void LoadGameDevice(IAsyncResult pAsyncResult)
{
mStorageDevice = StorageDevice.EndShowSelector(pAsyncResult);
mStorageDevice.BeginOpenContainer("Save1", LoadGameContainer, null);
}
private static void LoadGameContainer(IAsyncResult pAsyncResult)
{
mStorageContainer = mStorageDevice.EndOpenContainer(pAsyncResult))
// this is my wrapper of BinaryReader which I use to perform the load
BinaryReader reader = null;
// the file may not exist
if (mStorageContainer.FileExists("save.dat"))
{
reader = new BinaryReader(new System.IO.BinaryReader(mStorageContainer.OpenFile("save.dat", FileMode.Open)));
// pass the BinaryReader to read the data
GameProgram.LoadGameState(reader);
reader.Close();
}
// clean up
mStorageContainer.Dispose();
mStorageContainer = null;
}

Related

Need to pass a ds(data structure) when Http server is being started, and to make that ds global across controllers

So,
Here is the code setup.
There is a driver application, which starts the HTTP server(ASP.NET core Web API project).
The method called by driver application for starting HTTP server is
this:
public class Http_Server
{
public static ConcurrentQueue<Object> cq = new ConcurrentQueue<Object>();
public static void InitHttpServer(ConcurrentQueue<Object> queue)
{
cq = queue;
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.UseApplicationInsights()
.Build();
host.Run();
}
}
Controller Action Task:
[HttpPost]
[Route("XYZ")]
public virtual IActionResult AddXYZ([FromBody]List<Resourcemembers> resourcemembers)
{
//add something to ds
Http_Server.cq.Enqueue(new object());
//respond back
return new ObjectResult(example);
}
The data structure(a concurrent queue) being passed is to be made visible at controller level(like a global variable accessible across all controllers).
Is it fine to make the ds a static variable and access it across controllers?
Or Is there a way to pass this ds across to different layers?
This is my go at a better solution for this. What you are trying to do doesn't seem like the best way to approach this.
First, you want to enable caching in the application by calling the AddMemoryCache in the application StartUp.ConfigureServices method.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMemoryCache();
...
}
Then, you want to use the cache. Something like this should get you going in the right direction.
public class XYZController : Controller {
private IMemoryCache _memoryCache;
private const string xyzCacheKey = "XYZ";
public XYZController(IMemoryCache memoryCache)
{
_memoryCache = memoryCache;
}
[HttpPost("XYZ")]
public IActionResult AddXYZ([FromBody]ResourceMember[] resourceMembers)
{
try
{
if (!_memoryCache.TryGetValue(xyzCacheKey, out ConcurrentQueue<Object> xyz))
{
xyz = new ConcurrentQueue<Object>();
_memoryCache.Set(xyzCacheKey, xyz, new MemoryCacheEntryOptions()
{
SlidingExpiration = new TimeSpan(24, 0, 0)
});
}
xyz.Enqueue(resourceMembers);
return Ok();
}
catch (Exception ex)
{
return BadRequest(ex);
}
}
}
public class ResourceMember { }
What this does is allow you to use a Memory Cache to hold your object(s), and what ever you Enqueue in the ConcurrentQueue object, should you stay with that as your main object within the Cache. Now, you can cache any object type in the MemoryCache, and pull the value when you need to based on the key you gave it when you added it to the cache. In the case above, I created a const named xyzCacheKey with a string value of XYZ to use as the key.
That static global variable thing you are trying is just not... good.
If this doesn't help, let me know in a comment, I will delete the answer.
Good luck!

How to notify progress for a YouTube video upload

I am working on a ASP.NET Web API with Angularjs for client side programming. My application users will be uploading/watching videos in my application. I want to upload these videos to YouTube (using YouTube API for server side).
For now I have completed the uploading part, but I am not sure how to show a process bar on client side browser with real indication of the progress of the video being uploaded. I can capture the progress on the server side as I am using the following code for uploading:
VideosResource.InsertMediaUpload insertRequest = youtube.Videos.Insert(video, "snippet, status", fileStream, "video/*");
insertRequest.ProgressChanged += insertRequest_ProgressChanged;
insertRequest.ResponseReceived += insertRequest_ResponseReceived;
insertRequest.Upload();
Here I can capture the ProgressChanged event to see the progress, but how can I notify my end user (browser) these progress updates?
You havea lot of ways, here are couple of them:
Make AJAX requests from client side to server in loop, and get progress. In this case you need to save progress in insertRequest_ProgressChanged into static storage (Static Dictionary of uploads).
Use SirnalR. This will allows you to make direct updates.
Anyway you need to store progress of your uploading in any storage.
For example you can create static class, something like:
public static class UploadingDispatcher
{
private static Dictionary<Guid, Int32> Uploads = new Dictionary<Guid, Int32>();
private static object syncRoot = new object();
public static void Add(Guid id)
{
lock (syncRoot)
{
Uploads.Add(id,0);
}
}
public static void Remove(Guid id)
{
lock (syncRoot)
{
Uploads.Remove(id);
}
}
public static int GetProgress(Guid id)
{
lock (syncRoot)
{
if (Uploads.ContainsKey(id))
{
return Uploads[id];
}
return 100;
}
}
public static Boolean SetProgress(Guid id, Int32 value)
{
lock (syncRoot)
{
if (Uploads.ContainsKey(id))
{
Uploads[id] = value;
return true;
}
return false;
}
}
}
Before your code you should create Upload by:
Guid uploadId = Guid.NewGuid();
UploadingDispatcher.Add(uploadId);
In your insertRequest_ProgressChanged method use UploadingDispatcher to update progress:
UploadingDispatcher.SetProgress(id);
You need to create separate action to get progress, like GetUploadingProgress. In this action method you can get progress by calling:
UploadingDispatcher.GetProgress(id);
To remove Upload from UploadingDispatcher after file is uploaded use:
UploadingDispatcher.Remove(id);

BlackBerry - write and read from persistent object vector

I have a BlackBerry Application that sends messages to a server at fixed intervals. The messages are sent via web service using any of the connection methods available; Wifi, BIS, TCP/IP etc.
Since the messages are being sent continuously, I need a mechanism to queue the messages in case internet is not available and send the messages across when internet becomes available. For that reason, I wish to first save any outgoing message in the Persistent Store and then read the Persistent Store and loop through it to send all pending messages. Any new message should be saved at the last spot in the Persistent Store.
I am calling the two methods below when "Send" is clicked:
public static void saveMessage(String msg){
Hashtable hashtable=new Hashtable();
persistentObject = PersistentStore.getPersistentObject(KEY);
hashtable.put("MessageToSend", msg);
persistentObject.commit();
}
public static void sendMessage(String msg){
Hashtable hashtable=new Hashtable();
persistentObject = PersistentStore.getPersistentObject(KEY);
Vector msgVector = (Vector)persistentObject.getContents();
Enumeration eMsgs=msgVector.elements();;
/*synchronized(poObject )*/{
persistentObject.setContents(msgVector);
persistentObject.commit();
}
int i=0;
while(eMsgs.hasMoreElements()){
hashtable=(Hashtable)eMsgs.nextElement();
String encryptedMessage=(String)hashtable.get("MessageToSend");
if(!encryptedMessage.equals("")){
//check internet connection
String C0NNECTION_EXTENSION = checkInternetConnection();
if(C0NNECTION_EXTENSION==null)
{
Dialog.alert("Check internet connection and try again");
return;
}
else
{
MyScreen.PostMsgToServer(encryptedMessage);
hashtable.remove(encryptedMessage);
}
}
i++;
}
}
This is just an attempt from the tutorials/examples that I came across. Kindly help.
The save method you show is not actually putting the hashtable into the PersistentObject. Try something like this instead:
public static void saveMessage(String msg){
Hashtable hashtable = new Hashtable();
persistentObject = PersistentStore.getPersistentObject(KEY);
hashtable.put("MessageToSend", msg);
persistentObject.setContents(hashtable); // <- you were missing this
persistentObject.commit();
}
That's still probably not a great implementation, because I'm assuming that you might want to call saveMessage() multiple times, and add more than one message to the persistent store (?). Is that right, or can you only ever have one message saved? (if that's true, you can ignore this next suggestion for saveMessage())
public static void saveMessage(String msg){
persistentObject = PersistentStore.getPersistentObject(KEY);
Hashtable hashtable = (Hashtable) persistentObject.getContents();
if (hashtable == null) {
// lazily initialize the store contents
hashtable = new Hashtable();
hashtable.put("MessagesToSend", new Vector());
}
Vector queuedMessages = (Vector) hashtable.get("MessagesToSend");
queuedMessages.addElement(msg);
// write the store contents to device storage
persistentObject.setContents(hashtable);
persistentObject.commit();
}
/**
* #param msg TODO: I'm not sure why msg needs to be passed, if
* saveMessage(msg) was called first?
*/
public static void sendMessage(String msg){
// TODO: you could choose to save the message here, so that the caller
// need not remember to call both sendMessage() and saveMessage()
// saveMessage(msg);
persistentObject = PersistentStore.getPersistentObject(KEY);
Hashtable hashtable = (Hashtable) persistentObject.getContents();
if (hashtable != null) {
// check for saved messages first, and send them
Vector msgVector = (Vector) hashtable.get("MessagesToSend");
Enumeration eMsgs = msgVector.elements();
Vector toDelete = new Vector();
while (eMsgs.hasMoreElements()) {
String encryptedMessage = (String)eMsgs.nextElement();
// if the send was successful, you should delete message from the store
toDelete.addElement(encryptedMessage);
}
eMsgs = toDelete.elements();
while (eMsgs.hasMoreElements()) {
// we can delete this sent message now
msgVector.removeElement((String)eMsgs.nextElement());
}
// re-write the persistent store to the device
persistentObject.setContents(hashtable);
persistentObject.commit();
}
}
I'd also generally like to steer you away from making everything static ... that said, that's really a bigger, unrelated issue here, and it does happen that your persistent store object is likely to be a unique, global object in your application (a better implementation, however, would probably avoid all these static declarations).
Update: I'm a little unclear as to how you expect to call these two methods. Based on your description, it seems that you call both saveMessage(msg) and then sendMessage(msg) when Send is clicked by the user. If you save the message first, with my implementation, then there is no need to pass msg in to sendMessage(), since sendMessage() will send out all saved, unsent messages in the queue (vector). So, the API for sendMessage() has an unnecessary parameter. Or, I supposed you could leave sendMessage(String) as the only public method, and have sendMessage(String) first call saveMessage(String).
In any case, that's up to you, and how you want your method calling semantics to work. The basic problem of storing and retrieving persistent objects should be addressed by the code above.

How to use InputStream and OutputStream on the Event thread

I am new to blackberry development and I am creating a native blackberry application. On every screen of my application, I need to send and receive data to the server on the same connection.
What I have done so far is I have made a ConnectToServer class which has a bunch of methods for sending and receiving. I instantiate it on the main screen and I pass it to each screen as a parameter.
That class in not a thread because I only read and write when the user types in information and presses a button. So basically I am using the inputStream and outputStream on the event thread which I hear is BAD. Then I ask ConnectToServer to get me what the server sent. For instance, I get a vector which I use to make a ListField.
How can I make these UI updates?
public class Screen3 extends MainScreen {
ConnectToServer con;
Vector v;
public Screen3(String exerciseName, ConnectToServer connect)
{
con = connect;
con.send(exerciseName);
v = con.receiveVector();
mylist = new listField();
mylist.setSize(v.size());
add(mylist);
}
public void drawListRow(...)
{
graphics.drawText((String) v.elementAt(index)
}
}
So, there's many ways to approach this. First of all, since it seems like you only want one instance of ConnectToServer, and you are currently having to pass that around, you might try making that class a Singleton object. This is not necessary, and does not have anything to do with your threading problem, but I only offer it as a solution, for situations where you want to enforce that there's only one instance of something, and want to avoid having to pass it around everywhere. A simple Singleton implementation might be this:
public class ConnectToServer {
private static ConnectToServer _instance;
/** use this static method to get the one and only instance */
public static ConnectToServer getInstance() {
if (_instance == null) {
_instance = new ConnectToServer();
}
return _instance;
}
/** private to enforce Singleton pattern */
private ConnectToServer() {
}
}
And use it in your screens like this (no need to pass it into the constructor any more):
ConnectoToServer connection = ConnectToServer.getInstance();
connection.blahBlahBlah();
Now, on to the threading problem. You're right that you should not be performing network requests on the main (aka "UI", aka "Event") thread. If you have a nice separate ConnectToServer class, that makes it easier to encapsulate this behaviour. Instead of UI clients using a synchronous send() and receiveVector() method, make one method that just kicks off the request, and another callback method that the ConnectToServer class will call when the response comes back. The ConnectToServer class will use a Thread to perform this work, and thus avoid freezing the UI during the request.
I'll define an interface that the UI clients will implement:
public interface RequestListener {
/** listeners must implement this method to get data. method will be called on the UI thread */
void onDataReceived(Vector response);
}
And then the new (partial) ConnectToServer class:
public class ConnectToServer {
private Thread _worker;
private RequestListener _listener;
public void setRequestListener(RequestListener listener) {
// note: this implementation only allows one listener at once.
// make it a list if you need something more
_listener = listener;
}
/** initiate a network request on a background thread */
public void sendRequest(final String request) {
_worker = new Thread(new Runnable() {
public void run() { // run on the background/worker thread
send(request);
final Vector response = receiveVector();
if (_listener != null) {
// this assumes all our listeners are UI objects, so we pass
// data back to them on the UI thread:
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() { // run on UI thread
_listener.onDataReceived(response);
}
});
}
}
});
_worker.start();
}
}
Note that you should also make your original send() and receiveVector() methods in this class private. They should only be called from inside the class now, not directly from UI clients.
Then, you need to code your Screen classes like this:
public class Screen3 extends MainScreen implements RequestListener {
public Screen3(String exerciseName) {
ConnectToServer connection = ConnectToServer.getInstance();
connection.setRequestListener(this);
// kick off the request (on a background thread)
connection.sendRequest(exerciseName);
}
public void onDataReceived(Vector response) {
if (mylist == null) {
// first time data has been received, so create and add the list field:
mylist = new listField();
add(mylist);
}
mylist.setSize(response.size());
// TODO: presumably, you would copy the contents of 'response' into 'mylist' here
}
}
Also, you might also want to code the server class to protect against multiple UI clients making concurrent requests, allow current requests to be cancelled, etc. But the above should get you started on a solution that provides a responsive app, without freezing your UI.

Using persistence to display number of times visits for a BB Application?

I have developed an application. I want to display a message before the user starts implementing my application. Like when it is used first time i want to show "Count = 1". And when app is visited second time, "Count = 2".
How can i achieve it? I had done such thing in android using sharedperferences. But how can i do it in blackberry. I had tried something with PersistentStore. But cant achieve that, for i dont know anything about the Persistance in BB.
Also i would wish to restrict the use for 100. Is it possible?
sample codes for this will be appreciable, since i am new to this environment..
You can achieve it with Persistent Storage.
Check this nice tutorial about storing persistent data.
Also you can use SQLite. Link to a development guide which describes how to use SQLite databases in Java® applications: Storing data in SQLite databases.
You can restrict user for trying your application at most 100 times using your own logic with the help of persistent data. But I think there may be some convention, so try Google for that.
got it...
I created a new class which implements Persistable. In that class i had created an integer variable and set an getter and setter function for that integer...
import net.rim.device.api.util.Persistable;
public class Persist implements Persistable
{
private int first;
public int getCount()
{
return first;
}
public void setCount()
{
this.first += 1;
}
}
Then in the class which initializes my screen, i had declared persistence variables and 3 functions to use my Persist.java, initStore(), savePersist(), and getPersist()
public final class MyScreen extends MainScreen implements FieldChangeListener
{
/*
* Declaring my variables...
*/
private static PersistentObject store;
public Persist p;
public MyScreen()
{
//my application codes
//here uses persistence
initStore();
p = getPersist();
if(p.getCount()<100)
{
savePersist();
UiApplication.getUiApplication().invokeLater(new Runnable()
{
public void run()
{
Dialog.alert(p.getCount.toString());
}
});
}
else
{
close();
System.exit(0);
}
}
//three function....
public static void initStore()
{
store = PersistentStore.getPersistentObject(0x4612d496ef1ecce8L);
}
public void savePersist()
{
synchronized (store)
{
p.setCount();
store.setContents(p);
store.commit();
}
}
public Persist getPersist()
{
Persist p = new Persist();
synchronized(store)
{
p = (Persist)store.getContents();
if(p==null)
{
p = new Persist();
}
}
return p;
}
}
I hope u all will get it right now....
If there are another simple way, plz let me know...
Thanks

Resources