Skip to content
This repository was archived by the owner on Feb 26, 2023. It is now read-only.
This repository was archived by the owner on Feb 26, 2023. It is now read-only.

enhanced IntentService support #572

@pstefan

Description

@pstefan

I am often using IntentService objects for background activities in my apps. These IntentService have quite many different ACTIONs in it, which are distinguished by different ACTION strings and different extras.

To get a structure in the written code I always create an own methods for each action. But I have to write many code by myself that could be wrapped by annotations and would make the code better readable.

I wanna show you this in an example. For this purpose I am using the source code of the FileTransferService of WifiDirectDemo Sample App.

public class FileTransferService extends IntentService {

    private static final int SOCKET_TIMEOUT = 5000;
    public static final String ACTION_SEND_FILE = "com.example.android.wifidirect.SEND_FILE";
    public static final String EXTRAS_FILE_PATH = "file_url";
    public static final String EXTRAS_GROUP_OWNER_ADDRESS = "go_host";
    public static final String EXTRAS_GROUP_OWNER_PORT = "go_port";

    public FileTransferService(String name) {
        super(name);
    }

    public FileTransferService() {
        super("FileTransferService");
    }

    /*
     * (non-Javadoc)
     * @see android.app.IntentService#onHandleIntent(android.content.Intent)
     */
    @Override
    protected void onHandleIntent(Intent intent) {

        Context context = getApplicationContext();
        if (intent.getAction().equals(ACTION_SEND_FILE)) {
            String fileUri = intent.getExtras().getString(EXTRAS_FILE_PATH);
            String host = intent.getExtras().getString(EXTRAS_GROUP_OWNER_ADDRESS);
            Socket socket = new Socket();
            int port = intent.getExtras().getInt(EXTRAS_GROUP_OWNER_PORT);

            try {
                Log.d(WiFiDirectActivity.TAG, "Opening client socket - ");
                socket.bind(null);
                socket.connect((new InetSocketAddress(host, port)), SOCKET_TIMEOUT);

                Log.d(WiFiDirectActivity.TAG, "Client socket - " + socket.isConnected());
                OutputStream stream = socket.getOutputStream();
                ContentResolver cr = context.getContentResolver();
                InputStream is = null;
                try {
                    is = cr.openInputStream(Uri.parse(fileUri));
                } catch (FileNotFoundException e) {
                    Log.d(WiFiDirectActivity.TAG, e.toString());
                }
                DeviceDetailFragment.copyFile(is, stream);
                Log.d(WiFiDirectActivity.TAG, "Client: Data written");
            } catch (IOException e) {
                Log.e(WiFiDirectActivity.TAG, e.getMessage());
            } finally {
                if (socket != null) {
                    if (socket.isConnected()) {
                        try {
                            socket.close();
                        } catch (IOException e) {
                            // Give up
                            e.printStackTrace();
                        }
                    }
                }
            }

        }
    }
}

In my opinion the whole onHandleIntent method could be generated automatically and the annotated class could look like the following:

@EIntentService
public class FileTransferService extends IntentService {
    private static final int SOCKET_TIMEOUT = 5000;
    public static final String ACTION_SEND_FILE = "com.example.android.wifidirect.SEND_FILE";
    public static final String EXTRAS_FILE_PATH = "file_url";
    public static final String EXTRAS_GROUP_OWNER_ADDRESS = "go_host";
    public static final String EXTRAS_GROUP_OWNER_PORT = "go_port";

    public FileTransferService() {
        super("FileTransferService");
    }

    @Action(ACTION_SEND_FILE)
    public void sendFile( @Extra(EXTRAS_FILE_PATH) String fileUri, @Extra(EXTRAS_GROUP_OWNER_ADDRESS) String host, @Extra(EXTRAS_GROUP_OWNER_PORT) int port ) {
            Socket socket = new Socket();
         try {
                Log.d(WiFiDirectActivity.TAG, "Opening client socket - ");
                socket.bind(null);
                socket.connect((new InetSocketAddress(host, port)), SOCKET_TIMEOUT);

                Log.d(WiFiDirectActivity.TAG, "Client socket - " + socket.isConnected());
                OutputStream stream = socket.getOutputStream();
                ContentResolver cr = context.getContentResolver();
                InputStream is = null;
                try {
                    is = cr.openInputStream(Uri.parse(fileUri));
                } catch (FileNotFoundException e) {
                    Log.d(WiFiDirectActivity.TAG, e.toString());
                }
                DeviceDetailFragment.copyFile(is, stream);
                Log.d(WiFiDirectActivity.TAG, "Client: Data written");
            } catch (IOException e) {
                Log.e(WiFiDirectActivity.TAG, e.getMessage());
            } finally {
                if (socket != null) {
                    if (socket.isConnected()) {
                        try {
                            socket.close();
                        } catch (IOException e) {
                            // Give up
                            e.printStackTrace();
                        }
                    }
                }
            }
   }
}

The code reduction in this example isn't much, but it has already improved the readability of the code.
With more ACTIONs defined the effect would be much greater!

The generated onHandleIntent method could look like this:

    @Override
    protected void onHandleIntent(Intent intent) {
        if ( ACTION_SEND_FILE.equals( intent.getAction() ) {
            String fileUri = intent.getExtras().getString(EXTRAS_FILE_PATH);
            String host = intent.getExtras().getString(EXTRAS_GROUP_OWNER_ADDRESS);
            int port = intent.getExtras().getInt(EXTRAS_GROUP_OWNER_PORT);
            sendFile( fileUri, host, port );
        } else if ( ACTION_OTHER.equals( intent.getAction() ) {
            // etc.
        }
    }

But it would not only be possible to simplify the IntentService class itself, it's also possible to simplify the calling actions of the IntentService.

Intent intent = new Intent(context, FileTransferService.class);
intent.setAction(FileTransferService.ACTION_SEND_FILE);
intent.putExtra(FileTransferService.EXTRAS_FILE_PATH, "/image.png");
intent.putExtra(FileTransferService.EXTRAS_GROUP_OWNER_ADDRESS, "192.168.0.3");
intent.putExtra(FileTransferService.EXTRAS_GROUP_OWNER_PORT, 8080);
context.startService(intent);

could be converted to

FileTransferService_.intent(context).sendFile("/image.png", "192.168.0.3", 8080).start();

I think this would be a great enhancement for every android programmer. But I do not know if annotations can be used that way and if the annotations names are the best choice for it.

What do you think? Do you think that this is a good enhancement for androidannotations? And could it be implemented that way?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions