'Share via' application that runs without

2019-06-13 16:19发布

I want to write an app that sits in the 'Share via' menu (for quickly emailing myself links to things I find on the web or look at in RSS readers) For this I'm declaring my app with an intent.action.SEND intent-filter:

    <activity
        android:name="uk.co.baroquedub.checkit.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.SEND" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:mimeType="text/plain" />
           </intent-filter>
    </activity>

Here's a skeleton of the MainActivity package

package uk.co.baroquedub.testcheck;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;

import android.widget.Toast;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

// real code here grabs URL from intent then emails it as an asyncTask:
    doSendTask task = new doSendTask();
    task.execute(new String[] { "urlString" });
}

protected void showDialog (String response){
    Toast.makeText(this, response, Toast.LENGTH_SHORT).show();
    finish();
}

private class doSendTask extends AsyncTask<String, Void, String> {
    @Override
    protected String doInBackground(String... urls) {
      String response = "";
      // Real code here sends the email
      // Simulate waiting for the email to be sent:
      try { 
          Thread.sleep(5000);
          response = "Waited";
      }
      catch (InterruptedException ex) {  }

      return response;
    }

    @Override
        protected void onPostExecute(String result) {
            showDialog(result);
    }
}

}

The problem is that my app is opening on top of the browser (a white screen appears with a title bar showing the name of the app) - which is stopping the browser from being accessible until the 'wait' is finished (hence defeating the purpose of wrapping my sendEmail functionality within an asyncTask).

See: screencast for demo of problem

See: related question with full code

Can anyone tell me how I can have my app start (from the 'Share via' menu) and execute my code but without actually having a 'View' (if that's the right terminology for the blank screen and title bar)?

2条回答
啃猪蹄的小仙女
2楼-- · 2019-06-13 16:36
  1. start an activity without any UI
  2. start a service to do your background service in OnCreate
  3. finish the activity as soon as you start service
  4. let the service post notification or Toast about completion.

If you do want to show a dialog, you could start a separate activity with just the dialog from service, but it is usually intrusive to show dialog.

查看更多
迷人小祖宗
3楼-- · 2019-06-13 16:44

Thanks to Nandeesh for putting me on the right path. For those wanting to know exactly how to do it, here's the full solution:

1: start an activity without any UI to do this I used the following Theme in the AndroidManifest:

android:theme="@android:style/Theme.NoDisplay"

which makes the initial application not just transparent but completely without a UI

2: start a service to do your background service in OnCreate Here I still had to 'grab' the URL from the Share intent and pass it as an Extra to the service:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // get url
    Intent intent = getIntent();
    intent.setFlags( Intent.FLAG_ACTIVITY_CLEAR_TOP );
    String action = intent.getAction();

    // if this is from the share menu
   if (Intent.ACTION_SEND.equals(action)) {   
           title = intent.getStringExtra(Intent.EXTRA_SUBJECT);
           url = intent.getStringExtra(Intent.EXTRA_TEXT);

           // Flipboard fix (remove title in URL)
           url = url.replace(title, "");

           if (url != null){
            url = title+"\n"+url;
           } else {
            url = "error getting URL";
           }

    // prepare service
    Intent emailSendIntent = new Intent(getApplicationContext(), EmailSendService.class);
    emailSendIntent.putExtra("extraData", url);
    startService(emailSendIntent);

    finish();
   }

}

3: finish the activity as soon as you start service - see above

Note that in the service the Extras are passed to the OnStart method (not the On Create method as might be expected) See: link

4: let the service post notification or Toast about completion. I couldn't get the Service to open a Dialog notification(as per my original app), this kept on crashing the app/service but Toast works great - and as Nandeesh suggests, it's probably less intrusive.

Here's the service package:

public class EmailSendService extends Service {

String url;
String message;


@Override
public IBinder onBind(Intent arg0) {
    return null;
}

@Override
public void onCreate() {
    super.onCreate();

}


@Override
public void onDestroy() {
    super.onDestroy();
}

@Override 
public void onStart(Intent intent, int startId) {
      super.onStart(intent, startId);
      url = intent.getExtras().getString("extraData");

      String senderPassword = getResources().getString(R.string.senderPassword); 
      String senderEmail = getResources().getString(R.string.senderEmail); 
      String recipientEmail = getResources().getString(R.string.recipientEmail); 
      String subjectText = getResources().getString(R.string.subjectText);

      GMailSender sender = new GMailSender(senderEmail, senderPassword);
        try {
            sender.sendMail(subjectText,   
                    url,   
                      senderEmail,   
                      recipientEmail);
                message = "Email sent";
            } catch (Exception e) {
                message = "Error sending email";
            }
        Toast.makeText(this, message, Toast.LENGTH_LONG).show();
    }

}

NB. remember to declare the service in the manifest (inside the application tag):

    <service
        android:name=".EmailSendService"
        android:label="CheckIt EmailSendService" >
    </service>
查看更多
登录 后发表回答