BananaPi BPI-M2Z(H2+) New Image Android4.4 Release 2018-07-09

BananaPi BPI-M2Z(H2+) New Image Android4.4 V1.1 Release 2018-07-09

1.About this release

  • This release is for banana pi M2Z board which is based on Allwinner H2+, and it is based on Android 4.4 operation system with kernel 3.4.

2.M2Z Android 4.4 Features Map

3.Image Links:

  1. HDMI-Version

4.FAQ:

This image doesn’t work. The Etcher SD Burn software says it hasn’t a recognizable boot partition.

Any tips?

Hello,Please use this PhoenixCard to burn Android image:

https://pan.baidu.com/s/18Fo_JhYY02gmxtFw2Ps3rQ

it’s the same way to burn image .

http://wiki.banana-pi.org/Getting_Started_with_M3#Load_your_first_image_on_M3

Stiil getting a problem:image

This image is for BPI-ZERO, did you use this board? if yes, I think maybe your image was damaged, could you download it again?

Yes. My board is the BPI-Z.

I believe the image file is fine (2018-07-09-android4.4_bpi-m2z_hdmi.zip with 378Mb). Maybe the Android burn process using this Phoenix Card is the problem.

There is some other Android image that I can try on it and on BPI-Z?

I tested the linux images (Ubuntu and Armbian) both works fine. The problems I have till now were with Raspbian (wifi didin’t work) and Android doesn’t even boot my BPI-Z board.

For Raspbian you can use wpa_supplicant to enable wifi.

Please see here:http://wiki.banana-pi.org/Getting_Started_with_M2_Zero#WiFi_Client

For Android, Did you try format your sd card before you burn the image?

Hi there. The problem really was the Phoenix Card Software. I followed the steps from https://forum.pine64.org/showthread.php?tid=548 and the burn process worked fine after the steps.

The problem now is the recognition of the mouse and the keyboard.

1 Like

Hi. I am developing a project that involves the “banan pi m2 zero”. The project needs to use android as the operating system and in the banana pi zero devices that I own, it works quite well version 4.4 that you have published. However it is necessary for my project the use of google services (google play services) that in the version of android that you have published are not present. I have managed to install them without problem nevertheless to be able to use the services of the play services the device “banana pi m2 zero” must be registered (you can see the information in www.google.com/android/uncertified/) where they clearly inform of the problem. I would like to know if you have planned to certify pi m2 zero banana to be able to use google services. I think this topic is key to being able to use this wonderful board in my future projects.

Hello, BPI-Zero is a development board,if you want to use google service you could use Android ID to certify board. https://www.google.com/android/uncertified/

and if you have a plan to do a product in your project, you could send email to [email protected].

Thank you. Another question, is there some way, configuration or something that allows the processor not to heat up so much. It’s weird because on this board everything gets pretty hot. the camera, the wifi chip and of course the processor.

Did anyone get the GPIO pins working under Android? Using Raspberian image I can export the Banana Pi’s pins (e.g. “echo 9 > /sys/class/gpio/export” creates PIN 13). This does not work on Android, despite that the same gpio chip exists like in Linux (/sys/class/gpio/gpiochip0). Any ideas?

Hi, I did this class and it works well for me. Use what you need. I hope it helps you.

import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log;

import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException;

/**

  • Created by Alleiny on 17/10/2018. */

// PA0 PA1 PA2 PA3 PA6 PA7 PA8 PA9 PA10 PA11 PA12 PA17 PA18 PA19 PA20 PA21 // PC0 PC1 PC2 PC3 PC4 PC7 // PL2 PL4

public class CBpiM2ZeroGpio {

Handler msgHandler;
Handler stateMachine;
private boolean gpioready;
private int state = 5;
boolean running = false;

public CBpiM2ZeroGpio(Handler msg){
    gpioready = false;
    msgHandler = msg;

    stateMachine = new Handler(  );
    Log.e("myApp","Start Configure Gpio");
    stateMachine.postDelayed( runnableStateMachine,1000 );
}

Runnable runnableStateMachine = new Runnable() {
    @Override
    public void run() {
        switch (state)
        {
            case 0:{// init PA0
                  if(configGpio( "PA0" ))
                  {
                      state++;
                  }
                break;
            }

            case 1:{// init PA1
                if(configGpio( "PA1" ))
                {
                    state++;
                }
                break;
            }

            case 2:{// init PA2
                if(configGpio( "PA2" ))
                {
                    state++;
                }
                break;
            }

            case 3:{// init PA3
                if(configGpio( "PA3" ))
                {
                    state++;
                }
                break;
            }

            case 4:{// init PA6
                if(configGpio( "PA6" ))
                {
                    state++;
                }
                break;
            }

            case 5:{// init PA7
                if(configGpio( "PA7" ))
                {
                    state = 7;
                }
                break;
            }

            case 6:{// init PA8
                if(configGpio( "PA8" ))
                {
                    state++;
                }
                break;
            }

            case 7:{// init PA9
                if(configGpio( "PA9" ))
                {
                    state = 14;
                }
                break;
            }

            case 8:{// init PA10
                if(configGpio( "PA10" ))
                {
                    state++;
                }
                break;
            }

            case 9:{// init PA11
                if(configGpio( "PA11" ))
                {
                    state++;
                }
                break;
            }

            case 10:{// init PA12
                if(configGpio( "PA12" ))
                {
                    state++;
                }
                break;
            }

            case 11:{// init PA17
                if(configGpio( "PA17" ))
                {
                    state++;
                }
                break;
            }

            case 12:{// init PA18
                if(configGpio( "PA18" ))
                {
                    state++;
                }
                break;
            }

            case 13:{// init PA19
                if(configGpio( "PA19" ))
                {
                    state++;
                }
                break;
            }

            case 14:{// init PA20
                if(configGpio( "PA20" ))
                {
                    state++;
                }
                break;
            }

            case 15:{// init PA21
                if(configGpio( "PA21" ))
                {
                    state = 24;
                    gpioready = true;
                }
                break;
            }

            case 16:{// init PC0
                if(configGpio( "PC0" ))
                {
                    state++;
                }
                break;
            }

            case 17:{// init PC1
                if(configGpio( "PC1" ))
                {
                    state++;
                }
                break;
            }

            case 18:{// init PC2
                if(configGpio( "PC2" ))
                {
                    state++;
                }
                break;
            }

            case 19:{// init PC3
                if(configGpio( "PC3" ))
                {
                    state++;
                }
                break;
            }

            case 20:{// init PC4
                if(configGpio( "PC4" ))
                {
                    state++;
                }
                break;
            }

            case 21:{// init PC7
                if(configGpio( "PC7" ))
                {
                    state++;
                }
                break;
            }

            case 22:{// init PL2
                if(configGpio( "PL2" ))
                {
                    state++;
                }
                break;
            }

            case 23:{// init PL4
                if(configGpio( "PL4" ))
                {
                    state++;
                    gpioready = true;
                }
                break;
            }
        }

        if(!gpioready)
        {
            stateMachine.postDelayed( runnableStateMachine,1000);
        }
        else
        {
            Log.e("myApp","Configure Gpio OK");
            Message m = new Message();
            m.arg1 = 0; // gpio config ok
            msgHandler.sendMessage( m );
        }
    }
};

boolean configGpio(String pin)
{
    boolean ret = true;
    FileOutputStream fos ;
    FileWriter fWriter;

    try{
        fos = new FileOutputStream("/sys/class/gpio_sw/" + pin + "/cfg", true);
        fWriter = new FileWriter(fos.getFD());
        fWriter.write("0");
        fWriter.flush();
        fWriter.close();
    }catch(Exception e){
        ret = false;
        try{
            Process p=Runtime.getRuntime().exec("su");
            DataOutputStream dos = new DataOutputStream(p.getOutputStream());
            dos.writeBytes("chmod -R 777 /sys/class/gpio_sw/" + pin + "/*\n");
            dos.writeBytes("exit\n");
            dos.flush();
            dos.close();
            p.waitFor();
        }catch (Exception e1){ }
    }

    return ret;
}

public boolean setDirection(String pin, String direction) // direction -> "in" , "out"
{
    boolean ret = true;
    FileOutputStream fos ;
    FileWriter fWriter;
    String dir = "0";

    if(gpioready)
    {
        if(direction.equals( "inNormal" ) || direction.equals( "inButton" ))
        {
            dir = "0";
        }
        else
        {
            if(direction.equals( "out" ))
            {
                dir = "1";
            }
            else
            {
                return false;
            }
        }

        try{
            fos = new FileOutputStream("/sys/class/gpio_sw/" + pin + "/cfg", true);
            fWriter = new FileWriter(fos.getFD());
            fWriter.write(dir);
            fWriter.flush();
            fWriter.close();
        }catch(Exception e){
            ret = false;
        }

        if(direction.equals( "inNormal" ))
        {
            configInPInInterrupt( pin, false, msgHandler );
        }

        if(direction.equals( "inButton" ))
        {
            configInPInInterrupt( pin, true, msgHandler );
        }
    }
    else
    {
        return false;
    }

    return ret;
}

boolean writePin(String pin, String value)
{
    boolean ret = true;
    FileOutputStream fos ;
    FileWriter fWriter;

    if(gpioready)
    {
        try{
            fos = new FileOutputStream("/sys/class/gpio_sw/" + pin + "/data", true);
            fWriter = new FileWriter(fos.getFD());
            fWriter.write(value);
            fWriter.flush();
            fWriter.close();
        }catch(Exception e){
            ret = false;
        }
    }
    else
    {
        ret = false;
    }
    return ret;
}

public String readPin(String pin)
{
    String result = "-1";
    BufferedReader buffered_reader = null;

    if(gpioready)
    {
        try {
            buffered_reader = new BufferedReader( new FileReader( "/sys/class/gpio_sw/" + pin + "/data" ) );
            String line;
            while ((line = buffered_reader.readLine()) != null) {
                result = line;
            }
        } catch (IOException e) {
            // TODO
            Log.e( "myApp", e.getMessage() );
            e.printStackTrace();
        } finally {
            try {
                if (buffered_reader != null)
                    buffered_reader.close();
            } catch (IOException ex) {
                // TODO
                ex.printStackTrace();
            }
        }
    }

    return result;
}

public void stopRuning()
{
    running = false;
}

boolean configInPInInterrupt(final String pin, boolean antirebote  , final Handler msg)
{
    boolean res = true;
    final boolean antiRebote = antirebote;

    if(gpioready)
    {
        running = true;
        new Thread( new Runnable() {
            @Override
            public void run() {

                Bundle b = new Bundle();
                String old_state = "";
                String new_state = "";
                boolean firstRead = true;
                Message men = new Message();

                while(running)
                {
                    if(firstRead)
                    {
                        firstRead = false;
                        old_state = readPin(pin);
                    }
                    else
                    {
                        new_state = readPin(pin);

                        try{
                            if(!new_state.equals( old_state ))
                            {
                                if(antiRebote)
                                {
                                    try {
                                        Thread.sleep( 20 );
                                    }catch (Exception e){}

                                    String state = readPin(pin);
                                    if(state.equals( new_state ))//cambio real
                                    {
                                        b.clear();
                                        b.putString( "pin",pin );
                                        men.arg1 = 1;
                                        men.arg2 = Integer.valueOf( new_state );
                                        men.setData( b );
                                        msg.sendMessage( men );
                                        old_state = new_state;
                                    }
                                }
                                else
                                {
                                    b.clear();
                                    b.putString( "pin",pin );
                                    men.arg1 = 1;
                                    men.arg2 = Integer.valueOf( new_state );
                                    men.setData( b );
                                    msg.sendMessage( men );
                                    old_state = new_state;
                                }
                            }
                        }catch (Exception e){
                            Log.e("myApp","Interrupt error " + e.getMessage());
                        }
                    }
                   try {
                       Thread.sleep( 20 );
                   }catch (Exception e){}
                }
            }
        } ).start();
    }
    else
    {
        return false;
    }

    return res;
}

}

Hi Alleiny,

Thanks for sharing. I am having a question regarding the value in cfg file for setting the pin as INPUT. I am trying to change the value from 0 to 1 however it never gets updated. Even using file explorer. Access rights are on 777. Thank you

Hello,

Are you planning to fix the access to GPIO ? Export does not work !

Thank you Ladislav

Hi mi friend.

I attached the class and commented in the end how I use it. I just want to tell you that in the BPI_M2Z it takes some time after the boot to allow the pins to be exported. You can see the different status in the logs. I hope it helps you, and if you have any other questions or it doesn’t work, write me.
keep in touch.

CBpiM2ZeroGpio.java (14,7 KB)

H Alleiny,

Thanks for coming back.

I did a lot of investigation since yesterday and have tried many ways to manage the GPIO.

Using below class I am unable to write into the files like cfg or direction. The only file which I am able to change the value in is data.

Not sure why – but to me it seems that the module gpio_sunxi is blocking it.

So what I have tried is to unload the module from kernel using rmmode gpio_sunxi.

This allowed me to export the port using echo # > /sys/class/gpio/export – I believe because the gpio_sunxi was utilizing the pin resources the export was not working

But I would still prefer to use the library rather then shell commands.

It is still not clear to when gpio_sunxi module is running why I am not able for exaple to change the direction. I have tried that using text editor on android and the value still gets back to 0.

Even the text editor confirms the save. Does not work via code as well.

I am using the latest Android 4.4 with Kernel 3.4.39

This firware is for BPI-M2-Zero but I have not found a one for P2-Zero.

So I assume from harware perspective is exactly the same.

You are right my friend. My class works only with the previous version of android 4.4. The last version I had not tried.

Would you have a link to previous Android ?

is in wiki page.

https://drive.google.com/open?id=1TywrMLLxqJj23ql2jyzLruZw18V_XwX3