How can I detect the last character of GSM modem response - c

I am using a GSM modem "SIM900"
I have tested it with hyper terminal and main command is ok.
Then I burnt the code to send the AT command to dial a number on the Microcontroller to the GSM modem using UART and it works fine.
But I'm having a problem with the response.
The GSM replies with stream of characters but it doesn't end with Null '\0' !
How can I get the whole response in array to parse it later? And, how can I detect the end of response?
AT\r\n response is ==> OK
AT+CMGR=1 response is ==> +CMGR: "REC UNREAD" ,"+2347060580383","10/10/27,18:54:32+04"
Thanks in advance.

You can use \r\nOK for the ending, because phones use \n only for NewLine. But there's a more reliable way (I did that once) to make sure you don't get the wrong ending, for example when the incoming text message had the exact \r\nOK in it. In order to do that, I suggest that you change the Character Set to UCS2, so you will get the message text and sender number in UnicodeArray (It's like it is been escaped.)
Here's the class I used for my purpose (The extra check modules (AT\r command) are used to prevent getting stuck in error, in case there's an unexpected error or something like that! And the module I had sometimes went unresponsive, so with this I could make it again responsive! Doesn't seem logical, but saved me! Works perfectly for me now!):
public class SMSController
{
public event EventHandler StatusChanged;
protected virtual void OnStatusChanged()
{
if (StatusChanged != null)
{
StatusChanged(this, EventArgs.Empty);
}
}
SerialPort serial;
public SMSController(SerialPort serialPort)
{
this.serial = serialPort;
}
string readLine(int timeout = -1)
{
int oldTo = serial.ReadTimeout;
serial.ReadTimeout = timeout;
string str = serial.ReadTo("\n").Replace("\n", "").Replace("\r", "");
serial.ReadTimeout = oldTo;
return str;
}
void writeLine(string str)
{
serial.Write(str + "\r\n");
}
bool waitForString(string str, int timeout = -1)
{
if (readLine(timeout).Contains(str))
{
return true;
}
return false;
}
bool waitForOK(int timeout = -1, bool repeat = true)
{
if (repeat)
{
readUntilFind("OK", timeout);
return true;
}
else
return waitForString("OK", timeout);
}
void readUntilFind(string str, int timeout = -1)
{
while (!waitForString(str, timeout)) ;
}
void writeCommand(string command)
{
serial.DiscardInBuffer();
writeLine(command);
}
bool applyCommand(string command, int timeout = -1)
{
writeCommand(command);
return waitForOK(timeout);
}
private string lastStatus = "Ready";
public string LastStatus
{
get { return lastStatus; }
private set
{
lastStatus = value;
OnStatusChanged();
}
}
public void InitModule()
{
try
{
LastStatus = "Checking SIM900...";
applyCommand("ATE0", 2000); //Disable echo
applyCommand("AT", 5000); //Check module
LastStatus = "Initializing SIM900...";
applyCommand("AT+CMGF=1", 1000); //Set SMS format to text mode
LastStatus = "Operation successful!";
}
catch (TimeoutException)
{
LastStatus = "Operation timed-out";
}
catch (Exception ex)
{
LastStatus = ex.Message;
}
}
public static string ConvertToUnicodeArray(string str)
{
byte[] byt = Encoding.Unicode.GetBytes(str);
string res = "";
for (int i = 0; i < byt.Length; i+=2)
{
res += byt[i + 1].ToString("X2");
res += byt[i].ToString("X2");
}
return res;
}
public void SendMessage(string destinationNumber, string text, bool isUnicode = false)
{
try
{
LastStatus = "Initiating to send...";
applyCommand("AT+CSMP=17,167,2,25", 1000);
if (isUnicode)
{
if (!applyCommand("AT+CSCS=\"UCS2\"", 5000))
throw new Exception("Operation failed!");
writeCommand("AT+CMGS=\"" + ConvertToUnicodeArray(destinationNumber) + "\"");
}
else
{
if (!applyCommand("AT+CSCS=\"GSM\"", 5000))
throw new Exception("Operation failed!");
writeCommand("AT+CMGS=\"" + destinationNumber + "\"");
}
waitForString("> ", 5000);
LastStatus = "Sending...";
serial.DiscardInBuffer();
serial.Write(isUnicode ? ConvertToUnicodeArray(text) : text);
serial.Write(new byte[] { 0x1A }, 0, 1);
if (waitForOK(30000))
{
LastStatus = "Message sent!";
}
else
LastStatus = "Sending failed!";
}
catch (TimeoutException)
{
LastStatus = "Operation timed-out";
}
catch (Exception ex)
{
LastStatus = ex.Message;
}
}
private string readTo(string str, int timeout)
{
int to = serial.ReadTimeout;
serial.ReadTimeout = timeout;
string strread = serial.ReadTo(str);
serial.ReadTimeout = to;
return strread;
}
public static byte[] StringToByteArray(string hex)
{
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
public static string ConvertUnicodeToText(string bytes)
{
byte[] bt = StringToByteArray(bytes);
for (int i = 0; i < bt.Length; i+=2)
{
byte swap = bt[i];
bt[i] = bt[i + 1];
bt[i + 1] = swap;
}
return Encoding.Unicode.GetString(bt);
}
public SMS[] GetUnreadMessages()
{
List<SMS> lst = new List<SMS>();
try
{
LastStatus = "Initializing...";
applyCommand("AT+CSMP=17,167,2,25", 1000);
applyCommand("AT+CSCS=\"UCS2\"", 2000);
LastStatus = "Fetching text messages...";
writeCommand("AT+CMGL=\"REC UNREAD\"");
string texts = readTo("OK\r\n", 10000);
string[] packets = texts.Split(new string[] { "\r\n\r\n" }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < packets.Length; i++)
{
if (!packets[i].Contains("+CMGL"))
continue;
string num = packets[i].Split(new string[] { "," },
StringSplitOptions.RemoveEmptyEntries)[2].Replace("\"", "");
string txt = packets[i].Split(new string[] { "\r\n" },
StringSplitOptions.RemoveEmptyEntries)[1].Replace("\"", "");
lst.Add(new SMS(ConvertUnicodeToText(num), ConvertUnicodeToText(txt)));
}
applyCommand("AT+CMGDA=\"DEL READ\"", 10000);
LastStatus = "Operation successful!";
}
catch (TimeoutException)
{
LastStatus = "Operation timed-out";
}
catch (Exception ex)
{
LastStatus = ex.Message;
}
return lst.ToArray();
}
}

Test for a new-line, which typical is \n or \r\n.
A NUL (0 or '\0') is only used in C to terminate a character array, a "string".

Related

System.IndexOutOfRangeException in c# window form

I have been trying too parse 2 parameter using for loop but it only loop once and locates one parameter. This is my code.
By providing rectangle 70,80 command in the form, I am trying to draw shapes but while passing through check variable for loop works only once. It does not increments but returns value only after first execution then goes to check number of parameter then rejects with error Array out of bounds.
public String[] ParameterSplit;
public IDictionary<string, int> VariableDictionary = new Dictionary<string, int>();
public IDictionary<string, int> MethodVariableDictionary = new Dictionary<string, int>();
public Boolean AlreadyInArray = false;
public Boolean Value1IsVariable = false;
public Boolean Value2IsVariable = false;
public int value = 0;
public int value1 = 0;
public int value2 = 0;
public CommandParser()
{
}
//This method is used for the validation of commands and parameters which passes thorough
//singleline command and multiline command method
public string[] CommandParsers(string input, int lineCount)
{
string[] text = { };
string[] inputcommand = input.Split(',', ' ');
if (inputcommand[0].ToUpper() == "MOVETO")
{
if(inputcommand.Length < 4)
{
Convert.ToInt32(inputcommand[1]);
Convert.ToInt32(inputcommand[2]);
text = inputcommand;
}
}
else
{
if (inputcommand[0].ToUpper() == "DRAWTO")
{
if (inputcommand.Length == 3)
{
Convert.ToInt32(inputcommand[1]);
Convert.ToInt32(inputcommand[2]);
text = inputcommand;
}
else
{
MessageBox.Show($"ERROR: Provide correct parameter for moveto in line no {lineCount}");
string[] strings = { "moveto,100,100" };
text = strings;
}
}
else if (inputcommand[0].ToUpper() == "RECTANGLE")
{
ParameterSplit = inputcommand[1].Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
CheckForVariable();
if (ParameterSplit.Length == 2)
{
}
else
{
Convert.ToInt32(ParameterSplit[0]);
Convert.ToInt32(ParameterSplit[1]);
text = ParameterSplit;
}
}
else if (inputcommand[0].ToUpper() == "CIRCLE")
{
if (inputcommand.Length == 2)
{
Convert.ToInt32(inputcommand[1]);
text = inputcommand;
}
else
{
MessageBox.Show("ERROR: Provide correct parameter for circle in line no " + lineCount );
string[] strings = { "circle,20" };
text = strings;
}
}
else if (inputcommand[0].ToUpper() == "TRIANGLE")
{
if (inputcommand.Length == 3)
{
Convert.ToInt32(inputcommand[1]);
Convert.ToInt32(inputcommand[2]);
text = inputcommand;
}
else
{
MessageBox.Show("ERROR: Provide correct parameter for triangle in line no "+ lineCount);
string[] strings = { "triangle,20,60" };
text = strings;
}
}
else if (inputcommand[0].ToUpper() == "PEN")
{
Pen = true;
string[] validateinput = { "pen", inputcommand[1] };
text = validateinput;
switch (inputcommand[1])
{
case "red":
color = Color.Red;
break;
case "blue":
color = Color.Blue;
break;
case "yellow":
color = Color.Yellow;
break;
case "green":
color = Color.Green;
break;
case "violet":
color = Color.Violet;
break;
}
}
else if (inputcommand[0].ToUpper() == "FILL")
{
string[] validateinput = { "fill", inputcommand[1] };
text = validateinput;
switch (inputcommand[1])
{
case "on":
fill = true;
break;
case "off":
fill = false;
break;
}
}
else if (inputcommand.Length > 2)
{
text = inputcommand;
//checks if the middle element is a "="
if(inputcommand[1].ToUpper() == "=")
{
//check if the variable is already stored or not
//StoreVarialable();
foreach(KeyValuePair<string,int> variable in VariableDictionary)
{
if (variable.Key.Equals(inputcommand[0]))
{
AlreadyInArray = true;
}
}
foreach(KeyValuePair<string,int> variable in VariableDictionary)
{
if(variable.Key.Equals(inputcommand[2]))
{
value1 = variable.Value;
Value1IsVariable = true;
}
}
if(inputcommand.Length.Equals(5))
{
foreach(KeyValuePair<string,int> variable in VariableDictionary)
{
if (variable.Key.Equals(inputcommand[4]))
{
value2 = variable.Value;
Value2IsVariable = true;
}
}
if (AlreadyInArray)
{
VariableDictionary.Remove(inputcommand[0]);
}
}
try
{
if (Value1IsVariable.Equals(false))
{
value1 = Convert.ToInt32(inputcommand[2]);
}
if (Value2IsVariable.Equals(false))
{
if (inputcommand.Length.Equals(5))
{
value2 = Convert.ToInt32(inputcommand[4]);
}
}
if (inputcommand.Length > 3)
{
if (inputcommand[3].Equals("+"))
{
value = value1 + value2;
}
else if (inputcommand[3].Equals("-"))
{
value = value1 - value2;
}
else
{
//InvalidOperator();
}
}
else
{
try
{
value = int.Parse(inputcommand[2]);
}
catch (FormatException ex)
{
//If it is not an integer throw an error
//ValueIsIncorrect();
}
}
//Adds the variable with the inputted value if it is an integer
// VariableDictionary.Add(inputcommand[0], value);
}
catch (FormatException ex)
{
//If it is not an integer throw an error
//ValueIsIncorrect();
//return;
}
}
else
{
}
}
else
{
string[] validateinput = { "error" };
text = validateinput;
}
//end of condition
}
return text;
}
public void CheckForVariable()
{
//Loops through all the parameters
for (int i = 0; i<ParameterSplit.Length ; i++)
{
int index = i;
try
{
//Checks if the parameter is an int
int test = int.Parse(ParameterSplit[index]);
}
catch
{
Boolean foundVariable = false;
foreach (KeyValuePair<string, int> variable in MethodVariableDictionary)
{
if (variable.Key.Equals(ParameterSplit[index]))
{
//if it is then assign the parameter the integer value of the variable
ParameterSplit[index] = variable.Value.ToString();
//ErrorList = ErrorList + variable.Key + ParameterSplit[i] + Environment.NewLine; ;
foundVariable = true;
}
}
if (foundVariable == false)
{
//if it is not then loop through the VariableDictionary to check if the parameter is a variable name
foreach (KeyValuePair<string, int> variable in VariableDictionary)
{
if (variable.Key.Equals(ParameterSplit[i]))
{
//if it is then assign the parameter the integer value of the variable
ParameterSplit[i] = variable.Value.ToString();
}
}
}
}
}
}
//This method is used to get the color from pen by returning its values
internal Color getColor()
{
return color;
}
}
I tried this where I have to check 2 parameter using for loop inside CheckForVariable method

Encode InputStream response as UTF-8

I'm trying to make a connection to a URL which displays some data in plain text on a webpage (it's a block of text in between <pre> tags). Whenever a character with a character with a special character is passed through (for example é or ì) it displays a question mark instead of the character a �
is displayed. I've tried using this but that didn't change much. I can't read the page per line so I'm pretty much stuck here.
Here is my code:
try
{
// Open the connection
NetworkManager networkManager = NetworkManager.getInstance();
networkManager.addErrorListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
NetworkEvent n = (NetworkEvent) evt;
n.getError().printStackTrace();
success = false;
}
});
ConnectionRequest request = new ConnectionRequest()
{
{
setTimeout(40000);
}
#Override
protected void readResponse(InputStream input) throws IOException
{
InputStreamReader inputStreamReader = new InputStreamReader(input, "UTF-8");
int chr;
buffer = new StringBuilder();
//reading the answer
while ((chr = inputStreamReader.read()) != -1)
{
System.out.println("Append the character " + (char) chr);
buffer.append((char) chr);
}
response = buffer.toString();
response = response.trim();
data = new byte[buffer.length()];
int tmpCounter = buffer.length();
counter = 0;
while (counter != buffer.length())
{
for (int i = 0; i < tmpCounter; i++)
{
data[counter + i] = (byte) buffer.charAt(i);
}
counter += tmpCounter;
}
process(data);
dataEvent.setDataAvailable();
}
#Override
protected void handleException(Exception err)
{
success = false;
dataEvent.setDataAvailable();
}
};
request.setUrl(url);
request.setPost(false);
networkManager.addToQueue(request);
}
catch (Exception x)
{
x.printStackTrace();
}
Turns out the actual response didn't respond using UTF-8 the characters were just readable in my browser. I fixed it by specifying the response characters should be UTF-8

Is there any way to pass Observable<String> into AbstractInputStreamContent?

I'm working on uploading a text file to Google Drive
ByteArrayContent content = new ByteArrayContent("text/csv", fileContent.getBytes(Charset.forName("UTF-8")));
Drive.Files.Insert request = drive.files().insert(file, content);
where type(fileContent) = String
I'd like to refactor and change type of fileContent to Observable<String>, is there any nice workaround to pass it to that insert() function (which takes AbstractInputStreamContent as a second argument)?
Thanks
Here is a general Flowable -> InputStream bridge you can delegate to:
import java.io.*;
import java.nio.charset.Charset;
import java.util.concurrent.atomic.AtomicReference;
import org.reactivestreams.*;
import io.reactivex.FlowableSubscriber;
import io.reactivex.internal.subscriptions.SubscriptionHelper;
public final class FlowableStringInputStream {
private FlowableStringInputStream() {
throw new IllegalStateException("No instances!");
}
public static InputStream createInputStream(
Publisher<String> source, Charset charset) {
StringInputStream parent = new StringInputStream(charset);
source.subscribe(parent);
return parent;
}
static final class StringInputStream extends InputStream
implements FlowableSubscriber<String> {
final AtomicReference<Subscription> upstream;
final Charset charset;
volatile byte[] bytes;
int index;
volatile boolean done;
Throwable error;
StringInputStream(Charset charset) {
this.charset = charset;
upstream = new AtomicReference<>();
}
#Override
public void onSubscribe(Subscription s) {
if (SubscriptionHelper.setOnce(upstream, s)) {
s.request(1);
}
}
#Override
public void onNext(String t) {
bytes = t.getBytes(charset);
synchronized (this) {
notifyAll();
}
}
#Override
public void onError(Throwable t) {
error = t;
done = true;
synchronized (this) {
notifyAll();
}
}
#Override
public void onComplete() {
done = true;
synchronized (this) {
notifyAll();
}
}
#Override
public int read() throws IOException {
for (;;) {
byte[] a = awaitBufferIfNecessary();
if (a == null) {
Throwable ex = error;
if (ex != null) {
if (ex instanceof IOException) {
throw (IOException)ex;
}
throw new IOException(ex);
}
return -1;
}
int idx = index;
if (idx == a.length) {
index = 0;
bytes = null;
upstream.get().request(1);
} else {
int result = a[idx] & 0xFF;
index = idx + 1;
return result;
}
}
}
byte[] awaitBufferIfNecessary() throws IOException {
byte[] a = bytes;
if (a == null) {
synchronized (this) {
for (;;) {
boolean d = done;
a = bytes;
if (a != null) {
break;
}
if (d || upstream.get() == SubscriptionHelper.CANCELLED) {
break;
}
try {
wait();
} catch (InterruptedException ex) {
if (upstream.get() != SubscriptionHelper.CANCELLED) {
InterruptedIOException exc = new InterruptedIOException();
exc.initCause(ex);
throw exc;
}
break;
}
}
}
}
return a;
}
#Override
public int read(byte[] b, int off, int len) throws IOException {
if (off < 0 || len < 0 || off >= b.length || off + len > b.length) {
throw new IndexOutOfBoundsException(
"b.length=" + b.length + ", off=" + off + ", len=" + len);
}
for (;;) {
byte[] a = awaitBufferIfNecessary();
if (a == null) {
Throwable ex = error;
if (ex != null) {
if (ex instanceof IOException) {
throw (IOException)ex;
}
throw new IOException(ex);
}
return -1;
}
int idx = index;
if (idx == a.length) {
index = 0;
bytes = null;
upstream.get().request(1);
} else {
int r = 0;
while (idx < a.length && len > 0) {
b[off] = a[idx];
idx++;
off++;
r++;
len--;
}
index = idx;
return r;
}
}
}
#Override
public int available() throws IOException {
byte[] a = bytes;
int idx = index;
return a != null ? Math.max(0, a.length - idx) : 0;
}
#Override
public void close() throws IOException {
SubscriptionHelper.cancel(upstream);
synchronized (this) {
notifyAll();
}
}
}
}
Usage:
#Test(timeout = 10000)
public void async() throws Exception {
AtomicInteger calls = new AtomicInteger();
Flowable<String> f = Flowable.range(100, 10).map(Object::toString)
.doOnCancel(() -> calls.incrementAndGet())
.subscribeOn(Schedulers.computation())
.delay(10, TimeUnit.MILLISECONDS);
try (InputStream is = FlowableStringInputStream.createInputStream(f, utf8)) {
assertEquals('1', is.read());
assertEquals('0', is.read());
assertEquals('0', is.read());
byte[] buf = new byte[3];
assertEquals(3, is.read(buf));
assertArrayEquals("101".getBytes(utf8), buf);
}
assertEquals(1, calls.get());
}

LZH in Byte Array Decompress in .NET?

An LZH archive is embedded within a file. The file was read into a byte[], and the LZH part is identified as a smaller byte[].
How can the embedded LZH bytes be decompressed into another byte[] using .NET Framework 4.6 (C#)? I have only see http://www.infoq.com/news/2008/06/7-Zip-from-.NET which doesn't exactly do what I need.
Thanks.
the code snippet that follows is taken from the sample program from this article
http://www.codeproject.com/Articles/27148/C-NET-Interface-for-Zip-Archive-DLLs
There are no significant changes: instead of reading and writing files, it reads and write byte arrays. Changes are marked by comments
Run with sevenzip.exe e "C:\temp\gwo0.11-sample-win32.lzh" 3 for example
https://dl.dropboxusercontent.com/u/71459360/7z.zip
using System;
using System.Collections.Generic;
using System.Text;
using Nomad.Archive.SevenZip;
using System.IO;
using System.Runtime.InteropServices;
using System.Reflection;
namespace SevenZip
{
class Program
{
private static void ShowHelp()
{
Console.WriteLine("SevenZip");
Console.WriteLine("SevenZip l {ArchiveName}");
Console.WriteLine("SevenZip e {ArchiveName} {FileNumber}");
}
static void Main(string[] args)
{
if (args.Length < 2)
{
ShowHelp();
return;
}
try
{
string ArchiveName;
uint FileNumber = 0xFFFFFFFF;
bool Extract;
switch (args[0])
{
case "l":
ArchiveName = args[1];
Extract = false;
break;
case "e":
ArchiveName = args[1];
Extract = true;
if ((args.Length < 3) || !uint.TryParse(args[2], out FileNumber))
{
ShowHelp();
return;
}
break;
default:
ShowHelp();
return;
}
using (SevenZipFormat Format = new SevenZipFormat(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "7z.dll")))
{
IInArchive Archive = Format.CreateInArchive(SevenZipFormat.GetClassIdFromKnownFormat(KnownSevenZipFormat.Lzh));
if (Archive == null)
{
ShowHelp();
return;
}
try
{
//the byte array is provided by you. here it's coming from a file
byte[] data;
using (var stream = File.OpenRead(ArchiveName))
{
data = new byte[stream.Length];
stream.Read(data, 0, data.Length);
}
using (InStreamWrapper ArchiveStream = new InStreamWrapper(new MemoryStream(data))) //modified here
{
ulong CheckPos = 32 * 1024;
if (Archive.Open(ArchiveStream, ref CheckPos, null) != 0)
ShowHelp();
Console.Write("Archive: ");
Console.WriteLine(ArchiveName);
if (Extract)
{
PropVariant Name = new PropVariant();
Archive.GetProperty(FileNumber, ItemPropId.kpidPath, ref Name);
string FileName = (string) Name.GetObject();
Console.Write("Extracting: ");
Console.Write(FileName);
Console.Write(' ');
MemoryStream ms = new MemoryStream();
Archive.Extract(new uint[] { FileNumber }, 1, 0, new ArchiveMemoryCallback(FileNumber, ms)); //modified here
byte[] output = ms.ToArray(); //here you have the output byte array
output.ToString();
}
else
{
Console.WriteLine("List:");
uint Count = Archive.GetNumberOfItems();
for (uint I = 0; I < Count; I++)
{
PropVariant Name = new PropVariant();
Archive.GetProperty(I, ItemPropId.kpidPath, ref Name);
Console.Write(I);
Console.Write(' ');
Console.WriteLine(Name.GetObject());
}
}
}
}
finally
{
Marshal.ReleaseComObject(Archive);
}
}
}
catch (Exception e)
{
Console.Write("Error: ");
Console.WriteLine(e.Message);
}
}
}
class ArchiveCallback : IArchiveExtractCallback
{
private uint FileNumber;
private string FileName;
private OutStreamWrapper FileStream;
public ArchiveCallback(uint fileNumber, string fileName)
{
this.FileNumber = fileNumber;
this.FileName = fileName;
}
#region IArchiveExtractCallback Members
public void SetTotal(ulong total)
{
}
public void SetCompleted(ref ulong completeValue)
{
}
public int GetStream(uint index, out ISequentialOutStream outStream, AskMode askExtractMode)
{
if ((index == FileNumber) && (askExtractMode == AskMode.kExtract))
{
string FileDir = Path.GetDirectoryName(FileName);
if (!string.IsNullOrEmpty(FileDir))
Directory.CreateDirectory(FileDir);
FileStream = new OutStreamWrapper(File.Create(FileName));
outStream = FileStream;
}
else
outStream = null;
return 0;
}
public void PrepareOperation(AskMode askExtractMode)
{
}
public void SetOperationResult(OperationResult resultEOperationResult)
{
FileStream.Dispose();
Console.WriteLine(resultEOperationResult);
}
#endregion
}
//new
class ArchiveMemoryCallback : IArchiveExtractCallback
{
private uint FileNumber;
private Stream stream;
private OutStreamWrapper FileStream;
public ArchiveMemoryCallback(uint fileNumber, Stream stream)
{
this.FileNumber = fileNumber;
this.stream = stream;
}
#region IArchiveExtractCallback Members
public void SetTotal(ulong total)
{
}
public void SetCompleted(ref ulong completeValue)
{
}
public int GetStream(uint index, out ISequentialOutStream outStream, AskMode askExtractMode)
{
if ((index == FileNumber) && (askExtractMode == AskMode.kExtract))
{
FileStream = new OutStreamWrapper(stream);
outStream = FileStream;
}
else
outStream = null;
return 0;
}
public void PrepareOperation(AskMode askExtractMode)
{
}
public void SetOperationResult(OperationResult resultEOperationResult)
{
FileStream.Dispose();
Console.WriteLine(resultEOperationResult);
}
#endregion
}
}

Get IMSI from the SIM using codename1

I need to get the IMSI (International
Mobile Subsriber Identity) stored in the SIM card using codename1. Also in the case of dual or tri SIM phones, i need to get the IMSI for each SIM. Please, How do i get it?
Display.getMsisdn() will work for some devices but most don't allow accessing that information. For more information you can just use a native interface if you can access it that way.
Another way to get IMSI for dual Sim device:
Try this .. its working for me. Idea is to call service for iphonesubinfo function#3. you will get output as parcel value thats why I use getNumberFromParcel to extract number.
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* Created by Apipas on 6/4/15.
*/
public class SimUtil {
public static String getIMSI_1() {
String imsiParcel = runCommand("service call iphonesubinfo 3");
String imsi = getNumberFromParcel(imsiParcel);
Log.d("apipas", "IMSI_1:" + imsi);
return imsi;
}
public static String getIMSI_2() {
String imsiParcel = runCommand("service call iphonesubinfo2 3");
String imsi = getNumberFromParcel(imsiParcel);
Log.d("apipas", "IMSI_2:" + imsi);
return imsi;
}
public static String runCommand(String src) {
try {
Process process = Runtime.getRuntime().exec(src);
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
int read;
char[] buffer = new char[2048];
StringBuffer output = new StringBuffer();
while ((read = reader.read(buffer)) > 0) {
output.append(buffer, 0, read);
}
reader.close();
// Waits for the command to finish.
process.waitFor();
return output.toString();
} catch (IOException e) {
Log.e("apipas", "IOException:" + e.getMessage());
return null;
} catch (InterruptedException e) {
Log.e("apipas", "InterruptedException:" + e.getMessage());
return null;
}
}
public static String getNumberFromParcel(String str) {
String res = "";
if (str != null && str.length() > 0) {
String lines[] = str.split("\n");
for (String line : lines) {
if (line == null || line.length() == 0)
continue;
String content[] = line.split("'");
if (content.length > 1) {
res += content[1].replace(".", "");
}
}
} else return "NA";
return res;
}
}
Then call these static methods like:
String imsi1 = SimUtil.getIMSI_1();
String imsi2 = SimUtil.getIMSI_2();
You'd need to set this permission:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

Resources