Categories
discuss

Android: long click on the child views of a ExpandableListView?

ExpandableListView has a setOnChildClickListener method, but lacks of setOnChildLongClickListener method.

When I added setOnLongClickListener() on child view in getChildView(), whole sublist became completely unclickable (despite of parentView.setOnChildClickListener() present and working before).

How can I enable long clicks on child views?

Answer

I found an answer on Steve Oliver’s blog here: http://steveoliverc.wordpress.com/2009/10/16/context-menus-for-expandable-lists/

You should use onCreateContextMenu() instead of looking for setOnChildLongClickListener(). Here is Steve’s info:

An expandable list supports context menus in pretty much the same way that a standard list does: add a listener for the context menu (when the user has long-pressed on a list item). Unlike a standard list view, however, you probably want to know whether the user has selected a group (expandable item) or a child (sub-item) list item.

Furthermore, you might not want to do anything if the user tries to bring up a context menu on a group item. There might be cases where you would want to do something to all of the children under a group, but in my Librarium application, I wanted to ignore group items and present the context menu only for children.

First, you need to know when the context menu is going to be created so that you can identify whether the user pressed on a group or a child. If they pressed on a group, then cancel the context menu. This also gives us a chance to get the text of the child item, so that we can put it into the header of the context menu.

public void onCreateContextMenu(ContextMenu menu, View v,
                                ContextMenuInfo menuInfo)             
{
  super.onCreateContextMenu(menu, v, menuInfo);

  ExpandableListView.ExpandableListContextMenuInfo info =
    (ExpandableListView.ExpandableListContextMenuInfo) menuInfo;

  int type =
    ExpandableListView.getPackedPositionType(info.packedPosition);

  int group =
    ExpandableListView.getPackedPositionGroup(info.packedPosition);

  int child =
    ExpandableListView.getPackedPositionChild(info.packedPosition);

  // Only create a context menu for child items
  if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) 
  {
    // Array created earlier when we built the expandable list
    String page =mListStringArray[group][child];

    menu.setHeaderTitle(page);
    menu.add(0, MENU_READ, 0, “Read page”);
    menu.add(0, MENU_EDIT, 0, “Edit page”);
    menu.add(0, MENU_FAVORITE, 0, “Add page to favorites”);
    menu.add(0, MENU_EXPORT, 0, “Export page to file”);
    menu.add(0, MENU_DELETE, 1, “Delete page”);
  }
}

Secondly, create the Context Menu:

public boolean onContextItemSelected(MenuItem menuItem) 
{
  ExpandableListContextMenuInfo info = 
    (ExpandableListContextMenuInfo) menuItem.getMenuInfo();

  int groupPos = 0, childPos = 0;

  int type = ExpandableListView.getPackedPositionType(info.packedPosition);
  if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) 
  {
    groupPos = ExpandableListView.getPackedPositionGroup(info.packedPosition);
    childPos = ExpandableListView.getPackedPositionChild(info.packedPosition);
  }

  // Pull values from the array we built when we created the list
  String author = mListStringArray[groupPos][0];
  String page = mListStringArray[groupPos][childPos * 3 + 1];
  rowId = Integer.parseInt(mListStringArray[groupPos][childPos * 3 + 3]);

  switch (menuItem.getItemId()) 
  {
    case MENU_READ:
      readNote(rowId);
      return true;

    case MENU_EDIT:
      editNote(rowId);
      return true;

    // etc..

    default:
      return super.onContextItemSelected(menuItem);
  }
}

That’s it. Now users can long-press on an item in an expandable list, and get the context menu if it’s a child item.

Categories
discuss

How to convert InputStream to FileInputStream

I have this line in my program :

InputStream Resource_InputStream=this.getClass().getClassLoader().getResourceAsStream("Resource_Name");

But how can I get FileInputStream from it [Resource_InputStream] ?

Answer

Use ClassLoader#getResource() instead if its URI represents a valid local disk file system path.

URL resource = classLoader.getResource("resource.ext");
File file = new File(resource.toURI());
FileInputStream input = new FileInputStream(file);
// ...

If it doesn’t (e.g. JAR), then your best bet is to copy it into a temporary file.

Path temp = Files.createTempFile("resource-", ".ext");
Files.copy(classLoader.getResourceAsStream("resource.ext"), temp, StandardCopyOption.REPLACE_EXISTING);
FileInputStream input = new FileInputStream(temp.toFile());
// ...

That said, I really don’t see any benefit of doing so, or it must be required by a poor helper class/method which requires FileInputStream instead of InputStream. If you can, just fix the API to ask for an InputStream instead. If it’s a 3rd party one, by all means report it as a bug. I’d in this specific case also put question marks around the remainder of that API.

Categories
discuss

Android: construct a File from an android.net.URI

I have an android.net.URI object (of the kind returned by onActivityResult after MediaStore.ACTION_VIDEO_CAPTURE): it looks like content://media/video/media/33.

I want to convert this into a File object, and only a File object – I need to pass it to another constructor that requires a File.

How can I convert a URI like this to a File object? If I try

File newFile = new File(myURI);

I get an error in Eclipse suggesting that I should convert the URI to a String. Supplying URI.getPath() in the constructor doesn’t help either.

This relates to the ‘How can I convert android.net.uri object to java.net.uri object?‘ question, which unfortunately seems to have no good answer, but I want a File object out, not a java uri.

I don’t mind if I have to write it to a bytestream and back again – whatever is the best way.

Apologies if I’m cross-posting my own question, but I thought I might need to make things a bit clearer.

Answer

How can I convert a URI like this to a File object?

You can’t, in a reliable, SDK-compliant fashion.

“If the table entry is a content: URI, you should never try to open and read the file directly (for one thing, permissions problems can make this fail). Instead, you should call ContentResolver.openInputStream() to get an InputStream object that you can use to read the data. “

(from http://developer.android.com/guide/topics/providers/content-providers.html)

You will need to modify the other code to accept and utilize an InputStream. Or, if the other code is supposed to be modifying the data, it will need to use an OutputStream, a topic also covered in the page linked to above.

Categories
discuss

YSOD Yellow Screen Of Death JavaScript RegExp – Syntax Error

I built up this regex at http://regextester.com to parse YSOD but VS is complaining about a syntax error. I am sure I am missing an escape somewhere but I am coming up blank.

Here is is in original form. any help is appreciated.

var rxYSOD = /<!--s*[(.*?)]:(s*.*s(.*n)*?)s*(at(.*n)*)-->/gs;

UPDATE: Kobi pointed out the obvious and got me moving again. For those who are interested, this is valid JavaScript to test and parse an XMLHttpRequest.responseText for an ASP.net Yellow Screen Of Death (YSOD).

var rxYSOD = /<!--s*[(.*?)]:(s*.*s(.*[nr]*)*?)s*(at(.*[nr]*)*)-->/;
if (rxYSOD.test(text)) {
    // looks like one..
    var ysod = rxYSOD.exec(text);
    errObj = { Message: ysod[2], StackTrace: ysod[4], ExceptionType: ysod[1] };
}

@Kobi – This is the result and the reason I want to parse the html even though I get a 500:

{
 "message": " Unknown web method ValidateUser.rnParameter name: methodNamern",
 "stackTrace": "at System.Web.Script.Services.WebServiceData.GetMethodData(String methodName)rn   at System.Web.Script.Services.RestHandler.CreateHandler(WebServiceData webServiceData, String methodName)rn   at System.Web.Script.Services.RestHandler.CreateHandler(HttpContext context)rn   at System.Web.Script.Services.RestHandlerFactory.GetHandler(HttpContext context, String requestType, String url, String pathTranslated)rn   at System.Web.Script.Services.ScriptHandlerFactory.GetHandler(HttpContext context, String requestType, String url, String pathTranslated)rn   at System.Web.HttpApplication.MapHttpHandler(HttpContext context, String requestType, VirtualPath path, String pathTranslated, Boolean useAppConfig)rn   at System.Web.HttpApplication.MapHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()rn   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)rn",
 "exceptionType": "ArgumentException",
 "errorObject": {
  "Message": " Unknown web method ValidateUser.rnParameter name: methodNamern",
  "StackTrace": "at System.Web.Script.Services.WebServiceData.GetMethodData(String methodName)rn   at System.Web.Script.Services.RestHandler.CreateHandler(WebServiceData webServiceData, String methodName)rn   at System.Web.Script.Services.RestHandler.CreateHandler(HttpContext context)rn   at System.Web.Script.Services.RestHandlerFactory.GetHandler(HttpContext context, String requestType, String url, String pathTranslated)rn   at System.Web.Script.Services.ScriptHandlerFactory.GetHandler(HttpContext context, String requestType, String url, String pathTranslated)rn   at System.Web.HttpApplication.MapHttpHandler(HttpContext context, String requestType, VirtualPath path, String pathTranslated, Boolean useAppConfig)rn   at System.Web.HttpApplication.MapHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()rn   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)rn",
  "ExceptionType": "ArgumentException"
 },
 "statusCode": 500,
 "servicePath": "/Authentication_JSON_AppService.axd",
 "useGet": false,
 "params": {
  "username": "testingUser",
  "password": "testingUser",
  "customCredential": null
 },
 "methodName": "ValidateUser",
 "__typeName": "Salient.ScriptModel.WebServiceError"
}

Answer

Firefox says:

Error: invalid regular expression flag s
Source Code:
var rxYSOD = /<!--s*[(.*?)]:(s*.*s(.*n)*?)s*(at(.*n)*)-->/gs; 

After removing the s it seems ok (of course, it isn’t tested, just parsed correctly).

Categories
discuss

App engine datastore – query on Enum fields

I am using GAE(Java) with JDO for persistence.

I have an entity with a Enum field which is marked as @Persistent and gets saved correctly into the datastore (As observed from the Datastore viewer in Development Console). But when I query these entities putting a filter based on the Enum value, it is always returning me all the entities whatever value I specify for the enum field.

I know GAE java supports enums being persisted just like basic datatypes. But does it also allow retrieving/querying based on them? Google search could not point me to any such example code.

Details:

I have printed the Query just before being executed. So in two cases the query looks like –

SELECT FROM com.xxx.yyy.User WHERE role == super ORDER BY key desc RANGE 0,50

SELECT FROM com.xxx.yyy.User WHERE role == admin ORDER BY key desc RANGE 0,50

Both above queries return me all the User entities from datastore in spite of datastore viewer showing some Users are of type ‘admin’ and some are of type ‘super’.

Answer

For time being, I have replaced the Enums with simple integer constants. Reported this case as an issue in the google app engine : http://code.google.com/p/googleappengine/issues/detail?id=2927

Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..