Print in bluetooth device-Xamarin - xamarin

I am developing a cross platform app.
I need print in printer Intermec PR2
I use this codes:
Class in .Droid
[assembly: Xamarin.Forms.Dependency(typeof(clsBluetooth))]
namespace Bluetooth.Droid
{
public class clsBluetooth : IBluetooth
{
private BluetoothAdapter adapter = BluetoothAdapter.DefaultAdapter;
private BluetoothSocket socket = null;
private BufferedWriter outReader = null;
private BluetoothDevice device = null;
public void Imprimir(string pStrNomBluetooth, int intSleepTime, string pStrTextoImprimir)
{
try
{
string bt_printer = (from d in adapter.BondedDevices
where d.Name == pStrNomBluetooth
select d).FirstOrDefault().ToString();
device = adapter.GetRemoteDevice(bt_printer);
UUID applicationUUID = UUID.FromString("00001101-0000-1000-8000-00805f9b34fb");
socket = device.CreateRfcommSocketToServiceRecord(applicationUUID);
socket.Connect();
outReader = new BufferedWriter(new OutputStreamWriter(socket.InputStream));
outReader.WriteAsync(pStrTextoImprimir);
}
catch (Exception)
{
throw;
}
finally
{
}
}
public ObservableCollection<string> PairedDevices()
{
ObservableCollection<string> devices = new ObservableCollection<string>();
foreach (var bd in adapter.BondedDevices)
devices.Add(bd.Name);
return devices;
}
}
}
Interface in Potable
public interface IBluetooth
{
ObservableCollection<string> PairedDevices();
void Imprimir(string pStrNomBluetooth, int intSleepTime, string pStrTextoImprimir);
}
Call of method
DependencyService.Get<IBluetooth>().Imprimir(SelectedBthDevice,200,"HolaMundo");
My error happens when I enter the class in the .Droid and it executes the sentence socket.Connect (); Does not seem to connect to the device.
Someone could help me to see the script or how the code could change so that the connection to the device works correctly

Try creating the insecure socket communication like:
socket = device.CreateInsecureRfcommSocketToServiceRecord(applicationUUID);
instead of the existing secure one:
socket = device.CreateRfcommSocketToServiceRecord(applicationUUID);
If you are able to connect after that you can write to printer as follows:
byte[] buffer = Encoding.UTF8.GetBytes(pStrTextoImprimir);
socket.OutputStream.Write(buffer, 0, buffer.Length);
For further details refer to.

Related

TCP connection in Unity

I'm working on TCP connection between two Windows10 laptops. I made the applications using Unity 2019.2.17f1. However, the TCP connection doesn't work. The Client application connects to the server only when I don't run the server application (this is strange though...), otherwise the client application shows the message "server is not found...".
I put the part of the codes here.
Client Program:
public class TCPClientManager : MonoBehaviour
{
// ip address(server) and port number
public string ipAddress = "192.0.0.1";
public int port = 3000;
private TcpClient m_tcpClient;
private NetworkStream m_networkStream;
private bool m_isConnection;
private string message;
void Start()
{
try
{
// connect to the server
m_tcpClient = new TcpClient(ipAddress, port);
m_networkStream = m_tcpClient.GetStream();
m_isConnection = true;
}
catch (SocketException)
{
m_isConnection = false;
// show a error message
// ...
}
}
void OnGUI()
{
if (m_isConnection)
{
GUILayout.Label("server is not found...");
return;
}
// some codes here
}
// some codes here
}
Server Program:
public class TCPServerManager : MonoBehaviour
{
// ip address(server) and port number
public string ipAddress = "192.0.0.1";
public int port = 3000;
private TcpListener m_tcpListener;
private TcpClient m_tcpClient;
private NetworkStream m_networkStream;
private bool m_isConnection;
private string message = string.Empty;
private void Awake()
{
Task.Run(() => OnProcess());
}
private void OnProcess()
{
var n_IpAddress = IPAddress.Parse(ipAddress);
m_tcpListener = new TcpListener(n_IpAddress, port);
m_tcpListener.Start();
m_tcpClient = m_tcpListener.AcceptTcpClient();
m_networkStream = m_tcpClient.GetStream();
while (true)
{
var buffer = new byte[256];
var count = m_networkStream.Read(buffer, 0, buffer.Length);
if (count == 0)
{
OnDestroy();
Task.Run(() => OnProcess());
break;
}
message += Encoding.UTF8.GetString(buffer, 0, count) + "\n";
}
}
// ....
}
Thank you very much for your comments in advice.
I think you inverted you m_isConnection variables values. You set it to true after connecting the server and false if not. But in OnGUI, if you found the connection then you print an error message and leave. Which means you do your //some code here only if no server was found.

Xamarin.Forms how open default email client on device?

In Xamarin.Forms if you want to open the device's default browser by tapping a Label with a link, it's simple as this:
private void WebUrl_TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
var label = sender as Label;
string url = "http://" + label.Text;
Device.OpenUri(new Uri(url));
}
Is there a similarly simple way to open the device's default email client with an open NewMessage with email address?
private void EmailClient_TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
var label = sender as Label;
// what goes here?
}
Thank you.
Try with:
var address = "your.address#gmail.com";
Device.OpenUri(new Uri($"mailto:{address}"));
Hope this helps.-
I actually use a Dependency Service so that I have more control over what I can send to mail client.
First I created an interface to be used by the dependency service called IEmailService.
public interface IEmailService
{
void CreateEmail(List<string> emailAddresses, List<string> ccs, string subject, string body, string htmlBody);
}
My Dependency Service for Android looks like this:
[assembly: Xamarin.Forms.Dependency(typeof(EmailService))]
namespace Droid.Services
{
public class EmailService : IEmailService
{
public void CreateEmail(List<string> emailAddresses, List<string> ccs, string subject, string body, string htmlBody)
{
var email = new Intent(Android.Content.Intent.ActionSend);
if (emailAddresses?.Count > 0)
{
email.PutExtra(Android.Content.Intent.ExtraEmail, emailAddresses.ToArray());
}
if (ccs?.Count > 0)
{
email.PutExtra(Android.Content.Intent.ExtraCc, ccs.ToArray());
}
email.PutExtra (Android.Content.Intent.ExtraSubject, subject);
email.PutExtra (Android.Content.Intent.ExtraText, body);
email.PutExtra (Android.Content.Intent.ExtraHtmlText, htmlBody);
email.SetType ("message/rfc822");
MainActivity.SharedInstance.StartActivity(email);
}
}
}
For iOS:
[assembly: Xamarin.Forms.Dependency(typeof(EmailService))]
namespace iOS.Services
{
public class EmailService : NSObject, IEmailService, IMFMailComposeViewControllerDelegate
{
public void CreateEmail(List<string> emailAddresses, List<string> ccs, string subject, string body, string htmlBody)
{
var vc = new MFMailComposeViewController();
vc.MailComposeDelegate = this;
if(emailAddresses?.Count > 0)
{
vc.SetToRecipients(emailAddresses.ToArray());
}
if(ccs?.Count > 0)
{
vc.SetCcRecipients(ccs.ToArray());
}
vc.SetSubject(subject);
vc.SetMessageBody(htmlBody, true);
vc.Finished += (sender, e) =>
{
vc.DismissModalViewController(true);
};
UIApplication.SharedApplication.Windows[0].
RootViewController.PresentViewController(vc, true, null);
}
}
}
Then I can just call this in my code:
DependencyService.Get<IEmailService>().CreateEmail(recipients, ccs, subject, body, bodyHtml);
This will open the mail client on each platform with the to, subject and body fields optionally poplulated.
I hope that helps.
You can use Launcher.OpenAsync(uri) exists in Xamarin.Essentials. OpenUri is obsolete as of version 4.3.0. uri = $"mailto:{address}?subject={emailSubject}&body={body content}";

kryonet client, send message to server without open a new connection

I'm saying i'm not a programmer but a guy who has been learning to program with java for a while. I hope to find the solution to my problem here. I'm trying to program my home automation system and remote control and to do this, I chose to use Kryonet. My problem is that every time I send the data to the server, the client opens a new connection. It's been 3 weeks since googlo and I try to figure out how to do it but with no results.
Every help is seriously appreciated. This is my code. Thank you.
This code work in my home network.
Sorry for my english...
public class MainActivity extends AppCompatActivity {
Button button;
String IP = "";
EditText editText;
TextView textView;
EditText editText3;
public static String msg_response;
public static String msg_request;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Handler handler = new MyHandler();
button = (Button) findViewById(R.id.button);
editText = (EditText) findViewById(R.id.editText);
editText3 = (EditText) findViewById(R.id.editText3);
textView = (TextView) findViewById(R.id.textView);
int MY_PERMISSIONS_REQUEST_INTERNET = 1;
int MY_PERMISSIONS_REQUEST_ACCESS_NETWORK_STATE = 1;
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.INTERNET},
MY_PERMISSIONS_REQUEST_INTERNET);
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_NETWORK_STATE},
MY_PERMISSIONS_REQUEST_ACCESS_NETWORK_STATE);
int MY_PERMISSIONS_REQUEST_ACCESS_WIFY_STATE = 1;
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_WIFI_STATE},
MY_PERMISSIONS_REQUEST_ACCESS_WIFY_STATE);
textView.setText(msg_response);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
msg_request = valueOf(editText3.getText().toString());
} catch (Exception e) {
e.printStackTrace();
}
MyThread myThread = new MyThread(handler);
myThread.start();
}
});
}
private class MyHandler extends Handler {
#Override
public void handleMessage(Message msg) {
Bundle bundle = msg.getData();
if (bundle.containsKey("msg da server")) {
String msgin = bundle.getString("msg da server");
textView.setText(msgin);
}
}
}
class MyThread extends Thread {
private Handler handler;
public MyThread(Handler handler) {
this.handler = handler;
}
public void run() {
System.out.println("MyThread running");
Client client = new Client();
client.start();
Kryo kryoClient = client.getKryo();
kryoClient.register(SampleRequest.class);
kryoClient.register(SampleResponse.class);
try {
client.connect(5000, "192.168.0.101", 54555, 54666);
} catch (IOException e) {
e.printStackTrace();
}
client.addListener(new Listener() {
public void received(Connection connection, Object object) {
if (object instanceof SampleResponse) {
SampleResponse response = (SampleResponse) object;
System.out.println(response.text);
msg_response = response.text.toString();
invia_activity(msg_response);
}
}
});
SampleRequest request = new SampleRequest();
request.text = msg_request;
client.sendTCP(request);
}
private void invia_activity(String invia) {
Message msg = handler.obtainMessage();
Bundle b = new Bundle();
b.putString("msg da server", "" + invia);
msg.setData(b);
handler.sendMessage(msg);
}
}
}
I dont have an direct solution, but i have an tutorial for it. I used the same one. So there the connections keeps open, and you can send as many packets as you need. Its without audio, but the code works well. After that you can experiment with the code. It works fine for me. This is the tutorial
I hope i can help you with this.
EDIT:
Maybe you can make an
public static Connection conn;
and you could use that object again and again as your connection to the server.

How to reuse a SSH (Jsch) session created in an AsyncTask in another class

I'm a Android & Java newbie and here is my situation:
I'm trying to create an app which connects to a Beaglebone Black using a ssh connection and then controls some peripherals connected to the BBB by issuing commands coming from an Android device.
I'm opening (successfully) an ssh session in an AsyncTask while the user sees an splash screen, if the connection was successful the user will get a confirmation and then will be able to send predefined commands by clicking some available buttons.
What I want to do next is left the session opened and then create a new channel (exec or shell ) each time I wish to issue a command and wait for the response from the BBB, but I donĀ“t know how to reuse such ssh session outside the AsynkTask.
is that even possible?
I'm using Android Studio 0.8.2 and Jsch 0.1.51, my code is as follows:
public class SplashScreen extends ActionBarActivity {
public static final int segundos =10;
public static final int milisegundos =segundos*1000;
public static final int delay=2;
private ProgressBar pbprogreso;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash_screen);
pbprogreso= (ProgressBar)findViewById(R.id.pbprogreso);
pbprogreso.setMax(maximo_progreso());
empezaranimacion();
}
public void empezaranimacion()
{
sshConnect task = new sshConnect();
task.execute(new String[] {"http:"});
new CountDownTimer(milisegundos,1000)
{
#Override
public void onTick(long milisUntilFinished){
pbprogreso.setProgress(establecer_progreso(milisUntilFinished));
}
#Override
public void onFinish(){
finish();
}
}.start();
}
public int establecer_progreso (long miliseconds)
{
return (int)((milisegundos-miliseconds)/1000);
}
public int maximo_progreso () {
return segundos-delay;
}
public class sshConnect extends AsyncTask <String, Void, String>{
ByteArrayOutputStream Baos=new ByteArrayOutputStream();
ByteArrayInputStream Bais = new ByteArrayInputStream(new byte[1000]);
#Override
protected String doInBackground(String... data) {
String host = "xxxxxxx";
String user = "root";
String pwd = "";
int port = 22;
JSch jsch = new JSch();
try {
Session session = jsch.getSession(user, host, port);
session.setPassword(pwd);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
ChannelExec channel = (ChannelExec)session.openChannel("exec");
channel.setOutputStream(Baos);
channel.setInputStream(Bais);
//Run Command
channel.setCommand("python ~/BBB_test/testconnect.py");
channel.connect();
try{Thread.sleep(3500);}catch (Exception ee){}
channel.disconnect();
//session.disconnect();
}catch (Exception e){
System.out.println(e.getMessage());
}
return Baos.toString();
}
#Override
protected void onPostExecute(String result) {
if (result.equals("Connected to BBB Baby!!\n")) {
Intent nuevofrom = new Intent(SplashScreen.this, Principal.class);
startActivity(nuevofrom);
finish();
} else {
Intent newfrom = new Intent(SplashScreen.this, ConnecError.class);
startActivity(newfrom);
finish();
}
}
}
//Here is where I want to reuse the opened session and create a new channel
public class sendCommand extends AsyncTask <String, Void, String >{
ByteArrayOutputStream Baosc=new ByteArrayOutputStream();
ByteArrayInputStream Baisc = new ByteArrayInputStream(new byte[1000])
protected String doInBackground (String... command){
try {
ChannelExec channel2 = (ChannelExec)session.openChannel("exec");
channel2.setOutputStream(Baosc);
channel2.setInputStream(Baisc);
//Run Command
channel2.setCommand("python ~/BBB_test/testgpio.py");
channel2.connect();
try{Thread.sleep(3500);}catch (Exception ee){}
channel2.disconnect();
}catch (Exception e) {
System.out.println(e.getMessage());
}
return Baosc.toString();
}
protected void onPostExecute(Long result) {
TextView txt = (TextView) findViewById(R.id.infotext);
txt.setText(result);
}
}
If something else is needed let me know! (it is the first time I ask something in a forum)
Thanks a lot for your time and support!
I managed to get what I wanted by using the recommendation from DamienKnight of creating the session outside the Asynktask class. I create a public classwith three methods to create, return and disconnect the session:
public static class cSession {
String host = "xxx.xxx.xxx.xxx";
String user = "root";
String pwd = "";
int port = 22;
JSch jsch = new JSch();
public Session Met1 (){
try {
session = jsch.getSession(user, host, port);
session.setPassword(pwd);
session.setConfig("StrictHostKeyChecking", "no");
} catch (Exception e2){
System.out.println(e2.getMessage());
}return session;
}
public Session damesession (){
return session;
}
public void close_ses(){
session.disconnect();
}
}
By doing this so, the creation of channels is flexible and I can use the methods from Jsch too.
public class sshConnect extends AsyncTask <String, Void, String>{
ByteArrayOutputStream Baos=new ByteArrayOutputStream();
ByteArrayInputStream Bais = new ByteArrayInputStream(new byte[1000]);
#Override
protected String doInBackground(String... data) {
cSession jschses = new cSession();
Session ses =null;
ses = jschses.Met1();
try {
ses.connect();
ChannelExec channel = (ChannelExec)ses.openChannel("exec");
channel.setOutputStream(Baos);
channel.setInputStream(Bais);
//Run Command
channel.setCommand("python ~/BBB_test/testconnect.py");
channel.connect();
try{Thread.sleep(3500);}catch (Exception ee){}
channel.disconnect();
//session.disconnect();
}catch (Exception e){
System.out.println(e.getMessage());
}
return Baos.toString();
}
Thanks #Damienknight!
Regards
If you are wanting to reuse the session, you dont need to reconect the channel each time. Connect it once as a shell, plugging an input and output stream into it. Use the streams to pass commands and capture output.
See the JSCH example on the JCraft website.
Channel channel=session.openChannel("shell");
channel.setInputStream(System.in);
channel.setOutputStream(System.out);
channel.connect();

How to use TcpClient in Windows 8 Consumer Preview

I'm writing a Metro app in Windows 8 Consumer Preview.
However, I'm unable to use the TcpClient in .NET 4.5, there doesn't seem to be a place to add the assembly reference.
http://msdn.microsoft.com/en-us/library/1612451t(v=vs.110).aspx
TcpClient is not supported on the metro side. You can use StreamSocket class instead. Here is a sample on how to use it to create a TCP Socket, make a connection, send and receive data. The samples are in JS and C++ but the same class will work for C#.
Ultimately, we should probably use the new Metro NET stuff. However, if porting a lot of code and depending on how much of the TcpClient members you are using, it might not be so bad to just create a limited implementation around the Metro objects. I wanted to do a quick port of a bunch of code over to Metro in a hurry (just to try out some stuff), so I slapped together something that seemed to work, but most certainly not ideal. (You end up doing some sync-ing of async methods which is commonly frowned upon.)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Networking;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;
namespace MetroNetHelper
{
public class IPAddress // assumes IPv4 currently
{
public string IP_String;
public IPAddress() { }
public IPAddress(string IP) { IP_String = IP; }
public static IPAddress Broadcast { get { return new IPAddress("255.255.255.255"); } }
public static IPAddress Parse(string IP) { return new IPAddress(IP); }
public static bool TryParse(string V, out IPAddress Addr)
{
try
{
Addr = IPAddress.Parse(V);
return true;
}
catch { Addr = null; return false; }
}
public HostName GetHostNameObject() { return new HostName(IP_String); }
public byte[] GetAddressBytes()
{
string[] Fields = IP_String.Split('.');
byte[] temp = new byte[4];
for (int i = 0; i < temp.Length; i++) temp[i] = byte.Parse(Fields[i]);
return temp;
}
}
public class IPEndPoint
{
public IPAddress Address;
public int Port;
public IPEndPoint() { }
public IPEndPoint(IPAddress Addr, int PortNum)
{
Address = Addr; Port = PortNum;
}
}
public class NetworkStream
{
private DataReader Reader;
private DataWriter Writer;
public void Set(StreamSocket HostClient)
{
Reader = new DataReader(HostClient.InputStream);
Reader.InputStreamOptions = InputStreamOptions.Partial;
Writer = new DataWriter(HostClient.OutputStream);
}
public int Write(byte[] Buffer, int Offset, int Len)
{
if (Offset != 0 || Len != Buffer.Length) throw new ArgumentException("Can only write whole byte array");
Writer.WriteBytes(Buffer);
Task Tk = Writer.StoreAsync().AsTask();
Tk.Wait();
return Buffer.Length;
}
public int Read(byte[] Buffer, int Offset, int Len)
{
if (Offset != 0 || Len != Buffer.Length) throw new ArgumentException("Can only read whole byte array");
Task<uint> Tk = Reader.LoadAsync((uint)Len).AsTask<uint>();
Tk.Wait();
uint Count = Tk.Result;
for (int i=0;i<Count;i++)
{
Buffer[i] = Reader.ReadByte();
}
return (int)Count;
}
public bool DataAvailable
{
get
{
return true; // Read() will still work if no data; could we do read ahead 1 byte to determine?
}
}
}
public class TcpClient
{
private StreamSocket sock;
public void Connect(IPEndPoint EndPt)
{
try
{
sock = new StreamSocket();
HostName Hst = EndPt.Address.GetHostNameObject();
Task Tsk = sock.ConnectAsync(Hst, EndPt.Port.ToString()).AsTask();
Tsk.Wait();
}
catch (Exception ex) { MetroHelpers.UnpeelAggregate(ex); }
}
public void Close()
{
sock.Dispose();
sock = null;
}
public NetworkStream GetStream()
{
var N = new NetworkStream();
N.Set(sock);
return N;
}
}
public static class MetroHelpers
{
public static void UnpeelAggregate(Exception Ex)
{
AggregateException Ag_Ex = Ex as AggregateException;
if (Ag_Ex == null) throw Ex;
if (Ag_Ex.InnerExceptions.Count > 0)
{
if (Ag_Ex.InnerExceptions.Count == 1) throw Ag_Ex.InnerExceptions[0];
StringBuilder Str = new StringBuilder();
foreach (Exception X in Ag_Ex.InnerExceptions)
{
Str.AppendLine(X.Message);
}
throw new Exception(Str.ToString(), Ag_Ex);
}
else throw Ag_Ex;
}
}
} // END NAMESPACE
This was just something I did quick and dirty in a morning. If it helps anyone with ideas, great. Again, we are most likely better off developing the way Microsoft wants us for Metro apps. It just gets frustrating when they keep changing the ruddy framework. (If Xamarin can keep consistent frameworks on iOS/Android/etc, why can't MS on their own OS's!)

Resources