Android-发送短信/电子邮件-目的

时间:2018-08-21 19:47:32

标签: android android-intent android-service

我正在尝试通过调用Intent发送短信/电子邮件,但是我正在获得NPE,我不知道是什么原因。

我尝试了几种不同的方法,但是显然我在寻找代码错误部分中的问题。

我仍在测试中,我直接从其他类中使用sendSms / sendEmail,该类也扩展了IntentService,但事实并非如此。虽然那不是很重要。 Anyhoo,这是我的代码:

import android.app.IntentService;
import android.content.Intent;
import android.net.Uri;
import android.support.annotation.Nullable;
import android.widget.Toast;

import java.util.Map;

public class FallNotificationService extends IntentService { // FIXME necessário extender IntentService?

    public FallNotificationService() {
        super(".FallNotificationService");
    }

    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     *
     * @param name Used to name the worker thread, important only for debugging.
     */
    public FallNotificationService(String name) {
        super(name);
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {

    }

    public boolean sendNotification(Elderly elderly) {
        boolean success = false;
        String name = elderly.getName();
        for (Caregiver caregiver : elderly.getCaregivers()) {
            for (Map.Entry<ContactType, String> entry : caregiver.getContacts().entrySet()) {
                ContactType contactType = entry.getKey();
                String contact = entry.getValue();
                switch (contactType) {
                    case SMS:
                        success = this.sendSms(name, contact);
                        break;
                    case EMAIL:
                        success = this.sendEmail(name, contact);
                        break;
                    case WHATSAPP:
                        success = this.sendWhatsapp(name, contact);
                        break;
                }
            }

        }

        return success;
    }

    public boolean sendWhatsapp(String name,
                                 String contact) {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_SEND);
        intent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
        intent.setType("text/plain");
        intent.setPackage("com.whatsapp");

        try {
            super.startActivity(intent);
            //finish();
            return true;
        } catch (Exception e) {
            //Toast.makeText(this, "Sms not send", Toast.LENGTH_LONG).show();
            e.printStackTrace();
            return false;
        }
    }

    public boolean sendSms(String name,
                           String contact) {
        String uriText = "smsto:" + contact +
                "?sms_body=" + Uri.encode("caiu");

        Intent intent = new Intent(Intent.ACTION_SENDTO);

        //intent.setData(Uri.parse("smsto:"));
        //intent.setData(Uri.parse("smsto:" + contact));
        intent.setData(Uri.parse(uriText));
        intent.setType("vnd.android-dir/mms-sendSms");
        //intent.putExtra("address", contact);

        try {
            super.startActivity(intent);
            //finish();
            return true;
        } catch (Exception e) {
            //Toast.makeText(this, "Sms not send", Toast.LENGTH_LONG).show();
            e.printStackTrace();
            return false;
        }
    }

    public boolean sendEmail(String name,
                             String contact) {
        Intent intent = new Intent(Intent.ACTION_SENDTO);

        intent.setData(Uri.parse("mailto:" + contact));
        //intent.putExtra("address", contact);
        intent.putExtra("message_body", "caiu");

        try {
            startActivity(intent);
            //finish();
            return true;
        } catch (Exception e) {
//            Toast.makeText(this, "Email not send", Toast.LENGTH_LONG).show();
            e.printStackTrace();
            return false;
        }
    }
}

这是我的AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.cam.myapplication">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service android:name=".FallDetectionService" android:exported="false"/>
    </application>
    <uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true" />
    <uses-feature android:name="android.hardware.sensor.gyroscope" android:required="false"/>

    <uses-permission android:name="android.permission.SEND_SMS"/>
</manifest>

这是app / build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "com.example.cam.myapplication"
        minSdkVersion 15
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    packagingOptions {
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/license.txt'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/NOTICE.txt'
        exclude 'META-INF/notice.txt'
        exclude 'META-INF/ASL2.0'
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

    compileOnly "org.projectlombok:lombok:1.18.2"
    annotationProcessor 'org.projectlombok:lombok:1.18.2'

    implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
}

Stacktrace:

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.content.Context.startActivity(android.content.Intent)' on a null object reference
     at android.content.ContextWrapper.startActivity(ContextWrapper.java:356)
     at com.example.cam.myapplication.FallNotificationService.sendEmail(FallNotificationService.java:108)
     at com.example.cam.myapplication.FallDetectionService.isFallDetected(FallDetectionService.java:88)
     at com.example.cam.myapplication.FallDetectionService.onSensorChanged(FallDetectionService.java:74)
     at android.hardware.SystemSensorManager$SensorEventQueue.dispatchSensorEvent(SystemSensorManager.java:699)
     at android.os.MessageQueue.nativePollOnce(Native Method)
     at android.os.MessageQueue.next(MessageQueue.java:323)
     at android.os.Looper.loop(Looper.java:136)
     at android.app.ActivityThread.main(ActivityThread.java:6123)
     at java.lang.reflect.Method.invoke(Native Method)
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)

此外,如果取消注释Toast.makeText所在的行,我也会得到一个NPE。 因此,我猜测问题出在与我作为上下文传递的内容有关,但我无法弄清楚是什么。

2 个答案:

答案 0 :(得分:0)

正如我们在堆栈跟踪中看到的那样,崩溃是由函数sendEmail()引起的,并且像在手机中那样生成,没有应用程序具有任何可以处理意图约束的活动,您已经在意图中提供了该功能,

    Intent intent = new Intent(Intent.ACTION_SENDTO);
    intent.setData(Uri.parse("mailto:" + contact));
    //intent.putExtra("address", contact);
    intent.putExtra("message_body", "caiu");

    try {
        startActivity(intent);
        //finish();
        return true;
    } catch (Exception e) {
       // Toast.makeText(this, "Email not send", Toast.LENGTH_LONG).show();
        e.printStackTrace();
        return false;
    }

我们可以在这里看到,您在setData(Uri.parse("mailto:" + contact))中提供了条件,因此如果android手机没有任何可发送电子邮件的应用程序,它将崩溃,但是由于您在try-catch中捕获了它,因此抛出空指针异常,如果您将在具有电子邮件应用程序的设备中测试代码,则它将起作用。 因此,使用功能resolveActivity()检查意图条件是否满足始终是最佳实践 如下所示。

    Intent intent = new Intent(Intent.ACTION_SENDTO);
    intent.setData(Uri.parse("mailto:" + contact));
    //intent.putExtra("address", contact);
    intent.putExtra("message_body", "caiu");
    if(intent.resolveActivity(getContext().getPackageManager())){
       // Phone has email app to handle this intent.. we can call the 
       intent
       startActivity(intent);
     }else{
        // Phone does not have email app to handle this intent, handle 
        accordingly, in this case we can show open default android 
        share intent..
     }

答案 1 :(得分:0)

碰巧,正如Mike M.所说,我正在用new实例化服务。 所以我将其添加到AndroidManifest.xml中,并在我调用新的FallNotificationService()的地方调用了startActivity。