How to set a virtual scene image programmatically on android emulator

Viewed 2064

I have writing some driven tests to a flutter project and there are a barcode scanner functionality which I can test successfully using the virtual scene tool provided by android emulator.

However there are many cases to test regarding to different barcodes. I want to set a specific barcode image on virtual scene to each case. Is it possible?

I found that the value of this image is putted on ~/.android/avd/[emulatorName]/AVD.conf file at virtualscene\posters variable.

enter image description here

virtualscene\posters=@Variant(\0\0\0\b\0\0\0\x2\0\0\0\b\0w\0\x61\0l\0l\0\0\0\n\xff\xff\xff\xff\0\0\0\n\0t\0\x61\0\x62\0l\0\x65\0\0\0\n\xff\xff\xff\xff)

enter image description here

virtualscene\posters=@Variant(\0\0\0\b\0\0\0\x2\0\0\0\b\0w\0\x61\0l\0l\0\0\0\n\ 0\0\0\\\0/\0U\0s\0\x65\0r\0s\0/\0l\0\x65\0o\0n\0\x61\0r\0\x64\0o\0.\0\x61\0r\0m\0\x65\0r\0o\0/\0\x44\0\x65\0s\0k\0t\0o\0p\0/\0J\0\x61\0m\0\x65\0s\0W\0i\0l\0s\0o\0n\0.\0p\0n\0g\0\0\0\n\0t\0\x61\0\x62\0l\0\x65\0\0\0\n\xff\xff\xff\xff)
2 Answers

You can replace the default (global) image located at $ANDROID_SDK_HOME/emulator/resources/poster.png with your poster.png image, nor change the default pointer by editing the file $ANDROID_SDK_HOME/emulator/resources/Toren1BD.posters.

You can set the virtual scene image to a specified path. And manipulate the target image while testing. As the Instrumented tests are running on your (virtual) device, it cannot manipulate the host machine files directly. What can be done, (which is an ugly hack) is to start a server on the host, which can be reached from the virtual device with the hosts loop-back "10.0.2.2" address. This server can manipulate the target files. If anybody has better solution, please share it!

An example server and client is here.

Server:

import java.io.*;
import java.net.*;
import java.nio.channels.FileChannel;

public class FileManipulatorServer {
    public static void main(String args[]) {
        int port = 6789;
        FileManipulatorServer server = new FileManipulatorServer( port );
        server.startServer();
    }

    // declare a server socket and a client socket for the server

    private ServerSocket fileManipulatorServer = null;
    private Socket clientSocket = null;
    private int port;

    public FileManipulatorServer(int port ) {
        this.port = port;
    }

    public void stopServer() {
        System.out.println( "Server cleaning up." );
        System.exit(0);
    }

    public void startServer() {
        // Try to open a server socket on the given port
        // Note that we can't choose a port less than 1024 if we are not
        // privileged users (root)

        try {
            fileManipulatorServer = new ServerSocket(port);
        }
        catch (IOException e) {
            System.out.println(e);
        }

        System.out.println( "Waiting for connections. Only one connection is allowed." );

        // Create a socket object from the ServerSocket to listen and accept connections.
        // Use FileManipulatorTask to process the connection.

        while ( true ) {
            try {
                clientSocket = fileManipulatorServer.accept();
                FileManipulatorTask task = new FileManipulatorTask(clientSocket, this);
                task.run();
            }
            catch (IOException e) {
                System.out.println(e);
            }
        }
    }
}

class FileManipulatorTask {
    private BufferedReader is;
    private PrintStream os;
    private Socket clientSocket;
    private FileManipulatorServer server;

    public FileManipulatorTask(Socket clientSocket, FileManipulatorServer server) {
        this.clientSocket = clientSocket;
        this.server = server;
        System.out.println( "Connection established with: " + clientSocket );
        try {
            is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            os = new PrintStream(clientSocket.getOutputStream());
        } catch (IOException e) {
            System.out.println(e);
        }
    }

    public void run() {
        String line;
        try {
            boolean serverStop = false;

            line = is.readLine();
            System.out.println( "Received " + line );
            saveImageToPoster(line.trim());

            os.println("OK");
            os.flush();

            System.out.println( "Connection closed." );
            is.close();
            os.close();
            clientSocket.close();

            if ( serverStop ) server.stopServer();
        } catch (IOException e) {
            System.out.println(e);
        }
    }

    private void saveImageToPoster(String filename) {

        try {
            FileChannel src = new FileInputStream("C:\\fullpathtopostercandidates\\"+filename).getChannel();
            FileChannel dest = new FileOutputStream("C:\\fullpathtoconfiguredposter\\poster.jpg").getChannel();
            dest.transferFrom(src, 0, src.size());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Client:

import java.io.*;
import java.net.*;

public class FileNameSenderClient {

    private String hostname = "10.0.2.2";
    private int port = 6789;

    public void sendFileName(String filename) {

        Socket clientSocket = null;
        DataOutputStream os = null;
        BufferedReader is = null;
        try {
            clientSocket = new Socket(hostname, port);
            os = new DataOutputStream(clientSocket.getOutputStream());
            is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        } catch (UnknownHostException e) {
            System.err.println("Don't know about host: " + hostname);
        } catch (IOException e) {
            System.err.println("Couldn't get I/O for the connection to: " + hostname);
        }


        if (clientSocket == null || os == null || is == null) {
            System.err.println( "Something is wrong. One variable is null." );
            return;
        }

        try {
            System.out.println("Write to output stream");
            os.writeBytes( filename +"\n");
            os.flush();
            String responseLine = is.readLine();             
            System.out.println("Server returns: " + responseLine);
            os.close();
            is.close();
            clientSocket.close();
        } catch (UnknownHostException e) {
            System.err.println("Trying to connect to unknown host: " + e);
        } catch (IOException e) {
            System.err.println("IOException:  " + e);
        }
    }
}

Use the FileNameSenderClient from your instrumented test like this.

@Test
public void testQRcodeReadingOK()
{
   FileNameSenderClient c = new FileNameSenderClient();
   c.sendFileName("QRCode.jpg");

   //your code that wants to use the image, like the this:

    onView(withId(R.id.load_qr_code)).perform(click());
}
Related