I am developing a J2ME application to run on my W595s Sony Ericsson mobile phone.
My application uses the JSR 135 Mobile Media API and the JSR 234 Advanced Multimedia Supplements API.
My application displays a Form.
The camera video is displayed in a Form's item.
The Form has a command.
The application takes a snapshot when the user activates the command.
The snapshot file is saved to the Picture directory on the memory stick.
Here is the Form's commandAction event listener :
public void commandAction(Command arg0, Displayable arg1) {
m_snapshotControl.setDirectory("e:/Picture");
m_snapshotControl.setFilePrefix("AC");
m_snapshotControl.setFileSuffix(".JPG");
int[]resolutions = m_cameraControl.getSupportedStillResolutions();
int maxValue = (resolutions.length / 2) - 1;
m_cameraControl.setStillResolution(maxValue);
m_snapshotControl.start(1);
}
I ran my application 2 times.
The Picture directory did not contain any snapshot file before the first run.
I did the following actions during each run :
I activated the command
I answered yes to the following rights requesting dialogs :
Allow the application to read user data ?
Allow the application to write user data ?
Allow the application to read user data ?
Allow the application to write user data ?
Allow the application to shoot with the camera ?
Allow the application to read user data ?
Allow the application to write user data ?
The AC0000.jpg snapshot file was created after the first run.
The AC0000.jpg picture file was replaced after the second run.
I do not want my application to replace snapshots taken during past runs.
How can I set the name of a snapshot file before taking the snapshot ?
Is it possible to set the string in between the prefix and the suffix ?
Any help will be greatly appreciated
I haven't tried on this particular range of phone but how about this:
private int iSnapshotCounter = 0;
public void commandAction(Command arg0, Displayable arg1) {
m_snapshotControl.setDirectory("e:/Picture");
m_snapshotControl.setFilePrefix("AC");
m_snapshotControl.setFileSuffix( (++iSnapshotCounter) + ".JPG");
int[]resolutions = m_cameraControl.getSupportedStillResolutions();
int maxValue = (resolutions.length / 2) - 1;
m_cameraControl.setStillResolution(maxValue);
m_snapshotControl.start(1);
}
If that works, you can then decide to include the date and time (say, to the second) in the file name.
Of course, if setFileSuffix() won't allow you to specify more than a file extension, you can try to use the same trick on the prefix string.
You may also need to use JSR-75 to figure out what files already exist in the folder.
I have added a PlayerListener to the SnapshotControl's Player.
My playerUpdate method renames the created Snapshot file when the SHOOTING_STOPPED event occurs.
The new name is made up of the current date and time's parts.
The format of the new name is YYYYMMDD_HHMMSS.jpg.
Here is the playerUpdate method :
public void playerUpdate(Player arg0, String arg1, Object arg2) {
if (arg1.equalsIgnoreCase(SnapshotControl.SHOOTING_STOPPED)) {
FileConnection fconn = null;
try {
fconn = (FileConnection)Connector.open("file:///e:/Picture/" + (String)arg2);
Date now = new Date();
Calendar calendar = Calendar.getInstance();
calendar.setTime(now);
StringBuffer buffer = new StringBuffer();
buffer.append(calendar.get(Calendar.YEAR));
int month = calendar.get(Calendar.MONTH);
month++;
if (month < 10) {
buffer.append(0);
}
buffer.append(month);
int day = calendar.get(Calendar.DAY_OF_MONTH);
if (day < 10) {
buffer.append(0);
}
buffer.append(day);
buffer.append("_");
int hour = calendar.get(Calendar.HOUR_OF_DAY);
if (hour < 10) {
buffer.append(0);
}
buffer.append(hour);
int minute = calendar.get(Calendar.MINUTE);
if (minute < 10) {
buffer.append(0);
}
buffer.append(minute);
int second = calendar.get(Calendar.SECOND);
if (second < 10) {
buffer.append(0);
}
buffer.append(second);
buffer.append(".jpg");
fconn.rename(buffer.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
fconn.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Related
I have a requirement where I need to add the time stamp for the screenshot image that is saved in /img folder. When I see AssertionService.java(https://github.com/qmetry/qaf/blob/master/src/com/qmetry/qaf/automation/ui/selenium/AssertionService.java), I See it is adding some random string at the end.
How to remove this random string added and add time stamp? Thanks for the help in advance!
private String captureScreenShot() {
String filename = StringUtil.createRandomString(getTestCaseName()) + ".png";
try {
selenium.captureEntirePageScreenshot(getScreenShotDir() + filename, "");
} catch (Exception e) {
try {
selenium.windowFocus();
} catch (Throwable t) {
logger.error(t);
}
selenium.captureScreenshot(getScreenShotDir() + filename);
}
lastCapturedScreenShot = filename;
logger.info("Captured screen shot: " + lastCapturedScreenShot);
return filename;
}
Are you using selenium 1 or 2 api? Selenium 2 uses following code https://github.com/qmetry/qaf/blob/d58b1d1ca01b2df1a916bcd6d555df4f51a13b12/src/com/qmetry/qaf/automation/core/QAFTestBase.java#L351. Regardless of API, you can't change naming strategy for automatic screenshots. As alternate you may disable auto capturing of screenshot, capture as and when needed and set calling setLastCapturedScreenShot
I am using arcgis library 100.0.0 in android for displaying maps and information inside map.
I am using the following code to populate a ServiceFeaturetable using URL provided by arcGis. I am able to load the feature layer successfully into the mapview. I have written code that listens to the click on the symbol on the map, so that I can get some information about the specific feature on the map. I am able to get the specific feature OnClick.
Upon investigating the GetAttributes() result of the specific feature, I realize that it is not having all the fields. After investigating on internet, I found that the FeatureTable.QueryFeaturesAsync could be used to get all the fields of the feature. Even though I have written the code to get all the fields, I do not know how I link this result with the feature layer, so that the feature has all the fields that I require. Here is the code
final ServiceFeatureTable serviceFeatureTable = new ServiceFeatureTable("some URL");
ListenableFuture<FeatureQueryResult> queryresult = serviceFeatureTable.queryFeaturesAsync(null, ServiceFeatureTable.QueryFeatureFields.LOAD_ALL);
// create the feature layer using the service feature table
final FeatureLayer featureLayer = new FeatureLayer(serviceFeatureTable);
featureLayer.setSelectionColor(Color.YELLOW);
featureLayer.setSelectionWidth(10);
// add the layer to the map
mapView.getMap().getOperationalLayers().add(featureLayer);
// set an on touch listener to listen for click events
mapView.setOnTouchListener(new DefaultMapViewOnTouchListener(getContext(), mapView) {
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
// get the point that was clicked and convert it to a point in map coordinates
Point clickPoint = mMapView.screenToLocation(new android.graphics.Point(Math.round(e.getX()), Math.round(e.getY())));
int tolerance = 10;
double mapTolerance = tolerance * mMapView.getUnitsPerDensityIndependentPixel();
// create objects required to do a selection with a query
Envelope envelope = new Envelope(clickPoint.getX() - mapTolerance, clickPoint.getY() - mapTolerance, clickPoint.getX() + mapTolerance, clickPoint.getY() + mapTolerance, mapView.getMap().getSpatialReference());
QueryParameters query = new QueryParameters();
query.setGeometry(envelope);
// call select features
final ListenableFuture<FeatureQueryResult> future = featureLayer.selectFeaturesAsync(query, FeatureLayer.SelectionMode.NEW);
// add done loading listener to fire when the selection returns
future.addDoneListener(new Runnable() {
#Override
public void run() {
try {
//call get on the future to get the result
FeatureQueryResult result = future.get();
// create an Iterator
Iterator<Feature> iterator = result.iterator();
Feature feature;
// cycle through selections
int counter = 0;
while (iterator.hasNext()){
feature = iterator.next();
counter++;
String name = feature.getAttributes().get(Constants.FIELD_NAME).toString();
Log.d(getResources().getString(R.string.app_name), "Selection #: " + counter + " Table name: " + feature.getFeatureTable().getTableName());
}
//Toast.makeText(getApplicationContext(), counter + " features selected", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Log.e(getResources().getString(R.string.app_name), "Select feature failed: " + e.getMessage());
}
}
});
return super.onSingleTapConfirmed(e);
}
});
Try replacing your code
from
final ListenableFuture<FeatureQueryResult> future = featureLayer.selectFeaturesAsync(query, FeatureLayer.SelectionMode.NEW);
to
final ListenableFuture<FeatureQueryResult> future = serviceFeatureTable.queryFeaturesAsync(query, ServiceFeatureTable.QueryFeatureFields.LOAD_ALL);
It works for me!
I was trying to build a bean that always retrieves the same document ( a counter document), gets the current value, increment it and save the document with the new value. Finally it should return the value to the calling method and that would get me a new sequential number in my Xpage.
Since the Domino objects cannot be serialized or singleton'ed what's the benefit creating a bean doing this, over creating a SSJS function doing the exact same thing?
My bean must have calls to session, database, view and document, which then will be called every time.
The same within the SSJS-function except for session and database.
Bean:
public double getTransNo() {
try {
Session session = ExtLibUtil.getCurrentSession();
Database db = session.getCurrentDatabase();
View view = db.getView("vCount");
view.refresh();
doc = view.getFirstDocument();
transNo = doc.getItemValueDouble("count");
doc.replaceItemValue("count", ++transNo);
doc.save();
doc.recycle();
view.recycle();
} catch (NotesException e) {
e.printStackTrace();
}
return transNo;
}
SSJS:
function getTransNo() {
var view:NotesView = database.getView("vCount");
var doc:NotesDocument = view.getFirstDocument();
var transNo = doc.getItemValueDouble("count");
doc.replaceItemValue("count", ++transNo);
doc.save();
doc.recycle();
view.recycle();
return transNo;
}
Thank you
Both pieces of code are not good (sorry to be blunt).
If you have one document in your view, you don't need a view refresh which might be queued behind a refresh on another view and be very slow. Presumably you are talking about a single sever solution (since replication of the counter document would for sure lead to conflicts).
What you do in XPages is to create a Java class and declare it as application bean:
public class SequenceGenerator {
// Error handling is missing in this class
private double sequence = 0;
private String docID;
public SequenceGenerator() {
// Here you load from the document
Session session = ExtLibUtil.getCurrentSession();
Database db = session.getCurrentDatabase();
View view = db.getView("vCount");
doc = view.getFirstDocument();
this.sequence = doc.getItemValueDouble("count");
this.docID = doc.getUniversalId();
Utils.shred(doc, view); //Shred currenDatabase isn't a good idea
}
public synchronized double getNextSequence() {
return this.updateSequence();
}
private double updateSequence() {
this.sequence++;
// If speed if of essence I would spin out a new thread here
Session session = ExtLibUtil.getCurrentSession();
Database db = session.getCurrentDatabase();
doc = db.getDocumentByUnid(this.docID);
doc.ReplaceItemValue("count", this.sequence);
doc.save(true,true);
Utils.shred(doc);
// End of the candidate for a thread
return this.sequence;
}
}
The problem for the SSJS code: what happens if 2 users hit that together? At least you need to use synchronized there too. Using a bean makes it accessible in EL too (you need to watch out not to call it too often). Also in Java you can defer the writing back to a different thread - or not write it back at all and in your class initialization code read the view with the actual documents and pick the value from there.
Update: Utils is a class with static methods:
/**
* Get rid of all Notes objects
*
* #param morituri = the one designated to die, read your Caesar!
*/
public static void shred(Base... morituri) {
for (Base obsoleteObject : morituri) {
if (obsoleteObject != null) {
try {
obsoleteObject.recycle();
} catch (NotesException e) {
// We don't care we want go get
// rid of it anyway
} finally {
obsoleteObject = null;
}
}
}
}
I'm trying to implement a customization in SharePoint 2010 so that when a document is uploaded to a library, the file name is changed to include the Document ID in the name. (I know that people shouldn't worry about file names as much any more, but we have a lot of legacy files already named and users who like to have local copies).
I was able to implement a custom Event Receiver on the ItemAdded event that renames the file by adding the Document ID before the file name. This works correctly from the web Upload.
The problem is with the Explorer View. When I try to add the file using WebDAV in the Explorer View, I get two copies of the file. It seems that when a file is uploaded via the Web the events that fire are
ItemAdding
ItemAdded
But when I copy/paste a file into Explorer View I see the following events:
ItemAdding
ItemAdded
ItemAdding
ItemAdded
ItemUpdating
ItemUpdated
The result is I have two files with different names (since the Document IDs are different).
I've found a lot of people talking about this issue online (this is the best article I found). Anyone have any other ideas? Would it make more sense to do this in a workflow instead of an event receiver? I could use a scheduled job instead, but that might be confusing to the user if the document name changed a few minutes later.
This is my code that works great when using the Web upload but not when using Explorer View:
public override void ItemAdded(SPItemEventProperties properties)
{
try
{
SPListItem currentItem = properties.ListItem;
if (currentItem["_dlc_DocId"] != null)
{
string docId = currentItem["_dlc_DocId"].ToString();
if (!currentItem["BaseName"].ToString().StartsWith(docId))
{
EventFiringEnabled = false;
currentItem["BaseName"] = docId + currentItem["BaseName"];
currentItem.SystemUpdate();
EventFiringEnabled = true;
}
}
}
catch (Exception ex)
{
//Probably should log an error here
}
base.ItemAdded(properties);
}
I have found that using a Visual Studio workflow allows me the most flexibility to do this. A SharePoint Designer Workflow would be simpler, but would be harder to deploy to different sites and libraries.
After reading some good articles including this and this I have come up with this code which seems to work. It starts a workflow and waits until the document is not in a LockState and then processes the filename.
The workflow looks like this:
And here is the code behind:
namespace ControlledDocuments.RenameWorkflow
{
public sealed partial class RenameWorkflow : SequentialWorkflowActivity
{
public RenameWorkflow()
{
InitializeComponent();
}
public Guid workflowId = default(System.Guid);
public SPWorkflowActivationProperties workflowProperties = new SPWorkflowActivationProperties();
Boolean continueWaiting = true;
private void onWorkflowActivated1_Invoked(object sender, ExternalDataEventArgs e)
{
CheckFileStatus();
}
private void whileActivity(object sender, ConditionalEventArgs e)
{
e.Result = continueWaiting;
}
private void onWorkflowItemChanged(object sender, ExternalDataEventArgs e)
{
CheckFileStatus();
}
private void CheckFileStatus()
{
if (workflowProperties.Item.File.LockType == SPFile.SPLockType.None)
{
continueWaiting = false;
}
}
private void renameFile(object sender, EventArgs e)
{
try
{
SPListItem currentItem = workflowProperties.Item;
if (currentItem["_dlc_DocId"] != null)
{
string docId = currentItem["_dlc_DocId"].ToString();
if (!currentItem["BaseName"].ToString().StartsWith(docId))
{
currentItem["BaseName"] = docId + currentItem["BaseName"];
currentItem.SystemUpdate();
}
}
}
catch (Exception ex)
{
//Should do something useful here
}
}
}
}
Hope this helps someone else if they have the same problem.
Well i'd go for the workflow workaround... there are 2 options imo:
1) Create a boolean fied in your document library, then create a SPD workflow that fires when the item is added and set that field to "Changed" or something. In the EventReceiver you then check whether that field has been set..
2) Do everything with the SPD workflow - changing the title like in this example should be no problem.
One of the actions of my JPF controller builds up a PDF file and I would like to return this file to the user so that he can download it.
Is it possible to do that or am I forced to write the file somewhere and have my action forward a link to this file? Note that I would like to avoid that as much as possible for security reasons and because I have no way to know when the user has downloaded the file so that I can delete it.
I've tried to access the HttpServletResponse but nothing happens:
getResponse().setContentLength(file.getSize());
getResponse().setContentType(file.getMimeType());
getResponse().setHeader("Content-Disposition", "attachment;filename=\"" + file.getTitle() + "\"");
getResponse().getOutputStream().write(file.getContent());
getResponse().flushBuffer();
We have something similar, except returning images instead of a PDF; should be a similar solution, though, I'm guessing.
On a JSP, we have an IMG tag, where the src is set to:
<c:url value="/path/getImage.do?imageId=${imageID}" />
(I'm not showing everything, because I'm trying to simplify.) In your case, maybe it would be a link, where the href is done in a similar way.
That getImage.do maps to our JPF controller, obviously. Here's the code from the JPF getImage() method, which is the part you're trying to work on:
#Jpf.Action(forwards = {
#Jpf.Forward(name = FWD_SUCCESS, navigateTo = Jpf.NavigateTo.currentPage),
#Jpf.Forward(name = FWD_FAILURE, navigateTo = Jpf.NavigateTo.currentPage) })
public Forward getImage(final FormType pForm) throws Exception {
final HttpServletRequest lRequest = getRequest();
final HttpServletResponse lResponse = getResponse();
final HttpSession lHttpSession = getSession();
final String imageIdParam = lRequest.getParameter("imageId");
final long header = lRequest.getDateHeader("If-Modified-Since");
final long current = System.currentTimeMillis();
if (header > 0 && current - header < MAX_AGE_IN_SECS * 1000) {
lResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
return null;
}
try {
if (imageIdParam == null) {
throw new IllegalArgumentException("imageId is null.");
}
// Call to EJB, which is retrieving the image from
// a separate back-end system
final ImageType image = getImage(lHttpSession, Long
.parseLong(imageIdParam));
if (image == null) {
lResponse.sendError(404, IMAGE_DOES_NOT_EXIST);
return null;
}
lResponse.setContentType(image.getType());
lResponse.addDateHeader("Last-Modified", current);
// public: Allows authenticated responses to be cached.
lResponse.setHeader("Cache-Control", "max-age=" + MAX_AGE_IN_SECS
+ ", public");
lResponse.setHeader("Expires", null);
lResponse.setHeader("Pragma", null);
lResponse.getOutputStream().write(image.getContent());
} catch (final IllegalArgumentException e) {
LogHelper.error(this.getClass(), "Illegal argument.", e);
lResponse.sendError(404, IMAGE_DOES_NOT_EXIST);
} catch (final Exception e) {
LogHelper.error(this.getClass(), "General exception.", e);
lResponse.sendError(500);
}
return null;
}
I've actually removed very little from this method, because there's very little in there that I need to hide from prying eyes--the code is pretty generic, concerned with images, not with business logic. (I changed some of the data type names, but no big deal.)