WebRTC unable to decode text message sent from Datachannel - webrtc

I am trying to use WebRTC datachannel for the first time. I can sent text using WebRTC javascript code, and can catch the event from my WebRTC android code.
I am following procedure :
From JavaScript client :
function sendMsg(msg){
if(dataChannel.readyState=="open"){
dataChannel.send(msg); //dataChannel = my datachannel object
}
else{
console.error("data channel no ready");
}
}
From WebRTC android client:
public void onMessage(final Buffer arg0) {
byte[] bytearr = new byte[arg0.data.remaining()];
//Case 1:
Log.e("MSG_GOT",arg0.data.get(bytearr).toString());
//Case 2:
Log.e("MSG_GOT " + arg0.data.toString());
}
For case 1 :
I am getting some unreadable data, which I assume is encoded.
For case 2:
I am getting an object as java.nio.ReadWriteDirectByteBuffer, status: capacity=6 position=6 limit=6 .
I was sending abcdef as text.
How can I decode this into readable text ? Or is there any function provided by WebRTC android api to decode it ?

I am using the following function, that works when I send String payloads.
public void onMessage(DataChannel.Buffer buffer) {
ByteBuffer data = buffer.data;
byte[] bytes = new byte[data.remaining()];
data.get(bytes);
final String message = new String(bytes);
// ...
}
I remember it is from a similar question/answer which I cannot find right now.

Related

Azure service bus Message deserialize broken in core conversion

So, I've created a new Azure Functions project v3 and am porting over a subset of functions from v1 that was running on 4.6.2, while retiring the rest as obsolete. Unfortunately in the change from BrokeredMessage to Message due to changing from Microsoft.ServiceBus.Messaging to Microsoft.Azure.ServiceBus the following deserialization method is now failing with:
There was an error deserializing the object of type stream. The input source is not correctly formatted.
The problem is right there in the error, but Im not sure what the correct new approach is, its a bit unclear.
Serialize
public static Message CreateBrokeredMessage(object messageObject)
{
var message = new Message(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(messageObject)))
{
ContentType = "application/json",
Label = messageObject.GetType().Name
};
return message;
}
Deserialize
public static T ParseBrokeredMessage<T>(Message msg)
{
var body = msg.GetBody<Stream>();
var jsonContent = new StreamReader(body, true).ReadToEnd();
T updateMessage = JsonConvert.DeserializeObject<T>(jsonContent);
return updateMessage;
}
Object
var fileuploadmessage = new PlanFileUploadMessage()
{
PlanId = file.Plan_Id.Value,
UploadedAt = uploadTimeStamp,
UploadedBy = uploadUser,
FileHash = uploadedFileName,
FileName = file.Name,
BusinessUnitName = businessUnitName,
UploadedFileId = uploadedFile.Id
};
```
Message.GetBody<T>() is an extension method for messages sent using the legacy Service Bus SDK (WindowsAzure.ServiceBus package) where BrokeredMessage was populated with anything other than Stream. If your sender sends an array of bytes as you've showed, you should access it using Message.Body property.
In case your message is sent as a BrokeredMessage, the receiving code will need to select either of the methods based on some information to indicate how the message was originally sent.

Read the SMS activation code automatically in Xamarin Forms instead of manually typing it by user

I wrote a project with Xamarin Forms. When every user has signed up, I send him/her an activation Code to confirm it and the user has to insert it to enter the app. But I am looking for a plugin or a way that the user does not need to insert the activation Code.
I want the activation Code to be read automatically without the need to enter it manually.
First add the required permissions in AndroidManifest:
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
Here is SmsReceiver class in Android project:
using System.Linq;
using System.Text.RegularExpressions;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Telephony;
using Java.Lang;
using Xamarin.Forms;
namespace MyProject.Android
{
[BroadcastReceiver(Enabled = true, Label = "SMS Receiver")]
[IntentFilter(new string[] { "android.provider.Telephony.SMS_RECEIVED", Intent.CategoryDefault })]
public class SmsReceiver : BroadcastReceiver
{
private const string IntentAction = "android.provider.Telephony.SMS_RECEIVED";
private static readonly string Sender = "SMS Sender number here";
private static readonly string[] OtpMessageBodyKeywordSet = {"Keyword1", "Keyword2"}; //You must define your own Keywords
public override void OnReceive(Context context, Intent intent)
{
try
{
if (intent.Action != IntentAction) return;
var bundle = intent.Extras;
if (bundle == null) return;
var pdus = bundle.Get("pdus");
// var castedPdus = JNIEnv.GetArray(pdus.Handle);
var castedPdus = JNIEnv.GetArray<Object>(pdus.Handle);
var msgs = new SmsMessage[castedPdus.Length];
var sb = new StringBuilder();
string sender = null;
for (var i = 0; i < msgs.Length; i++)
{
var bytes = new byte[JNIEnv.GetArrayLength(castedPdus[i].Handle)];
JNIEnv.CopyArray(castedPdus[i].Handle, bytes);
string format = bundle.GetString("format");
msgs[i] = SmsMessage.CreateFromPdu(bytes, format);
if (sender == null)
sender = msgs[i].OriginatingAddress;
sb.Append(string.Format("SMS From: {0}{1}Body: {2}{1}", msgs[i].OriginatingAddress,
System.Environment.NewLine, msgs[i].MessageBody));
//Toast.MakeText(context, sb.ToString(), ToastLength.Long).Show();
//Log.Error("Vahid", sb.ToString());
var msgBody = msgs[i].MessageBody;
if(!sender.Contains(Sender)) return;
bool foundKeyword = OtpMessageBodyKeywordSet.Any(k => msgBody.Contains(k));
if (!foundKeyword) return;
var code = ExtractNumber(msgBody);
MessagingCenter.Send<RegisterSecondPageModel, string>(new RegisterSecondPageModel(), "OtpReceived", code);
}
}
catch (System.Exception ex)
{
//Toast.MakeText(context, ex.Message, ToastLength.Long).Show();
}
}
private static string ExtractNumber(string text)
{
if (string.IsNullOrEmpty(text)) return "";
var regPattern = #"\d+";
var number = Regex.Match(text, regPattern).Value;
return number;
}
}
}
Note: In order to filter out the coming SMSes and detect only our own SMS we can apply these two filters:
1- Ignoring all SMSes that their sender numbers are not our SMS sender number.
2- Sometimes our SMS sender might send different SMSes to our clients, for example one SMS to send an activation code, and another to inform and confirm user's successfully registration in system. That said, we gotta distinguish them. For that we can search message body in order to find some pre-defined keywords. Of course our SMS server has to stick to a defined body format. "Activation", "Code", "Activation code" could be some example keywords in English language. Of course keywords should be defined in each language accordingly.
Here is RegisterSecondPageModel inside PCL project:
public class RegisterSecondPageModel
{
public RegisterSecondPageModel()
{
SubscribeToOtpReceiving();
}
private void SubscribeToOtpReceiving()
{
MessagingCenter.Subscribe<RegisterSecondPageModel, string>(this, "OtpReceived", (sender, code) =>
{
ActivationCode = code;
});
}
}
Another note is that as Jason already said, iOS doesn't allow apps to read SMSes.
If you're already sure about your clients having a SIM card in their device, then you can create a token and authenticate backwards, sending an SMS containing your token to from clients' device to your number.
Pros:
No blocked numbers: Sending messages from client is not blocked even if you're on their blacklist or they're blocking advertisements and unknown senders.
No costs on your side for authentication.
This works also in iOS which you can't read but can send messages.
Cons:
Client may be using another number in another device. This can be overcome by creating easy-to-type tokens which expire fast enough not to attract brute force attacks.
Client may not be able to send an SMS to your number due to several reasons including but not limited to not having enough account charge.

onPayloadReceived Nearby connections 2.0 doesn't receive File payload

#Override
public void onPayloadReceived(String endpointId, Payload payload) {
if (payload.getType() == Payload.Type.BYTES) {
String payloadFilenameMessage = new String(payload.asBytes(), "UTF-8");
addPayloadFilename(payloadFilenameMessage);
} else if (payload.getType() == Payload.Type.FILE) {
// Add this to our tracking map, so that we can retrieve the payload later.
incomingPayloads.add(payload.getId(), payload);
}
}
The issue is that the payload.getType() == Payload.Type.FILE condition is never true, only the Payload.Type.BYTES condition is true.
The sendPayload() snippet is from the Exchange Data API page.
// The URI of the file selected by the user.
Uri uri = resultData.getData();
// Open the ParcelFileDescriptor for this URI with read access.
ParcelFileDescriptor pfd = getContentResolver().openFileDescriptor(uri, "r");
Payload filePayload = Payload.fromFile(pfd);
// Finally, send the file payload.
Nearby.Connections.sendPayload(endpointId, filePayload);
I know it's a duplicate, but I haven't found any working solution in web (regarding sending files) at least to compare my code with (unfinished medium article (text), walkie talkie app (stream), and fragments of from documentation)
here's sources https://github.com/salexwm/FilesExchange
It looks like your code to send the file payload is commented out at https://github.com/salexwm/FilesExchange/blob/master/app/src/main/java/com/test/filesexchange/ShareService.java#L199 (and it hasn't been updated since you posted this question, so could that be it?)

How i can sing up with restcomm correctly?

Already few weeks i try sing up on SIP service with restcomm for android. I check connection with third-party application (cSipSimple) and everything works correctly. But when i try coonection with restcomm demo app, connection falls everytime after 4 seconds. Whats wrong with my sdk or how i can sing up right?
SipProfile sipProfile = new SipProfile();
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("pref_proxy_ip", "my.server.ip");
params.put("pref_proxy_port", "5060");
params.put("pref_sip_user", "7879114");
params.put("pref_sip_password", "EeFei2Fa");
for (String key : params.keySet()) {
if (key.equals("pref_proxy_ip")) {
sipProfile.setRemoteIp((String) params.get(key));
} else if (key.equals("pref_proxy_port")) {
sipProfile.setRemotePort(Integer.parseInt((String) params.get(key)));
} else if (key.equals("pref_sip_user")) {
sipProfile.setSipUserName((String) params.get(key));
} else if (key.equals("pref_sip_password")) {
sipProfile.setSipPassword((String) params.get(key));
}
}
final SipManager sipManager = new SipManager(sipProfile, true);
Register registerRequest = new Register();
final Request r = registerRequest.MakeRequest(sipManager, 100000, null);
// Send the request statefully, through the client transaction.
Thread thread = new Thread() {
public void run() {
try {
final ClientTransaction transaction = sipManager.sipProvider.getNewClientTransaction(r);
transaction.sendRequest();
} catch (SipException e) {
e.printStackTrace();
}
}
};
thread.start();
#Vladislav, you are using the low level facilities of the SDK which are obsolete and not meant to be used directly. I would suggest that you use the RestCommClient API as exposed by the SDK directly. It is much easier to use and provides the same functionality and more.
For an example on how to use it please check:
https://github.com/RestComm/restcomm-android-sdk/blob/master/Examples/restcomm-helloworld/app/src/main/java/com/telestax/restcomm_helloworld/MainActivity.java
You need to change the SIP server settings from:
https://github.com/RestComm/restcomm-android-sdk/blob/master/Examples/restcomm-helloworld/app/src/main/java/com/telestax/restcomm_helloworld/MainActivity.java#L99
And the called party from:
https://github.com/RestComm/restcomm-android-sdk/blob/master/Examples/restcomm-helloworld/app/src/main/java/com/telestax/restcomm_helloworld/MainActivity.java#L174
Just keep in mind that for media Webrtc is used so that NATs can be handled properly. This means that the receiving party needs to be able to handle Webrtc as well. Unless there's a server in the middle handling the mediation, like Restcomm-Connect.
For more information please check RestComm Client Android SDK Quick Start

Parse Push Notfications in MonoDroid

So I'm using the Parse component from the Xamarin store in my MonoDroid app. So I was able to use the following code to store an object
ParseClient.Initialize ("appid", "windowskey");
var obj = new ParseObject("Note");
obj ["text"] = "Hello, world! This is a Xamarin app using Parse!";
obj ["tags"] = new List<string> {"welcome", "xamarin", "parse"};
obj.SaveAsync ();
My real goal is to be able to do push notifications. Even though the above object stored, Parse did not register the device in the installations to be able to send push notifications. What else am I missing. Note: I'm doing this in the emulator but if i'm not mistaken it still should work.
#basit-zia, yes I did! I had to create a binding for the push library from the Java Parse SDK. I believe I was able to strip away all the libraries except for the necessary elements. I can't remember exactly what I did though.
Then in the Main Activity class, I put the following into the OnStart() method:
// check for a notification
if (Intent != null)
try {
string jsonString = Intent.Extras.GetString("com.parse.Data");
PushObject jsonObj = JsonConvert.DeserializeObject<PushObject>(jsonString);
if (jsonObj.alert != null) {
Toast.MakeText (BaseContext, jsonObj.alert, ToastLength.Long).Show ();
}
} catch (Exception e) {
Console.WriteLine ("JSONException: " + e.Message);
}
And put the following into the OnCreate() method:
Com.Parse.Parse.Initialize(this, "app id here"}, "client key here");
PushService.SetDefaultPushCallback (this, this.Class);
PushService.StartServiceIfRequired (this);
ParseInstallation.CurrentInstallation.SaveInBackground ();