I have tried to get a message id which is saved in phone.
But I failed to get it.
My existing code is here
#Override
public void onReceive(Context context, Intent intent) {
String address = "";
String message = "";
String msg_id="";
Bundle extras = intent.getExtras();
if (extras != null) {
Object[] smsExtra = (Object[]) extras.get("pdus");
for (int i = 0; i < smsExtra.length; i++) {
SmsMessage sms = SmsMessage.createFromPdu((byte[]) smsExtra[i]);
message += sms.getMessageBody();
address = sms.getOriginatingAddress();
}
sms = new Sms(msg_id,message, address);
UploadSms up = new UploadSms();
up.start();
Toast.makeText(context,
"SMS Received>>" + message + "From >>" + address,
Toast.LENGTH_LONG).show();
}
}
By this I get sms body and sender number.
But I know there exist a unique number for every message in android phone, I retrieved it.
But unable to retrieved in onReceive methods.
Thanks
You will have to parse the SMS PDU (in the raw PDU format) since at the android application layer there exists no API to retrieve the user data header. I believe that the short message identifier resides within the User Data Header (Octet 1). Please refer to the post Parsing SMS PDU.
In that post one of the users mentions a freeware by the name 'SMSLib' (under APACHE License) in order to parse and extract the message parameters. The message ID could be extracted using the method getMessageId() - Method in class org.smslib.Message.
Hope this helps.
I am not sure if this suffices for your purposes, but the SMSMessage.getIndexOnICC() method returns an int, indexed from 1 (up to presumably Integer.MAX_VALUE) which is the unique identifier for the SMSMessage assigned by the smart card/ICC. It can also return -1 if the SMSMessage was synthesized opposed to processed through the ICC.
Instead of synthesizing using the PDU, you should probably be using Telephony.Sms.Intents#getMessagesFromIntent(Intent) to grab a list of the SMSMessages via the PDUs using an API call instead of rolling your own. However, that was added in API 19 and so it may not be supported depending on your API version.
If you want to roll your own, the current version (API 30 at the time of writing, though the link is to the master so it may change) of the getMessageFromIntent(Intent) source code can be viewed here for inspiration of how to do things without using the API (if you want to do that for some reason). It seems that the proper way to synthesize an SMSMessage is actually the way you are doing it though, at least for the most part. Though you really should be using SMSMessage.createFromPdu(byte[], String) and specifying the format you get from Intent.getStringExtra("format"), as otherwise you may run into problems depdending on how the message is formatted (for example you might find both formats on multi-sim devices).
If you want to get really low-level and parse things out yourself, you should look to the CDMA and GSM specific implementations of SMSMessage (though this is not a subclass to be clear), which are of course android internal and not meant to be used as exposed APIs. The CDMA implementation for parsing the PDU is at ...cdma.SMSMessage.parsePdu(byte[]) whereas the GSM implementation is at ...gsm.SMSMessage.parsePdu(byte[]). For reference to the underlying base class you should see SMSMessageBase.
Related
With Nearby Connections, each device has an endpointId, something similar to zkHk.
Getting the endpointId of others is trivial since it is returned by the API when scanning or connecting to other devices.
I must miss something, but I cannot find a way to get my own endpointId (apart implementing a mechanism where a connected peer echoes my id). It can be useful for some protocols where I want to follow what is sent to who.
The only thing I found is getLocalEndpointName but it returns my name, not my id. Even though it seems the C++ version of Nearby have it!
Do you have some ideas for Java/Kotlin? I specifically seek to get the endpointId, and not use alternatives like using a kind of GUID in the localendpoint name as a replacement.
Edit: Some example of usage
1) For instance, it can be interesting to implement some network mesh protocols. Several devices are interconnected making a global network, and each device add its endpointId in the incoming payload before sending it again, so others can check if they should send the payload to a device that already has it.
2) I may also want to specifically send a packet from device A to C through B acting as a relay, and add some "from: A" and "to: C" field in the payload so the network would know how to route the data and avoid some retransmission cycles. It is simpler to do that with endpointId since each device has a list of endpointId to which it is connected.
3) It can also be interesting for debug purpose. If I do some tests with a phone connected to several others (e.g. star network), it is easier to know from which phone a new piece of data is coming, all the more if I want to use name for another purpose.
Note: all of that could be done differently (e.g. use some unique identifier for the "name" of the devices and check that instead of the endpointId) but it seems a little cumbersome. All the more since endpointId guarantee a kind of unicity, whereas I must enforce it for the name. Moreover there isn't lots of information I can have on another device before exchanging data (only endpointId and name), so I feel I remove my last metadata slot if I use name as a substitute for endpointId.
As of today, you can't get your own endpoint id. We didn't see a reason you'd need it. Can you give a more detailed example of an algorithm where you need to know your own id?
i think you want to get your endpointId and sent its to other devices to know you again ?
if yes
let's think like that :
other devices will get your EndpointID and save it every time you connect to them
1)you have an Arrylist<EndPointObject> listOfUsers where EndPointObject it's an Object contain informations about Connected Endpoint Device (you create this class).
we w'ill use this Arry list to save recieved Endpoint informations
2)you need to make EndPointObject class Serializable by implements Serializable,you are doing that to make it able to be converted to Byte[] and send it in payload
public class EndPointObject implements Serializable
{
String endpointId ;
.
.
.
}
3)this is the Converting class add it to your project
public class SerializeHelperForPayLoad {
public static byte[] serialize(Object object) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
// transform object to stream and then to a byte array
objectOutputStream.writeObject(object);
objectOutputStream.flush();
objectOutputStream.close();
return byteArrayOutputStream.toByteArray();
}
public static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException{
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
return objectInputStream.readObject();
}
}
4) now the strategy is every time you connect to an endpoint Device you will exchange yours EndpointObject informations,so in payloadcallback
PayloadCallback mPayloadCallback =
new PayloadCallback() {
#Override
public void onPayloadReceived(String endpointId, Payload payload) {
if (payload.getType() == Payload.Type.BYTES) {
try{
onDataReceived(endpointId, SerializeHelperForPayLoad.deserialize(payload.asBytes()));
} catch (IOException | ClassNotFoundException e) { e.getMessage(); }
}
}
// onData recieved void
void onDataReceived(String endpointId, Object object) {
// do something with your Object
EndPointObject recieved_user_info = new EndPointObject();
if (object.getClass() == EndPointObject.class){
//casting
recieved_user_info = (EndPointObject) object;
//now add his end pointid to his information
recieved_user_info.setEndpointId(endpointId);
listOfUsers.add(recieved_user_info);
}
}
i'm very new in nearby technology ,but i hope that's helpful ,
by this way you can ask other end endpoint to send you your own endpointid every time
Currently I am trying to modify an incoming SMS before it is saved to the Inbox.
As the system is Android 4.4.4, a simple interception with a high priority broadcast receiver is not possible. That is also the reason why I'm modifying the Android Source (AOSP) and not building an App.
So far I have managed to identify a promising class: InboundSmsHandler. Within the inner class SmsBroadcastReceiver the method onReceive is triggered when a SMS has arrived and later on sends an "SMS_RECEIVED" intend. So basically this method seems to be at a good spot.
The problem is that I can not modify the SMS that is delivered with the intend of onReceive.
I have already tried to modify it with PDU:
byte[] pdu = createFakePDU("15555215556", "modified body");
intent.putExtra("pdus", new Object[] { pdu });
intent.putExtra("format", "3gpp");
(This approach did not work, the SMS App has shown the original message)
Tried to modify the body of a SmsMessage directly:
(I have added a method to SmsMessage to be able to modify the body)
SmsMessage[] msgs = Intents.getMessagesFromIntent(intent);
int pduCount = msgs.length;
for(int i=0; i<pduCount; i++)
{
msgs[i].modifyBody("test");
}
(This approach did not work, the SMS App has shown the original message)
And finally added a new SMS to the database:
....
contentResolver.insert( Uri.parse( SMS_URI ), values );
....
(The problem with that approach is that the original SMS still arrives and therefore not only one modified SMS but one original SMS and one modified arrive. The original SMS must be deleted, but I don't know how.)
Does anyone know how I can modify a SMS before it arrives at the Inbox?
Best regards
mint
AFAIK, on 4.4.4 there is nothing that can prevent your app to receive SMS by registering your BroadcastReceiver, setting the right permissions and the right intent filter. That is:
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
and
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
(if I correctly remember them)
Then inside your BroadcastReceiver you call abortBroadcast(), modify the SMS as needed, and finally store it manually with
getContentResolver().insert(Uri.parse("content://sms/sent"), values);
Thanks for all the answers, I have found a spot in InboundSmsHandler where it is possible to modify the PDU before the broadcast is sent: the method proccessMessagePart. Before the command "intent.putExtra("pdus", pdus);" is executed, the pdus array and therefore the message body can be modified.
I wish to achieve a SMS loopback, i.e. to send and receive SMS from the same application. In order to do so, I have created a class that extends BroadcastReciever, implemented the onReceive() method, and declared the relevant permissions.
I verified the implementation by sending a SMS using telnet.
I want to automate the telnet process, i.e. having the application test itself by sending the SMS. In order to do so, I invoke the following method in the main activity, but the BroadcastReceiver is never called:
private final void sendSMS() {
final TelephonyManager telMgr = (TelephonyManager)
getSystemService(Context.TELEPHONY_SERVICE);
final int len = telMgr.getLine1Number().length();
final String phoneNum = telMgr.getLine1Number().substring(len - 4, len);
final String msg = "msg";
SmsManager.getDefault().sendTextMessage(phoneNum, null, msg, null, null);
}
Any clue what is wrong...?
UPDATE: Note that the code above is intended for the emulator.
Not sure if I understand you question right, but are you trying send an SMS from the emulator to itself? As far as I know, that is not possible. Just load up another emulator, and send messages between them.
Since telnet commands work, your BroadcastReceiver is probably correctly implemented, but you should probably attach the code for it anyways... Its hard to troubleshoot code you can't see :)
I need to know UUID on API 8 (2.2) or possibly 2.3.3.
As I understand the documentation, this should be allowed:
phoneDevice = blueAdapter.getRemoteDevice(phoneAddress);
ParcelUuid[] phoneUuids = phoneDevice.getUuids(); // Won't compile
Eclipse gives me:
"The method getUuids() is undefined for the type BluetoothDevice."
But see:
http://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#getUuids()
Also, I would like to know how the UUIDs are "parceled" inside the ParcelUuid[]. In case I ever manage to get there, how do I retrieve a UUID from a parcelUuid[]? Documentation for Android bluetooth seems to be very poor, in my opinion.
What a joke!
Now I try to get it from the intent, but this too gives: *"EXTRA_UUID cannot be resolved or is not a field"*:
intent.getParcelableExtra(BluetoothDevice.EXTRA_UUID);
You have to use reflection to use the getUuids() and fetchUuidsWithSdp() on android version < 3. So, try the code:
Method method = phoneDevice.getClass().getMethod("getUuids", null);
ParcelUuid[] phoneUuids = (ParcelUuid[]) method.invoke(phoneDevice, null);
//this will support from API level 15 and above.
Broadcast Action: This intent is used to broadcast the UUID wrapped as a ParcelUuid of the remote device after it has been fetched. This intent is sent only when the UUIDs of the remote device are requested to be fetched using Service Discovery Protocol
Always contains the extra field EXTRA_DEVICE
Always contains the extra field EXTRA_UUID
Requires BLUETOOTH to receive.
Constant Value: "android.bluetooth.device.action.UUID"
//no way to degrade its hardware related. there is no supporting jar also. http://developer.android.com/sdk/compatibility-library.html
Unfortunately, I don't think there is any good way to get the UUID's supported by a BluetoothDevice with API level < 15. I guess that's why they added the new functions in API 15.
Note, from the docs for BluetoothClass
BluetoothClass is useful as a hint to roughly describe a device (for
example to show an icon in the UI), but does not reliably describe
which Bluetooth profiles or services are actually supported by a
device. Accurate service discovery is done through SDP requests, which
are automatically performed when creating an RFCOMM socket with
createRfcommSocketToServiceRecord(UUID) and
listenUsingRfcommWithServiceRecord(String, UUID).
So, perhaps the device class could be used as a hint as to what services will be available until you perform one of the listed functions. Certainly it doesn't hurt to check the class since this won't require any additional bluetooth operations.
Note that the service class is also available (it is part of the device class) but this is just a general class, not a listing of specific services (like from SDP).
try BluetoothAdapter class
any question, read: http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html
In case you can not get UUID from getUuids() method. Please try the other way.
After scanned successfully, you should receive byte[] (scanRecord), so from this result, if you can recognize UUID format you can split step by step to get correct UUID as these codes.
P/s : Important thing, you should know UUID format to get from index correctly.
// Put item into hash map
// UUID from index 10 to 24 : 12233445566778899aabbccddeeff0
StringBuilder mSbUUID = new StringBuilder();
for (int i = 0; i < scanRecord.length; i++) {
// UUID
if (i >= 10 & i <= 24) {
if (Integer.toHexString(
scanRecord[i]).contains("ffffff")) {
mSbUUID.append(Integer.toHexString(scanRecord[i]).replace("ffffff", "") + "-");
} else {
mSbUUID.append(Integer.toHexString(scanRecord[i]) + "-");
}
}
}
I have a app, which sends a lot of SMS messages to a central server. Each user will probably send ~300 txts/day. SMS messages are being used as a networking layer, because SMS is almost everywhere and mobile internet is not. The app is intended for use in a lot of 3rd world countries where mobile internet is not ubiquitous.
When I hit a limit of 100 messages, I get a prompt for each message sent. The prompt says "A large number of SMS messages are being sent". This is not ok for the user to get prompted each time to ask if the app can send a text message. The user doesn't want to get 30 consecutive prompts.
I found this android source file with google. It could be out of date, I can't tell. It looks like there is a limit of 100 sms messages every 3600000ms(1 day) for each application.
http://www.netmite.com/android/mydroid/frameworks/base/telephony/java/com/android/internal/telephony/gsm/SMSDispatcher.java
/** Default checking period for SMS sent without uesr permit */
private static final int DEFAULT_SMS_CHECK_PERIOD = 3600000;
/** Default number of SMS sent in checking period without uesr permit */
private static final int DEFAULT_SMS_MAX_ALLOWED = 100;
and
/**
* Implement the per-application based SMS control, which only allows
* a limit on the number of SMS/MMS messages an app can send in checking
* period.
*/
private class SmsCounter {
private int mCheckPeriod;
private int mMaxAllowed;
private HashMap<String, ArrayList<Long>> mSmsStamp;
/**
* Create SmsCounter
* #param mMax is the number of SMS allowed without user permit
* #param mPeriod is the checking period
*/
SmsCounter(int mMax, int mPeriod) {
mMaxAllowed = mMax;
mCheckPeriod = mPeriod;
mSmsStamp = new HashMap<String, ArrayList<Long>> ();
}
boolean check(String appName) {
if (!mSmsStamp.containsKey(appName)) {
mSmsStamp.put(appName, new ArrayList<Long>());
}
return isUnderLimit(mSmsStamp.get(appName));
}
private boolean isUnderLimit(ArrayList<Long> sent) {
Long ct = System.currentTimeMillis();
Log.d(TAG, "SMS send size=" + sent.size() + "time=" + ct);
while (sent.size() > 0 && (ct - sent.get(0)) > mCheckPeriod ) {
sent.remove(0);
}
if (sent.size() < mMaxAllowed) {
sent.add(ct);
return true;
}
return false;
}
}
Is this even the real android code? It looks like it is in the package "com.android.internal.telephony.gsm", I can't find this package on the android website.
How can I disable/modify this limit? I've been googling for solutions, but I haven't found anything.
So I was looking at the link that commonsware.com posted, and I found that the source had actually changed. And so I might still have a shot.
int check_period = Settings.Gservices.getInt(mResolver,
Settings.Gservices.SMS_OUTGOING_CEHCK_INTERVAL_MS,
DEFAULT_SMS_CHECK_PERIOD);
int max_count = Settings.Gservices.getInt(mResolver,
Settings.Gservices.SMS_OUTGOING_CEHCK_MAX_COUNT,
DEFAULT_SMS_MAX_COUNT);
mCounter = new SmsCounter(max_count, check_period);
This is getting checkPeriod and maxCount from a settings table. But I don't seem to have access to the same table. That source should be Android 1.1, which is the same I'm using. When I try to import android.provider.Settings.Gservices, I get an error saying that the import can't be resolved.
What is going on?
Did you try using "import android.provider.Settings;" instead of "import android.provider.Settings.GServices"? (see line 36 of SMSDispatcher.java)
Also, not sure how much difference it makes, but 3600000 ms is one hour not one day.
Unfortunately I think you only have a few options
1) Get root access and alter the settings table directly by doing:
sqlite3 /data/data/com.android.providers.settings/databases/settings.db
sqlite> INSERT INTO gservices (name, value) VALUES
('sms_outgoing_check_interval_ms', 0);
2) Use multiple apps since it's a per app limit
3) Perhaps take out the battery after you reach the limit? It looks like the limit is stored in memory. I haven't tried this yet though.
This appears to be built into the Android source tree, so the only way to push this change down to the users would be the build your own ROM and have them install it.
As for ideas on getting around it, why not check for network connectivity first rather than just assuming it doesn't exist. Even if it is not present on a significant majority of devices today, that certainly won't always be the case. Let SMS be the fall back mechanism. If it is the fall back mechanism, you can then prompt the user letting them know that they will be prompted to confirm the level of SMS activity every 100 messages or so. Who knows, they may roam into a Wifi hotspot and have connectivity part of the day too.
Otherwise, you will get into a game of installing a bunch of other Activities+Intents that can act as silent SMS proxies to get around the limit. Of course, this has its own certain set of undesirable qualities as well and I can hardly believe I just typed/suggested something that evil.