Transaction is not active: tx=TransactionImple < ac, BasicAction

The Java Blog

This is an exception I was getting while trying to do some hibernate stuff.

It turned out that this is not a hibernate or jboss exception at all. The actual cause of this was a NullPointerException somewhere in the flow of the application. This caused the transaction to end and re-enter a loop when the transaction was not active and this was thrown. So if you ever get this exception I suggest you put some break points in your code and see where it fails. It’s likely that there is an unchecked exception thrown somewhere in your programme.

Ver la entrada original

Inicio de aplicaciones

Muchas de las aplicaciones que vemos en el mercado tienen un inicio algo brusco, ya que pasan de la pantalla de color negro o gris oscuro a la pantalla inicial de la aplicación.

Para lograr un inicio suave durante el arranque de la aplicación Nick Butcher y Katherine Kuan nos recuerdan que Android muestra esta preview basada en el tema de la aplicación principal.

Para lograr una transición mas suave podemos declarar el tema de nuestra aplicación indicando el color de fondo. Por ejemplo:

<style name="AppBaseTheme" parent="android:Theme.Holo.NoActionBar">
<item name="android:windowBackground">@color/red</item>
</style>

smoothlaunch

Mas información
https://plus.google.com/+AndroidDevelopers/posts/VVpjo7KDx4H

TuLista, mi aplicación favorita para las compras ;), estrena versión con menú lateral

Menu Lateral
Hace unos días TuLista publicó la versión 4.00.bX con un cambio importante en su interfaz, añadiendo el menú lateral. Con este menú lateral ahora tenemos un acceso mas rápido a las distintas listas de la compra que llegamos. Normalmente compramos en varios sitios, dependiendo de las tiendas que tengamos alrededor. Ahora mientras hacemos la lista de la compra podemos cambiar de una lista a otra mientras decidimos que compramos y donde: esto lo hacemos de forma sencilla accediendo al menú lateral desde el histórico y pulsando sobre la lista que queremos editar.

Ademas de este menú lateral, también ha cambiado el mecanismo de deslizamiento por otro mucho mas suave.

Si no la tienes todavía, ¿a que esperas a descargarla que es gratis?!!

TuLista para #android

Nexus 7 y la cámara que no responde

Hace poco he  estado usando la cámara para trabajar con las fotos realizadas. El código es sencillo:

Uri uri = Uri.fromFile(mTempPictureFile)
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, TAKE_PICTURE_SUBACTIVITY);

El problema viene en donde colocar el fichero temporal.

Como la SDK de android tiene un método para tal propósito pues lo he usado.

File mTempPictureFile = File.createTempFile ("imagen", "jpg");

No se si en muchos dispositivos, pero esto inicialmente funciona aunque posteriormente he podido comprobar que coloca las imágenes en el raiz, y eso me parece muy poco conveniente.

Y decía en muchos porque no en todos. En la nexus 7 y en creo que en los samsumg III produce un curioso efecto, y eso que después de hacer la foto, no te permite aceptarla para usarla. En ambos casos, el software que controla la cámara te muestra una previsualización para aceptar o no la foto con un a X y un ✓ pero no permite confirmarla. Y para colmo, no deja unas trazas claras del problema.

La solución a este problema ha consistido en cambiar la ubicación del fichero, usando algo como:
File cacheDir = this.getExternalCacheDir();
cacheDir.mkdirs();
mTempPictureFile = new File(cacheDir,"waypointCapture.jpg");
mTempPictureFile.delete();
Uri uri = Uri.fromFile(mTempPictureFile);

Bueno, espero que os sea útil si os habéis encontrado con este problema.

Comartid!🙂

ListActivity + ActionBarActivity

A muchos se nos ha ocurrido la feliz idea de añadir el ActionBar a nuestras aplicaciones que tienen algún Activity extendiendo de la clase ListActivity.

tulistaProSi nuestra aplicación además es compatible con versiones posteriores a android 2.1 debemos hacer que nuestro Activity extienda de ActionBarActivy y aquí comienzan la complicación: a los chicos de Google no se les ocurrió añadir un “ListActionBarActivity” o algo por el estilo.

Lo que es evidente es que no podemos extender de varias clases ya que java no soporta la multi-herencia así que nos toca buscar otro camino.

Se me ocurren dos soluciones así de pronto:

  1. Implementar nosotros mismos la gestión del ListView.
  2. Implementar una versión de ListActivity que extienda de ActionBarActivity y que luego nosotros usemos.

Vamos por el segundo caso y así, si tenemos varias activities que extiendan de ListActivity las solucionamos todas a la vez.

Como seguro que ya sabéis, desde hace algunas versiones Google incluye la posibilidad de descargar los fuentes de la SDK así que el primer paso es buscar el código fuente del ListView para buscar nuestra inspiración en él para crear nuestra clase ListActionBarActivity.

Hay algunas cosas que no nos sirven y tendremos que hacerlas ligeramente diferentes:

onContentChanged

public void onContentChanged() {
     super.onContentChanged();
     View emptyView = findViewById(com.android.internal.R.id.empty);
     mList = (ListView)findViewById(com.android.internal.R.id.list);
     [...]
}

Si usamos ese código tal cual dará error ya que la clase el contenido del paquete com.android.internal no está disponible para usarlo directamente. Lo que haremos será usar el paquete android.R para referirnos a él quedando el código como:

View emptyView = findViewById(android.R.id.empty);
mList = (ListView)findViewById(android.R.id.list);

Otro método que dará fallos es:
ensureList

private void ensureList() {
   if (mList != null) {
       return;
   }
   setContentView(com.android.internal.R.layout.list_content_simple);
}

Siempre deberíamos tener el contenido indicado no se me ocurre un activity sin su layout, así que de momento lanzaré una excepción a ver si averiguo cuando se puede dar esta situación y así resolverlo.

private void ensureList() {
   if (mList != null) {
     return;
   }
   //setContentView(com.android.internal.R.layout.list_content_simple);
   throw new RuntimeException("Esuring list but list is null");
}

Con estos cambio además de todos los cambios necesarios para añadir al ActionBar que ya vienen en la guía oficial debería funcionar en dispositivos con android v3.0 pero… no lo hará en dispositivos anteriores. ¿Por qué? Parece que la actual librería android.support.v7.app.ActionBarActivity ejecuta el método onContentChanged antes de que se hayan cargado los xml de nuestro layout, por lo que los métodos findViewById devolverán null. Aquí tenéis una entrada al respecto.

¿Cómo lo solucionamos? Pues tendremos que retrasar la inicialización de nuestras variables internas. Añadimos una variable de clase booleana para guardar cuando se puede ejecutar la búsqueda de nuestro ListView.

public void onContentChanged() {
  super.onContentChanged();
  if(mContentCharged){
     View emptyView = findViewById(android.R.id.empty);
     mList = (ListView) findViewById(android.R.id.list);
     [...]
  }
}

Y sobreescribimos el método setContentView que usamos (normalmente este):

@Override
public void setContentView(int layoutResID) {
  super.setContentView(layoutResID);
  mContentCharged = true;
  onContentChanged();
}

Creo que eso es todo!

Si te ha gustado ¡ayúdame a difundirlo! ¡Compártelo!!😀

Cursor already closed

¿Te sale este error cuando intentas cambiar el cursor de tu adapter?

java.lang.RuntimeException: Unable to resume activity …
java.lang.IllegalStateException: trying to requery an already closed cursor android.database.sqlite.SQLiteCursor

Parece que la gestion de los cursores de SimpleCursorAdapter ha cambiado en las versiones SDK > 11.

Si usas un adapter SimpleCursorAdapter para provisionar tu ListView, y has delegado la gestión del cursor al Activity haciendo startManagingCursor es posible que si cambias el cursor del adapter con changeCursor, te de un error de cursor actualmente cerrado…

Algo así como:

//Inicializamos el adapter en el constructor usando un cusor nulo
SimpleCursorAdapter mCursor = SimpleCursorAdapter(Context, int, Cursor, String[], int[])

[...]
//Presentamos los datos consultando la BBDD
Cursor productosCursor = mListaCompraDao.fetchAllProductosSeleccionados(listActive)
startManagingCursor(productosCursor);
mCursor.changeCursor(productosCursor);

Pues este código, que funciona perfectamente en versiones de SDK < 11 da un error cuando se retoma el activity, por ejemplo lanzando un subactivity y volviendo luego a este.

Para que funcionen en veresiones superiores, hay que quitarle la gestion del cursor antiguo al activity antes de cambiarlo al nuevo.

Algo así como:

if(mCursor.getCursor() != null){
stopManagingCursor(mCursor.getCursor());
mCursor.getCursor().close();
}
//Y ya podemos asignarle el nuevo cursor
startManagingCursor(productosCursor);
mCursor.changeCursor(productosCursor);

¿Te ha gustado? Compártelo!!😀