views:

92

answers:

2

Hello,

I'm trying to build a app that uses the SmsMessage class but there are two versions depending on the API level of the device:

android.telephony.gsm.SmsMessage (deprecated for 1.6 and above)

android.telephony.SmsMessage (the new class for 1.6 and up)

I want to target 1.5 and yet have the newer class (android.telephony.SmsMessage) run on devices with 1.6 or higher. How do I do this?

I have already tired this: http://devtcg.blogspot.com/2009/12/gracefully-supporting-multiple-android.html but I couldn't get it to work (the author doesn't mention how he/she handles the different imports, the exact api level settings etc.)

Thanks.

import java.util.Date;
import com.apps.myapp.Utilities;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.gsm.SmsMessage;//*NOTE* depreciated in v1.6+

public class OfflineSMSReceiver extends SMSReceiver
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        System.out.println("SMS_RECEIVED");

        System.out.println(Utilities.getNow());
        //---get the SMS message passed in---
        Bundle bundle = intent.getExtras();        
        SmsMessage[] msgs = null;

        Date date; 
        long timeStamp;
        String time;
        String str = "";            
        if (bundle != null)
        {
            //---retrieve the SMS message received---
            Object[] pdus = (Object[]) bundle.get("pdus");
            msgs = new SmsMessage[pdus.length];            
            for (int i=0; i<msgs.length; i++){
                msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
                timeStamp = msgs[i].getTimestampMillis();
                date = new Date(timeStamp);
                time = this.getTime(date.getHours(),date.getMinutes(),date.getSeconds());
                str += "SMS from " + msgs[i].getOriginatingAddress();                     
                str += " :";
                str += msgs[i].getMessageBody().toString();
                str += "\n";
                str += "TIME: "+time+"\t"+this.getNowDate();
            }

            System.out.println(str);
        }
    }
}
+1  A: 

You will need to target android-4 or higher, otherwise the newer class will not exist.

With respect to loading in the correct version, you can use conditional class loading, demonstrated in this sample project for the two editions of the contacts content provider. Also, this article is what Google has to say on the subject.

CommonsWare
Thanks for responding. Your first link was very helpful. After looking at that code, I think I understand what I have to do. The key is setting up the abstract class correctly. I'll report back after trying this on my own. Thanks again.
borg17of20
Your example worked perfectly. Just to make sure, because I set the min SDK to 3 (target to 4), the app should appear in the market for devices that run 1.5+? Thanks again.
borg17of20
@borg17of20: Whether or not you show up in the Market will be determined by your `android:minSdkVersion` setting in your manifest (see `uses-sdk` element), not by your build target when running the build tools.
CommonsWare
A: 

Using CommonsWare's example, I was able to create this (which works):

[manifest settings]

1.Set the target SDK to 4 (or higher) (Android 1.6+)

2.Set the min SDK to 3 (Android 1.5)

[OfflineSMSReceiver.java]

import java.util.Date;
import com.apps.myapp.Utilities;
import com.apps.myapp.SmsMessageBridge;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;

public class OfflineSMSReceiver extends SMSReceiver
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        System.out.println("SMS_RECEIVED");

        System.out.println(Utilities.getNow());
        //---get the SMS message passed in---
        Bundle bundle = intent.getExtras();        
        SmsMessageBridge[] msgs = null;

        Date date; 
        long timeStamp;
        String time;
        String str = "";            
        if (bundle != null)
        {
            //---retrieve the SMS message received---
            Object[] pdus = (Object[]) bundle.get("pdus");
            msgs = new SmsMessageBridge[pdus.length];           
            for (int i=0; i<msgs.length; i++){
                msgs[i] = SmsMessageBridge.INSTANCE.createFromPdu((byte[])pdus[i]);
                timeStamp = msgs[i].getTimestampMillis();
                date = new Date(timeStamp);
                time = this.getTime(date.getHours(),date.getMinutes(),date.getSeconds());
                str += "SMS from " + msgs[i].getOriginatingAddress();                     
                str += " :";
                str += msgs[i].getMessageBody().toString();
                str += "\n";
                str += "TIME: "+time+"\t"+this.getNowDate();
            }

            System.out.println(str);
        }
    }
}

[SmsMessageBridge.java]

import android.os.Build;

public abstract class SmsMessageBridge
{
    public abstract SmsMessageBridge createFromPdu(byte[] pdu);
    public abstract long getTimestampMillis();
    public abstract String getOriginatingAddress();
    public abstract String getMessageBody();

    public static final SmsMessageBridge INSTANCE = getBridge();

    private static SmsMessageBridge getBridge()
    {
        final int sdkVersion = new Integer(Build.VERSION.SDK).intValue();

        if(sdkVersion>3)
        {
            return new NewSmsMessage();
        }
        else
        {
            return new OldSmsMessage();
        }
    }
}

[OldSmsMessage.java]

import android.telephony.gsm.SmsMessage;//*NOTE* depreciated in v1.6+

@SuppressWarnings("deprecation")
public class OldSmsMessage extends SmsMessageBridge
{
    private SmsMessage myMSG;

    @Override
    public SmsMessageBridge createFromPdu(byte[] pdu)
    {
        myMSG = SmsMessage.createFromPdu(pdu);
        return this;
    }

    @Override
    public long getTimestampMillis()
    {
        return myMSG.getTimestampMillis();
    }

    @Override
    public String getOriginatingAddress()
    {
        return myMSG.getOriginatingAddress();
    }

    @Override
    public String getMessageBody()
    {
        System.out.println("v1.5");
        return myMSG.getMessageBody();
    }
}

[NewSmsMessage.java]

import android.telephony.SmsMessage;

public class NewSmsMessage extends SmsMessageBridge
{
    private SmsMessage myMSG;

    @Override
    public SmsMessageBridge createFromPdu(byte[] pdu)
    {
        myMSG = SmsMessage.createFromPdu(pdu);
        return this;
    }

    @Override
    public String getMessageBody()
    {
        //System.out.println("v1.6+");
        return myMSG.getMessageBody();
    }

    @Override
    public String getOriginatingAddress()
    {
        return myMSG.getOriginatingAddress();
    }

    @Override
    public long getTimestampMillis()
    {
        return myMSG.getTimestampMillis();
    }

}

Thanks again to CommonsWare.

borg17of20