miércoles, 18 de noviembre de 2015

Solucionar problema de dispositivo en modo de carga cuando se conecta a una pc [ANDROID][ROOT]



Hace pocos días tenia la necesidad de usar mi dispositivo android en modo de depuración en una PC con Windows, pero me lleve la sorpresa de que aun con los drivers instalados (intel para USB) en Windows 8.1 el dispositivo (Asus Zenfone 2 - ASUS_Z00A) no era reconocido.

Resulta que el smartphone -ASUS_Z00A- con el que realice las pruebas no utiliza el software stock de Asus sino que en su lugar usa la versión de CyanogenMod 12.1 unnoficial, y este anteriormente si permitía la conexión a una PC mediante cable USB ya sea MTP o PTP (pues se tuvo que usar adb y fastboot para la instalación).

Las primeras pruebas a como seria lo mas lógico fueron conectar el dispositivo por medio de un cable USB a la PC, pero lo más extraño y lo que me llamo mas la atención fue el hecho de que el administrador de dispositivos de Windows ni siquiera daba señales de vida de algún nuevo dispositivo conectado, por lo que pensé que el cable USB necesitaba ser el original del dispositivo (si, lo sé, algo descabellado de pensar). Luego cuando tuve acceso al cable USB original descarte que fuera necesario el cable original pues el resultado era el mismo.

Descartada mi primera idea proseguí a buscar en el foro de CyanogenMod unofficial para el Asus Zenfone 2 en busca de otra persona con el mismo problema y entonces encontré la solución. Resulta que por alguna extraña razón la configuración para la conexión vía USB a la PC estaba en modo "charging" por defecto, por lo que debía de configurarse las opciones de MTP y adb. Esto ocasionaba que en la pantalla de Ajustes > Almacenamiento > Conexión con computadora por USB mostrara un mensaje de "el dispositivo se encuentra desconectado" (cuando debería mostrar otra pantalla con una lista para seleccionar MTP/PTP/Carga), asimismo cuando se miraba en las opciones de desarrollo la opción de depuración, esta no se podía activar debido a que el dispositivo estaba en modo de carga.


Dispositivo no encontrado por adb

Para solucionar el problema debemos seguir los siguientes pasos:
  • Instalar los drivers USB de tu dispositivo en caso que no lo hayas hecho anteriormente.
  • Instalar la app Terminal emulator desde la play store.
  • Abrir la app de terminal y escribir lo siguiente:
    • su [enter] y dar permisos de súper usuario (ROOT)
    • setprop sys.usb.config mtp,adb

  • Ir a Ajustes > Almacenamiento > Menu > Conexion con computadora por USB y seleccionar MTP

En este punto ya deberíamos poder ver nuestro dispositivo usando el protocolo MTP en la ventana de Equipo.



Sin embargo necesitaba activar las opciones de desarrollo! por lo que debemos seguir los siguientes pasos:
  •  Nos iremos al administrador de dispositivos de Windows y veremos algo así:


  •  Actualizamos el driver del dispositivo MTP que aparece con un icono de advertencia:






 
Driver adb para dispositivo intel

Ahora podemos ver nuestro dispositivo como adb desde el administrador de equipos de Windows:



Activamos las herramientas de desarrollo y usando el comando adb desde la consola podemos conectar el dispositivo android:




Y ¡listo! Ojala a alguien le pueda servir, Saludos.

NOTA: Las imágenes de la solución fueron desde Windows 7.

Recursos/Fuentes:

domingo, 23 de agosto de 2015

Bajar la calidad de varios mp3 en una carpeta usando avconv y un script bash nivel noob en ubuntu




Hace unos días necesitaba bajar la calidad de audio de algunos archivos mp3 a 128kb/s, por lo que recordé la herramienta avconv que pertenece al proyecto Libav y que es la que sustituye a ffmpeg en la actualidad. Sabia que avconv era capaz de hacer este trabajo, pero lo que no sabia es que solamente podía hacerlo uno por uno y esto resultaba muy engorroso para mi, pues tenia cerca de unos 100 archivos, debido a esto decidí buscar una pequeña solución vía la madre de todas las sabidurías google.com.

Primero pensé que avconv tendría alguna forma de especificar un directorio de salida para los archivos convertidos (algo así como un -o <directorio>), pero aparentemente esto no es así, y la solución que encontré en unix.stackexchange fue crear un pequeño script bash para eso.

Para realizar la prueba se necesita tener instalado libav-tools, mediante el siguiente comando en la terminal:

sudo apt-get install libav-tools
Originalmente el script bash que probé fue:

#!/bin/bash
for i in *.mp3 ; do 
    avconv -i "$i" -ab 128k "./mp3/$i".mp3
done
guarde el archivo en formato .sh (shell script) y procedí a realizar una prueba.



Lo primero que se debe hacer para poder ejecutar el script es darle permisos de ejecución con el comando chmod:

sudo chmod +x mp3_test.sh



Mi carpeta de prueba contiene tres archivos mp3 y el script bash. Para ejecutar un script bash se utiliza ./<nombre de script>. Ejecute el script bash y…… ERROR! Entonces me di cuenta que el script recorría todos los archivos pero para cada archivo dio el error:

./mp3/Gorillaz-stylo.mp3.mp3: No such file or directory



Esto era debido a que la carpeta mp3 no estaba creada, esto se resolvía creando una carpeta manualmente, pero mi intensión era que el script fuera un poco mas “inteligente” para facilitar el trabajo. Ademas estaba agregando .mp3 al final de cada nombre de cada archivo, por lo que procedí a modificar el script quedando de la siguiente forma:

#!/bin/bash

if [ ! -d "mp3" ]; then
   mkdir "mp3"
fi

for i in *.mp3 ; do
   avconv -i "$i" -ab 128k "./mp3/$i"
done
Básicamente lo que agregue fue una validación que verifica si la carpeta mp3 no esta creada, se creara automáticamente, luego de esto ejecute el script nuevamente y la carpeta ahora es creada automáticamente por el script y los mp3 tendran un bitrate de 128kb/s que fue lo especificando en el script.



El objetivo hasta aquí ya se había logrado pero pensé: ¿Que tal si desea otra carpeta de salida o definir otro bitrate para los mp3? Por lo que procedí a modificar un poco el script:

#!/bin/bash

# Mostramos un mensaje en la terminal solicitando la carpeta de salida
# y almacenamos el nombre en una variable outputFolder con un read
echo 'Output folder (create folder first):'
read outputFolder

# Mostramos un mensaje en la terminal solicitando el bitrate del mp3
# y almacenamos el numero en una variable bitrate con un read
echo 'Bitrate (Eg. 96, 128, 320):'
read bitrate

# Se valida si el usuario no ingreso un nombre se establece por defecto mp3
if [ -z "$outputFolder" ]
then
   outputFolder=mp3
fi

# Se valida si el usuario no ingreso un bitrate se establece por defecto 128
if [ -z "$bitrate" ]
then
   bitrate=128
fi

# Se valida si no existe el folder, lo crea automaticamente
if [ ! -d "$outputFolder" ]; then
   mkdir $outputFolder
fi

# Recorre cada mp3 de la carpeta y procede a convertirlo
for i in *.mp3 ; do
   avconv -i "$i" -ab "$bitrate"k "$outputFolder/$i"
done
de ahora en adelante el script mostrara dos mensajes:




Nota: El script es bien básico y no acepta nombre de carpetas con espacios por lo que dará un error. Si se desea profundizar acerca de el funcionamiento de un script bash se puede leer algunos recursos que me han servido a mi:

Ojala les sea de utilidad, les dejo el link de descarga del script comentado junto con los links que me fueron utiles para realizarlo: Descargar script bash.

domingo, 28 de junio de 2015

Instalar xposed framework en android lollipop 5.1.1 32bits y sdk 22 [ROOT]



Buenas a todos, les traigo un pequeño tutorial de como instalar xposed framework en android 5.1.1. Primero que nada debo mencionar que se realizo el proceso en un nexus 4 con android lollipop 5.1.1 y rom SAOSP.

NOTA: No me hago responsable de cualquier daño ocurrido después de el proceso. Si el smartphone se brickea o aparecen bootloops infinitos queda bajo tu responsabilidad. El proceso me funciono a mi perfectamente pero eso no es garantía de que a todos les funcionara igual. Recuerda que esta es una versión alpha de xposed para lollipop.

El hilo oficial de xposed framework para lollipop permite la descarga de los archivos necesarios para android lollipop con sdk 21 que son:

  • xposed-sdk21-arm-*.zip: que debe ser flasheado desde el recovery (TWRP en mi caso).
  • XposedInstaller_3.0-alpha*.apk: el apk para administrar los modulos.
  • XposedBridgeApi-20150213.jar: un modulo para desarrolladores que no tomaremos en cuenta en este tutorial.
Nota: si te interesa xposed framework para 64 bits, ve el siguiente link.

He descargado los 2 primeros archivos y he instalado obteniendo el error: Wrong sdk version: 22, expected version 21. Esto es debido a que mi versión de android usa el sdk 22 y el hilo oficial provee los archivos para el sdk 21. Para android 5.0 estos deberían funcionar correctamente. 

Para solucionar esto debemos instalar el archivo zip compatible con el sdk 22 y el apk para administrar los módulos:
Primero reiniciamos nuestro teléfono y entramos a nuestro recovery:



Seleccionamos nuestro archivo de xposed e instalamos:





Recomendablemente hacer un wipe de cache/dalvik y reiniciar nuestro dispositivo, debemos esperar a que se complete la optimizacion de las aplicaciones. Luego debemos instalar el apk de exposed para administrar los modulos:


Habilitar las fuentes desconocidas en caso de ser necesario:

 



En mi caso he instalado un modulo y luego hice un reinicio suave y todo funciona a como se espera:



Aquí el resultado, netease (alias: spotify chino traducido al español):


 



Fuentes:


sábado, 20 de junio de 2015

Crear una directiva angular con una galeria jQuery

Nunca modifiques el DOM desde el controlador, usa directivas, es lo que dicen los chicos del equipo de Angular JS. Hoy vamos a tratar de hacerles un poco de caso, por eso en este post vamos a intentar explicar de manera sencilla como crear una directiva haciendo uso de un plugin de galería creado con jQuery.

Algunas veces se necesita usar un plugin de jQuery con angular, pero de repente no sabemos como hacerlo cuando no estamos tan familiarizados con las directivas de angular. Que usaremos:

Primero creamos la estructura html (código completo al final):

Luego creamos nuestro modulo, nuestro controlador y nuestra directiva:


Nuestra directiva ahora es capaz de mostrar la galería (de momento no pongas atención a la variable del controlador images, la usaremos luego). Veamos algunos aspectos importantes de la directiva:

  • restrict: 'A': 'restringe' la directiva para solo usarse como un atributo, por eso el html en que se llama la directiva es: <div simple-cycle></div>. Podemos hacer que la directiva tambien sea un elemento agregando la letra 'E'. Para mas información ver Creating Custom Directives.
  • replace: true: indica que el template de la directiva sustituirá el elemento en que se definió la directiva, en este caso el <div>. Para mas información ver la sección de $compile (Nota: replace esta deprecated porque sera removido en la version 2 de angular).
  • template: 'nuestro template': lo que queremos que la directiva muestre como html.
  • link: es la funcion que se ejecuta cuando luego que el elemento y el template de la directiva se ha creado en el DOM. Aqui colocamos nuestra instancia del cycle.
Hasta ahora nuestra directiva crea nuestro plugin, pero no es tan robusta, supongamos que queremos que nuestra directiva sea capaz de crear una galería a partir de una serie de imágenes que tengamos en nuestro controlador, mmmm estas recordando la variable images ??? para eso crearemos otra directiva:


Ahora podemos observar lo siguiente:

  • scope: {pics: '=' } le indicamos a la directiva que tenga un scope aislado del controlador 'Ctrl', y que por medio de un atributo pics le enviaremos una variable que sera un arreglo de imágenes.
  • template: nuestro template ahora contiene un ngRepeat y un ngSrc.
    • ng-repeat="item in pics": iteramos la variable pics (arreglo) y almacenamos cada elemento en una variable item.
    • ng-src="{{item.url}}": recordemos que nuestra variable images del controlador 'Ctrl' contiene objetos con una propiedad url.
  • $timeout: lo inyectamos en la directiva para esperar 300 milisegundos y crear la instancia del plugin. Este tiempo es necesario para esperar que el ngRepeat cree todos los elementos <img> del template.

Ahora modificamos nuestro html para agregar nuestra nueva directiva:



Notemos ahora que por medio del atributo pics 'pasamos' nuestra variable del controlador images y ya la podemos utilizar desde la directiva. Excelente ahora nuestra directiva es dinamica!! :)

Pero.... quizás te preguntes 300 milisegundos es suficiente???? mi respuesta es: si y quizás no... SI, porque en este momento la directiva funciona xD es decir con pocas imágenes funciona pero con unas 1000, no estoy seguro (jamas he hecho la prueba) pero si entonces en este momento estas diciendo algo como: 'a este mae le pica el cheto.... no puede hacer eso porque en un momento no va a funcionar.... o con otro plugin que necesite mas datos se va a quebrar'. Tranquilo, te dejo otra opción, esperar a que el ultimo elemento del ngRepeat este creado para crear la instancia del plugin.

Entonces vamos de nuevo a modificar nuestra directiva:


Simplemente lo que hacemos es comprobar cuando el ngRepeat crea el ultimo elemento usando la variable $last (bool) y la directiva ngInit. La directiva ngInit llamara a nuestra función initFunction que sera la que realice la validación.

Eso es todo, espero que les ayude un poco, hasta la próxima, saludos.

Puedes ver el ejemplo completo en el siguiente plunkr.

NOTA: El post pretendía ser mucho mejor, pero blogger no lo pone fácil y crear un resaltado de sintaxis no me funciono, disculpas por un post de tan baja calidad, espero que el código en plunker pueda dejarlos mas claro. Hubiera querido ser mas claro desde el post pero lamentablemente no conseguí el resaltado de sintaxis.