Resultados 1 al 7 de 7


[GUÍA] - Una forma más sencilla y rápida de añadir botones + HorizontalScrollView para poder acceder a ellos


Estás en el tema [GUÍA] - Una forma más sencilla y rápida de añadir botones + HorizontalScrollView para poder acceder a ellos dentro del subforo Tutoriales - Samsung Galaxy S III en Esp-Desarrolladores. El otro día os expliqué en este hilo cómo nos podíamos fácilmente hacer una pantalla de ajustes personalizada. En esta ocasión os voy a contar una forma muy sencilla que me he trabajado para añadir botones de acceso directo en otras partes del sistema, de una forma bastante más sencilla que otras que podéis encontrar. No se si es la mejor forma pero desde luego facilita mucho el trabajo. Para ello, voy a poner como ejemplo añadir dos botones: un acceso directo al jobmanager y otro...



Este tema tuvo 4619 Visitas y 6 Respuestas

Actualmente hay 1 usuarios viendo este tema. (0 miembros y 1 visitantes)

  1. #1
    Fecha de ingreso
     Mar-2013
    Mensajes
     12,594
    Gracias Enviadas
    8,662
    Agradecido 22,992 Veces en 7,864 Posts


    El otro día os expliqué en este hilo cómo nos podíamos fácilmente hacer una pantalla de ajustes personalizada.

    En esta ocasión os voy a contar una forma muy sencilla que me he trabajado para añadir botones de acceso directo en otras partes del sistema, de una forma bastante más sencilla que otras que podéis encontrar. No se si es la mejor forma pero desde luego facilita mucho el trabajo.

    Para ello, voy a poner como ejemplo añadir dos botones: un acceso directo al jobmanager y otro acceso directo a la ventana de ajustes que nos creamos el otro día.
    Este ejemplo está hecho sobre jkay y en concreto los vamos a poner en jkay_status_bar_expanded_header.xml, siendo el método igualmente válido para aquellas roms que no tienen jkay, en este caso en tw_status_bar_expanded_header.xml

    Veremos qué es accesible mediante este método y cómo podemos acceder a aplicaciones u otras partes del sistema.

    El método es sencillo: Creamos un método por cada botón en el smali adecuado e invocamos dicho método mediante la función onclick dentro de un imageview.

    Por cada imageview (será nuestro botón) repetimos el método modificando la acción invocada únicamente.

    La acción o actividad invocada tiene que ser "visible", luego veremos qué limitaciones tiene y cómo podemos solucionarla.

    Empezamos

    En el caso ejemplo, los métodos que creamos los pondremos, dentro de SystemUI, en smali\com\android\systemui dentro de SystemUIService.smali

    justo después de # virtual methods

    El código smali, que invoca la acción de la actividad visible del Jobmanager sería el siguiente (Ejemplo llamar a la actividad principal del JobManager - administrador de tareas)

    Código:
    .method public GrxBtnJobManager(Landroid/view/View;)V
        .locals 3
        .parameter "v"
    
        .prologue
        .line 1717
    	
    
        invoke-virtual {p1}, Landroid/view/View;->getContext()Landroid/content/Context;
    
        move-result-object v0
    
        new-instance v1, Landroid/content/Intent;
    
        const-string v2, "com.sec.android.app.controlpanel.MAIN"
    
        invoke-direct {v1, v2}, Landroid/content/Intent;-><init>(Ljava/lang/String;)V
    
        const/high16 v2, 0x1000
    
        invoke-virtual {v1, v2}, Landroid/content/Intent;->setFlags(I)Landroid/content/Intent;
    
        move-result-object v1
    
        invoke-virtual {v0, v1}, Landroid/content/Context;->startActivity(Landroid/content/Intent;)V
    	
    
        invoke-virtual {p1}, Landroid/view/View;->getContext()Landroid/content/Context;
    
        move-result-object v1
    
        const-string v2, "statusbar"
    
        invoke-virtual {v1, v2}, Landroid/content/Context;->getSystemService(Ljava/lang/String;)Ljava/lang/Object;
    
        move-result-object v0
    
        check-cast v0, Landroid/app/StatusBarManager;
    
        .local v0, sbm:Landroid/app/StatusBarManager;
        invoke-virtual {v0}, Landroid/app/StatusBarManager;->collapse()V
    
        return-void
    .end method
    Se distinguen dos partes,:
    - la invocación de la actividad, en azul, en este caso "com.sec.android.app.controlpanel.MAIN".
    - El código en morado corresponde a la tarea de cerrar la cortina una vez hayamos realizado la llamada.

    Para saber qué acción puede ser invocada dentro de una apk, en este caso el jobmanager, tendremos que descompilarla y abrir su AndroidManifest.xml
    En el ejemplo podremos ver que la acción (action) que podemos invocar es la puesta en el código. Si pusiéramos "android.intent.action.MAIN" nos saltaría un pop-up con prácticamente todas las apks que tengamos instaladas.
    Por tanto, este código vale para cuando encontremos dentro de las apks algo como
    Código:
     
     <action android:name="com.sec.android.app.controlpanel.MAIN" /> dentro de un intent-filter a su vez dentro de una activity.
    Otro día os pongo cómo modificar esa función para evitar esta "limitación", en realidad es añadir unas 10 líneas de código más, de forma que realicemos la llamada formando la categoría, permisos... y demás elementos necesarios, para lo cual hay que editar los manifiest de la apk en cuestión.
    Encontraréis muchas apks con varios action disponibles y si no los encontráis...pues hacemos lo que he hecho yo en el SecSettings para acceder a la pantalla de ajustes que os expliqué el otro día.

    En la guía que os puse sobre cómo crearse una pantalla propia, os comenté que usaba dos smalies, uno para pintar la pantalla y meter lógica en él y otro para que pudiera ser invocado vía una actividad.
    En realidad, con uno bien montado podría valer, pero yo me he dejado dos para ir metiendo lógica, je, je..

    Bien, aquella guía acababa comentando cómo modificar el androidmanifiest.xml, para dar visibilidad al montaje, declarando una actividad.
    Si recordáis era así:

    Código:
    <activity android:label="@string/grx_title_ajustes_rom" android:icon="@drawable/grx_ajustes_launcher" android:name="GrxAjustesEspeciales_act" android:parentActivityName="Settings">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                </intent-filter>
    </activity>
    Pues bien, según lo que os he dicho, para esta forma de crear botones, esto no nos valdría, por lo que lo único que tenemos que hacer es modificar ese código por este (o similar) en el manifiest.xml del SecSettings que quedaría así

    Código:
    <activity android:label="@string/grx_title_ajustes_rom" android:icon="@drawable/grx_ajustes_launcher" android:name="GrxAjustesEspeciales_act" android:parentActivityName="Settings">
                <intent-filter>
                    <action android:name="android.intent.action.GRXAJUSTES" />
                    <category android:name="android.intent.category.DEFAULT" />
                </intent-filter>
    </activity>
    De esta forma, la actividad será vista tanto por nuestro botón, como por un laucher tipo nova, etc., que nos permite crear también un acceso directo en nuestra home.

    Hecha esta modificación, nuestro código smali del método que pondremos dentro de SystemUIService.smali para invocar la pantalla de ajustes personalizada desde un botón en jkay o tw status_expanded_header.xml quedaría así, y ya tenemos dos botones más.; Es el mismo código, cambiando el nombre del método y el action de la actividad llamada.


    Código:
    .method public GrxBtnAjustesGrx(Landroid/view/View;)V
        .locals 3
        .parameter "v"
    
        .prologue
        .line 1717
        invoke-virtual {p1}, Landroid/view/View;->getContext()Landroid/content/Context;
    
        move-result-object v0
    
        new-instance v1, Landroid/content/Intent;
    
        const-string v2, "android.intent.action.GRXAJUSTES"
    
        invoke-direct {v1, v2}, Landroid/content/Intent;-><init>(Ljava/lang/String;)V
    
        const/high16 v2, 0x1000
    
        invoke-virtual {v1, v2}, Landroid/content/Intent;->setFlags(I)Landroid/content/Intent;
    
        move-result-object v1
    
        invoke-virtual {v0, v1}, Landroid/content/Context;->startActivity(Landroid/content/Intent;)V
    
        invoke-virtual {p1}, Landroid/view/View;->getContext()Landroid/content/Context;
    
        move-result-object v1
    
        const-string v2, "statusbar"
    
        invoke-virtual {v1, v2}, Landroid/content/Context;->getSystemService(Ljava/lang/String;)Ljava/lang/Object;
    
        move-result-object v0
    
        check-cast v0, Landroid/app/StatusBarManager;
    
        .local v0, sbm:Landroid/app/StatusBarManager;
        invoke-virtual {v0}, Landroid/app/StatusBarManager;->collapse()V
    
        return-void
    .end method
    - Es fácil optimizar el código cuando ponemos muchos botones, por ejemplo creando un método para cerrar la cortina u otro método para pasar el nombre de la actividad y realizar el asunto.

    Ahora hacemos la parte más sencilla.

    - Para invocar este código y siguiendo el ejemplo, en jkay (o tw) _status_bar_expanded_header, en res -> layout, añadiremos código como el siguiente(caso jobmanager):

    Código:
    <ImageView android:layout_gravity="center_vertical" android:layout_width="wrap_content" android:layout_height="fill_parent" android:src="@drawable/grx_iconbtn_jobmanager" android:onClick="GrxBtnJobManager" />
    Donde:
    - androidnClick="GrxBtnJobManager" es la forma en la que invocamos la ejecución del código anterior. En el caso de systemui averigué cual era el smali que era invocado por la función onClick vía logcat, puesto que pensaba que sería PhoneStatusBar.smali pues es donde se suelen programar estos botones (por ejemplo el de ir a ajustes está ahí). Pues no, en este caso es SystemUIService.smali y no podemos realizar llamadas hacia PhoneStatusBar.smali para realizar la animación de cerrar la cortina, por lo que tuve que desarrollar el código que os pongo.

    - android:src es o bien una imagen en drawable-xhdpi o bien si queremos que se produzca el efecto de pulsar un xml en el directorio drawable que se llame grx_iconbtn_jobmanager.xml y que dentro contendrá algo como
    Código:
    <?xml version="1.0" encoding="utf-8"?>
    <selector
      xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:state_pressed="true" android:drawable="@drawable/grx_iconbtn_jobmanager_pres" />
        <item android:drawable="@drawable/grx_iconbtn_jobmanager_normal" />
    </selector>
    Colocar los botones es una cuestión de maquetación. A continuación os muestro qué solución he tomado para poder tener todos los botones de Jkay y estos dos botones. He añadido un HorizontalScrollView en jkay_status_bar_expanded_header de forma que tendremos un scroll y podremos acceder a todos los botones que queramos.

    Código:
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout android:gravity="center_vertical" android:orientation="horizontal" android:background="#ff000000" android:layout_width="fill_parent" android:layout_height="39.0dip" android:baselineAligned="false"
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui">
        <LinearLayout android:gravity="left|center" android:orientation="horizontal" android:background="#ff000000" android:layout_width="fill_parent" android:layout_height="wrap_content">
            <HorizontalScrollView android:scrollbars="none" android:fadingEdge="vertical" android:fadingEdgeLength="20.0px" android:layout_width="wrap_content" android:layout_height="@dimen/tw_notification_panel_header_height" android:fillViewport="false" android:overScrollMode="never">
                <LinearLayout android:gravity="left|center" android:orientation="horizontal" android:background="#ff000000" android:layout_width="fill_parent" android:layout_height="wrap_content">
                    <com.android.systemui.statusbar.policy.BigClock android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock" android:id="@id/clock" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="4.0dip" android:layout_marginTop="-3.0dip" android:singleLine="true" systemui:ampmSmall="true" />
                    <com.android.systemui.statusbar.policy.DateView android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date" android:ellipsize="none" android:id="@id/date" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="8.0dip" android:layout_marginRight="4.0dip" android:maxLines="2" />
                    <com.android.systemui.statusbar.RotationToggle android:id="@id/rotation_lock_button" android:visibility="gone" android:clickable="true" android:layout_width="32.0dip" android:layout_height="32.0dip" android:layout_margin="8.0dip" android:button="@drawable/ic_notify_rotation" android:contentDescription="@string/accessibility_rotation_lock_off" />
                    <Space android:layout_width="4.0dip" android:layout_height="0.0dip" android:layout_weight="1.0" />
                    <RelativeLayout android:background="@drawable/tw_quick_panel_setting_button_bg" android:focusable="true" android:layout_width="42.0dip" android:layout_height="39.0dip">
                        <ImageView android:layout_gravity="center_vertical" android:paddingLeft="8.0dip" android:layout_width="wrap_content" android:layout_height="fill_parent" [B]android:src="@drawable/grx_iconbtn_grxajustes" android:onClick="GrxBtnAjustesGrx[/B]" />
                    </RelativeLayout>
                    <RelativeLayout android:background="@drawable/tw_quick_panel_setting_button_bg" android:focusable="true" android:layout_width="42.0dip" android:layout_height="39.0dip">
                        <ImageView android:layout_gravity="center_vertical" android:layout_width="wrap_content" android:layout_height="fill_parent" android:src="@drawable/grx_iconbtn_jobmanager" android:onClick="GrxBtnJobManager" />
                    </RelativeLayout>
                    <Space android:layout_width="0.0dip" android:layout_height="0.0dip" android:layout_weight="1.0" />
                    <ImageView android:layout_width="1.0dip" android:layout_height="25.0dip" android:layout_marginTop="7.0dip" android:layout_marginBottom="7.0dip" android:src="@drawable/tw_quick_panel_plnm_setting_dv" />
                    <RelativeLayout android:id="@id/recent_button" android:background="@drawable/tw_quick_panel_setting_button_bg" android:focusable="true" android:visibility="gone" android:layout_width="60.0dip" android:layout_height="39.0dip">
                        <ImageView android:id="@id/recent_button_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/jkay_ic_sysbar_recent" android:scaleType="center" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:contentDescription="@string/accessibility_recent" />
                    </RelativeLayout>
                    <RelativeLayout android:id="@id/lock_button" android:background="@drawable/tw_quick_panel_setting_button_bg" android:focusable="true" android:visibility="gone" android:layout_width="60.0dip" android:layout_height="39.0dip">
                        <ImageView android:id="@id/lock_button_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/jkay_ic_sysbar_lock" android:scaleType="center" android:adjustViewBounds="true" android:maxWidth="48.0dip" android:maxHeight="48.0dip" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:contentDescription="@string/accessibility_lock_button" />
                    </RelativeLayout>
                    <RelativeLayout android:id="@id/settings_button" android:background="@drawable/tw_quick_panel_setting_button_bg" android:focusable="true" android:visibility="visible" android:layout_width="59.5dip" android:layout_height="39.0dip">
                        <ImageView android:id="@id/settings_button_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/tw_quickpanel_icon_settings" android:scaleType="center" android:adjustViewBounds="true" android:maxWidth="48.0dip" android:maxHeight="48.0dip" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:contentDescription="@string/accessibility_settings_button" />
                    </RelativeLayout>
                    <RelativeLayout android:id="@id/clearall_button" android:background="@drawable/tw_quick_panel_setting_button_bg" android:focusable="true" android:visibility="gone" android:layout_width="60.0dip" android:layout_height="39.0dip">
                        <ImageView android:id="@id/clearall_button_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_notify_clear_normal" android:scaleType="center" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:contentDescription="@string/accessibility_remove_notification" />
                    </RelativeLayout>
                </LinearLayout>
            </HorizontalScrollView>
        </LinearLayout>
    </LinearLayout>
    Resumen:

    - Averiguamos cómo se llama la acción (action) que podemos invocar de la apk deseada descompilando y analizando androidmanifiest.xm. En caso necesario, modificamos el mismo, si bien al que no tenga experiencia no se lo recomiendo.
    - Insertamos el método, modificando el nombre de la acción. El método llevará el mismo nombre que queramos usar en el onClick
    - En jkay (tw)_status_bar_expanded_header.xml insertamos un ImageView, el icono (en drawable-xhdp) o iconos (en drawable vía un xml) y el onclick con el nombre del método que se encarga de invocar el action
    - Maquetamos e insertamos un HorizontalScrollView como el ejemplo si no tenemos espacio.

    Imágenes en Siguiente Post
    Saludos.

    Última edición por Grouxho; 18-05-13 a las 03:50


  2. Los siguientes 5 Usuarios dieron las gracias a Grouxho Por su Mensaje :

    Frantastik (06-03-14),neovendtta (13-03-14),peble (26-01-14),ramonore99 (06-03-14),xztxkratos (18-05-13)




  3. #2
    Fecha de ingreso
     Mar-2013
    Mensajes
     12,594
    Gracias Enviadas
    8,662
    Agradecido 22,992 Veces en 7,864 Posts


    Imágenes adjuntadas Imágenes adjuntadas


  4. Los siguientes 4 Usuarios dieron las gracias a Grouxho Por su Mensaje :

    juanjose191180 (13-04-14),peble (26-01-14),psanlu (06-03-14),ramonore99 (06-03-14)

  5. #3
    Fecha de ingreso
     Mar-2014
    Mensajes
     63
    Gracias Enviadas
    41
    Agradecido 11 Veces en 9 Posts


    Mañana voy a intentar el tutoriales a ver si tengo suerte, Jejeje



  6. #4
    Fecha de ingreso
     Mar-2014
    Mensajes
     63
    Gracias Enviadas
    41
    Agradecido 11 Veces en 9 Posts


    Una cosa que se me ha ocurrido al leer el tutorial si quiero por ejemplo deslizarme de una pantalla a otra por ejemplo en contactos,favoritos, teléfono, llamadas recientes, como podría hacerlo, o en settings que en mi movil no puedes hacerlo tienes q darle a los botones superiores.
    Gracias por todo


  7. Los siguientes usuarios agradecieron a psanlu por su mensaje :

    Grouxho (06-03-14)

  8. #5
    Fecha de ingreso
     Mar-2013
    Mensajes
     12,594
    Gracias Enviadas
    8,662
    Agradecido 22,992 Veces en 7,864 Posts


    Cita Iniciado por psanlu Ver mensaje
    Una cosa que se me ha ocurrido al leer el tutorial si quiero por ejemplo deslizarme de una pantalla a otra por ejemplo en contactos,favoritos, teléfono, llamadas recientes, como podría hacerlo, o en settings que en mi movil no puedes hacerlo tienes q darle a los botones superiores.
    Gracias por todo

    Enviado desde mi THL W8S mediante Tapatalk
    En la 4.3 es una movida.



  9. #6
    Fecha de ingreso
     Mar-2014
    Mensajes
     63
    Gracias Enviadas
    41
    Agradecido 11 Veces en 9 Posts


    Es 4.2.1


  10. #7
    Fecha de ingreso
     Mar-2013
    Mensajes
     12,594
    Gracias Enviadas
    8,662
    Agradecido 22,992 Veces en 7,864 Posts


    Hay que hacerlo apk x apk. Yo en mi mod para la 4.1.2 lo hice en el settings pero no hay receta...




  11. Los siguientes usuarios agradecieron a Grouxho por su mensaje :

    psanlu (06-03-14)

Permisos de publicación

  • No puedes crear nuevos temas
  • No puedes responder temas
  • No puedes subir archivos adjuntos
  • No puedes editar tus mensajes
  •  


ESP-Desarrolladores

    ESP-Desarrolladores, es una comunidad de desarrollo Android en habla hispana, Aquí encontrarás lo último en Android, ROMs, Kernel, APPs, etc... Pasa y Ponte Cómodo!!! estás en tu casa ;)

Síguenos en

Twitter Facebook Google+ espdesarrolladores - Andyou Youtube RSS Feed