How to connect Android on RabbitMQ? - android

I'd like to use RabbitMQ client from an android App.
From the server side, i use SpringBoot with spring AMQP. RabbitMQ (rabbitmq_server-3.4.3) is installed correctly and an integration test valid the server behaviour.
The difficult part is when i try to create a connection from RabbitMQ connectionFactory inside my android project.
I get this exception :
failed to connect to localhost/127.0.0.1 (port 5672):
connect failed: ECONNREFUSED (Connection refused)
In android manifest, Internet permission is set :
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
Here is my code :
public class LoadingTask extends AsyncTask<String, Integer, Integer> {
private static String replyQueue = "REPLY_QUEUE";
public interface LoadingTaskListener {
void onResourceLoaded();
}
private final ProgressBar progressBar;
private final LoadingTaskListener loadingTaskListener;
private ConnectionFactory connectionFactory;
public LoadingTask(ProgressBar progressBar, LoadingTaskListener loadingTaskListener) {
this.progressBar = progressBar;
this.loadingTaskListener = loadingTaskListener;
this.connectionFactory = new ConnectionFactory();
connectionFactory.setAutomaticRecoveryEnabled(true);
}
#Override
protected Integer doInBackground(String... params) {
try {
/*init rabbitMQ Context*/
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
channel.basicQos(1);
channel.queueDeclare(DATA_QUEUE.getName(), false, false, false, null);
AMQP.Queue.DeclareOk q = channel.queueDeclare();
channel.queueBind(q.getQueue(), "amq.fanout", "chat");
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(replyQueue, true, consumer);
/* initiate RPC */
String corrId = java.util.UUID.randomUUID().toString();
AMQP.BasicProperties props = new AMQP.BasicProperties.Builder()
.correlationId(corrId)
.replyTo(replyQueue)
.build();
AmqpRequest request = new AmqpRequest(LIST_IMAGE);
Gson gson = new Gson();
String jsonRequest = gson.toJson(request);
channel.basicPublish(MAIN_EXCHANGE.getName(), DATA_QUEUE.getRoutingKey(), props, jsonRequest.getBytes());
String response;
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
if (delivery.getProperties().getCorrelationId().equals(corrId)) {
response = new String(delivery.getBody());
break;
}
}
System.out.println(response);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
// Dummy Data until i can't connect to rabbitMQ
return 1234;
}
}
Is it really possible to connect Android on RabbitMQ, or should i use a kind of http bridge ?
Could anyone provide me an exemple for both http bridge or RabbitMQ connection.
Thank you

Related

Not able to Start appium service from java code

Not able to start appium from code made a function and called before desired capability, post desired capability.
Getting error while running below code: C:\Users\Ritesh Mittal\AppData\Roaming\npm\node_modules\appium\lib\appium.js:1
import _ from 'lodash';
^^^^^^
SyntaxError: Cannot use import statement outside a module
at Object.compileFunction (node:vm:352:18)
//Option 1
public static void runAppiumService(String portNumber) {
//Build parameters for appium server:
AppiumServiceBuilder appiumServiceBuilder = new AppiumServiceBuilder();
appiumServiceBuilder.usingPort(Integer.parseInt(portNumber))
.withIPAddress("127.0.0.1")
.withAppiumJS(new File("C:\\Users\\Ritesh Mittal\\AppData\\Roaming\\npm\\node_modules\\appium\\lib\\appium.js"))
.withArgument(GeneralServerFlag.SESSION_OVERRIDE)
.withLogFile(new File(System.getProperty("user.dir") + "/target/resources/appium_server_logs" + Thread.currentThread().getId()));
AppiumDriverLocalService service = AppiumDriverLocalService.buildService(appiumServiceBuilder);
service.start();
}
//Option 2
DesiredCapabilities dc = new DesiredCapabilities();
dc.setCapability(MobileCapabilityType.DEVICE_NAME, deviceName);
//dc.setCapability(MobileCapabilityType.PLATFORM_VERSION,platformVersion);
dc.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
dc.setCapability(MobileCapabilityType.APP, System.getProperty("user.dir")+"/src/test/resources/apps/CRMNextNative 6.29.0-release_screenshot_enabled.apk");
dc.setCapability("automationName","UiAutomator2");
dc.setCapability("appPackage", "com.crmnextmobile.crmnextofflineplay");
dc.setCapability("appActivity", "com.crmnextmobile.crmnextofflineplay.qr.QrScannerActivity");
dc.setCapability("enforceAppInsall", true);
URL url = new URL("http://127.0.0.1:"+portNumber+"/wd/hub");
AppiumDriverLocalService service;
service = AppiumDriverLocalService.buildService(new AppiumServiceBuilder()
.usingPort(Integer.parseInt(portNumber))
.usingDriverExecutable(new File("C:\\Program Files\\nodejs\\node.exe"))
.withAppiumJS(new File("C:\\Users\\Ritesh Mittal\\AppData\\Roaming\\npm\\node_modules\\appium\\lib\\appium.js"))
.withArgument(GeneralServerFlag.RELAXED_SECURITY)
.withArgument(GeneralServerFlag.SESSION_OVERRIDE)
.withArgument(GeneralServerFlag.LOG_LEVEL, "error")
.withCapabilities(dc));
service.start();
logger.info("Appium started ......");
Thread.sleep(10000);
driver = new AppiumDriver(url,dc);
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
System.out.println("CRMNext automation start..");
please try this code:
public void startServer() throws IOException, InterruptedException {
Properties prop = new Properties();
InputStream input = null;
input = getClass().getClassLoader().getResourceAsStream("config.properties");
try {
prop.load(input);
} catch (IOException e) {
e.printStackTrace();
}
Map<String, String> env = new HashMap<>(System.getenv());
env.put("PATH", prop.getProperty("Local_Path") + env.get("PATH"));
env.put("ANDROID_HOME", prop.getProperty("Android_Home"));
int port = Integer.parseInt(prop.getProperty("port"));
System.out.println("port--> "+port);
service = AppiumDriverLocalService.buildService(
new AppiumServiceBuilder().usingDriverExecutable(new File(prop.getProperty("DriverExecutable")))
.withAppiumJS(new File(prop.getProperty("AppiumJS"))).withIPAddress(prop.getProperty("IP"))
.usingPort(port).withLogFile(new File("AppiumLog.text")).withEnvironment(env));
service.start();
Thread.sleep(20000);
}
I solved it. I was doing two mistakes
Appium Path was not correct.
Incorrect path was
builder.withAppiumJS(new File("C:\Users\Ritesh Mittal\AppData\Roaming\npm\node_modules\appium\lib\appium.js"));
corrected:
builder.withAppiumJS(new File("C:\Users\Ritesh Mittal\AppData\Roaming\npm\node_modules\appium"));
added arguments
builder.withArgument(() -> "--base-path", "/wd/");

PJSUA2 Android - Incoming calls drop after 32 seconds

I'm building a PJSUA2 (PJSIP 2.8) Android app and I have some issues: i.e. only on incoming call, call state remains in "PJSIP_INV_STATE_CONNECTING" and after 32 seconds the call drops.
I'm looking for the cause of the issue since several days, I googled a lot and all what I found is: in most situations this issue is related to NAT management or network issues related to NAT. In a few words: in most cases the called party does not receive the ACK after answering the call.
Finally I was able to log all SIP messages between my app and the SIP server and found that my app receives the ACK from the server, so I suppose it's not a network related issue.
I compiled PJSIP 2.8 with OpenSSL and SRTP support, but without video support (I don't need it at least at the moment). If it makes any difference, the app has a target version 28 and minimum SDK version 19.
I tried several apps on the market and they work fine enough with and without SRTP and with all signaling transports (UDP, TCP, TLS), WebRTC works fine too (tested with SipML5), so I would exclude a server misconfiguration. My app does the same (except SRTP with which I have some issues at the moment).
I tried with a SIP provider too (MessageNet) using UDP and the behaviour is always the same. I tried to use compact SIP messages and it behaves the same, with and without uri parameters, with and without STUN and or ICE and nothing changes. Mobile network and WiFi networks give the same results.
I tried to debug inside PJSIP library too, but without any success, then I tried to follow the code, to understand what I was doing wrong, but it doesn't seem to me there is something evidently wrong.
The following is the code (last version) which initializes PJSIP:
public class SipService extends Service {
private Looper serviceLooper;
private ServiceHandler serviceHandler;
private final Messenger mMessenger = new Messenger(new IncomingHandler());
private LocalBroadcastManager localBroadcast;
private LifecycleBroadcastReceiver lifecycleBroadcastReceiver;
private boolean lastCheckConnected;
private Endpoint endpoint;
private LogWriter logWriter;
private EpConfig epConfig;
private final List<ManagedSipAccount> accounts = new ArrayList<>();
private final Map<String, Messenger> eventRegistrations = new HashMap<>();
#TargetApi(Build.VERSION_CODES.N)
#Override
public void onCreate() {
super.onCreate();
String userAgent = "MyApp";
try {
PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
String appLabel = (pInfo.applicationInfo.labelRes == 0 ? pInfo.applicationInfo.nonLocalizedLabel.toString() : getString(pInfo.applicationInfo.labelRes));
userAgent = appLabel + "/" + pInfo.versionName;
} catch (PackageManager.NameNotFoundException e) {
Log.e("SipService", "Unable to get app version", e);
}
try {
endpoint = new MyAppEndpoint();
endpoint.libCreate();
epConfig = new EpConfig();
// Logging
logWriter = new PJSIPToAndroidLogWriter();
epConfig.getLogConfig().setWriter(logWriter);
epConfig.getLogConfig().setLevel(5);
// UA
epConfig.getUaConfig().setMaxCalls(4);
epConfig.getUaConfig().setUserAgent(userAgent);
// STUN
StringVector stunServer = new StringVector();
stunServer.add("stun.pjsip.org");
epConfig.getUaConfig().setStunServer(stunServer);
// General Media
epConfig.getMedConfig().setSndClockRate(16000);
endpoint.libInit(epConfig);
// UDP transport
TransportConfig udpCfg = new TransportConfig();
udpCfg.setQosType(pj_qos_type.PJ_QOS_TYPE_VOICE);
endpoint.transportCreate(pjsip_transport_type_e.PJSIP_TRANSPORT_UDP, udpCfg);
// TCP transport
TransportConfig tcpCfg = new TransportConfig();
//tcpCfg.setPort(5060);
endpoint.transportCreate(pjsip_transport_type_e.PJSIP_TRANSPORT_TCP, tcpCfg);
// TLS transport
TransportConfig tlsCfg = new TransportConfig();
endpoint.transportCreate(pjsip_transport_type_e.PJSIP_TRANSPORT_TLS, tlsCfg);
endpoint.libStart();
} catch (Exception e) {
throw new RuntimeException("Unable to initialize and start PJSIP", e);
}
ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
lastCheckConnected = activeNetwork != null && activeNetwork.isConnected();
updateForegroundNotification();
startForeground(MyAppConstants.N_FOREGROUND_NOTIFICATION_ID, buildForegroundNotification());
localBroadcast = LocalBroadcastManager.getInstance(this);
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
serviceLooper = thread.getLooper();
serviceHandler = new ServiceHandler(serviceLooper);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
// Register LifeCycleBroadcastReceiver to receive network change notification
// It seems it's mandatory to do it programmatically since Android N (24)
lifecycleBroadcastReceiver = new LifecycleBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
registerReceiver(lifecycleBroadcastReceiver, intentFilter);
}
// Initialization
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
if (prefs != null) {
try {
CodecInfoVector codecs = endpoint.codecEnum();
SharedPreferences.Editor editor = prefs.edit();
for (int i = 0; i < codecs.size(); i++) {
CodecInfo codec = codecs.get(i);
int priority = prefs.getInt("codecs.audio{" + codec.getCodecId() + "}", 0);
try {
endpoint.codecSetPriority(codec.getCodecId(), (short) priority);
codec.setPriority((short) priority);
} catch (Exception e) {
Log.e("SipService", "Unexpected error setting codec priority for codec " + codec.getCodecId(), e);
}
}
} catch (Exception e) {
Log.e("SipService", "Unexpected error loading codecs priorities", e);
}
}
}
#Override
public void onDestroy() {
for (Account acc : accounts) {
acc.delete();
}
accounts.clear();
try {
endpoint.libDestroy();
} catch (Exception e) {
e.printStackTrace();
}
endpoint.delete();
endpoint = null;
epConfig = null;
if (lifecycleBroadcastReceiver != null) {
unregisterReceiver(lifecycleBroadcastReceiver);
}
super.onDestroy();
}
.......
}
And the following is my Account class with creation and registration code:
public class ManagedSipAccount extends Account {
public final String TAG;
private final VoipAccount account;
private final PhoneAccountHandle handle;
private final SipService service;
private final AccountStatus status;
private final Map<Integer, VoipCall> calls = new HashMap<>();
private final Map<String, VoipBuddy> buddies = new HashMap<>();
private AccountConfig acfg;
private List<SrtpCrypto> srtpCryptos = new ArrayList<>();
private AuthCredInfo authCredInfo;
public ManagedSipAccount(SipService service, VoipAccount account, PhoneAccountHandle handle) {
super();
TAG = "ManagedSipAccount/" + account.getId();
this.service = service;
this.account = account;
this.handle = handle;
this.status = new AccountStatus(account.getUserName() + "#" + account.getHost());
acfg = new AccountConfig();
}
public void register(Map<String, String> contactParameters) throws Exception {
StringBuilder contactBuilder = new StringBuilder();
for (Map.Entry<String, String> entry : contactParameters.entrySet()) {
contactBuilder.append(';');
contactBuilder.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
contactBuilder.append("=\"");
contactBuilder.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
contactBuilder.append("\"");
}
StringBuilder logBuilder = new StringBuilder();
logBuilder.append("Registering: ");
logBuilder.append(account.getProtocol().name());
/*logBuilder.append('(');
logBuilder.append(service.getTransport(account.getProtocol()));
logBuilder.append(')');*/
if (account.isEncryptionSRTP()) {
logBuilder.append(" SRTP");
}
if (account.isIce()) {
logBuilder.append(" ICE");
}
Log.d(TAG, logBuilder.toString());
String idUri = "sip:" + account.getUserName();
if (!"*".equals(account.getRealm())) {
idUri += "#" + account.getRealm();
}
else {
idUri += "#127.0.0.1" /*+ account.getHost()*/;
}
acfg.setIdUri(idUri);
acfg.getRegConfig().setRegistrarUri("sip:" + account.getHost() + ":" + account.getPort() + ";transport=" + account.getProtocol().name().toLowerCase());
acfg.getRegConfig().setRetryIntervalSec(account.getRetryInterval());
acfg.getRegConfig().setRegisterOnAdd(false);
acfg.getSipConfig().setContactUriParams(contactBuilder.toString());
// NAT management
acfg.getNatConfig().setSipStunUse(pjsua_stun_use.PJSUA_STUN_USE_DEFAULT);
if (account.isIce()) {
acfg.getNatConfig().setIceEnabled(true);
acfg.getNatConfig().setIceAlwaysUpdate(true);
acfg.getNatConfig().setIceAggressiveNomination(true);
}
else {
acfg.getNatConfig().setSdpNatRewriteUse(1);
}
acfg.getMediaConfig().getTransportConfig().setQosType(pj_qos_type.PJ_QOS_TYPE_VOICE);
if (account.isEncryptionSRTP()) {
acfg.getMediaConfig().setSrtpUse(pjmedia_srtp_use.PJMEDIA_SRTP_MANDATORY);
acfg.getMediaConfig().setSrtpSecureSignaling(0);
//acfg.getMediaConfig().getSrtpOpt().setKeyings(new IntVector(2));
acfg.getMediaConfig().getSrtpOpt().getKeyings().clear();
acfg.getMediaConfig().getSrtpOpt().getKeyings().add(pjmedia_srtp_keying_method.PJMEDIA_SRTP_KEYING_SDES.swigValue());
acfg.getMediaConfig().getSrtpOpt().getKeyings().add(pjmedia_srtp_keying_method.PJMEDIA_SRTP_KEYING_DTLS_SRTP.swigValue());
acfg.getMediaConfig().getSrtpOpt().getCryptos().clear();
StringVector cryptos = Endpoint.instance().srtpCryptoEnum();
for (int i = 0; i < cryptos.size(); i++) {
SrtpCrypto crypto = new SrtpCrypto();
crypto.setName(cryptos.get(i));
crypto.setFlags(0);
srtpCryptos.add(crypto);
acfg.getMediaConfig().getSrtpOpt().getCryptos().add(crypto);
}
}
else {
acfg.getMediaConfig().setSrtpUse(pjmedia_srtp_use.PJMEDIA_SRTP_DISABLED);
acfg.getMediaConfig().setSrtpSecureSignaling(0);
}
authCredInfo = new AuthCredInfo("digest",
account.getRealm(),
account.getAuthenticationId() != null && account.getAuthenticationId().trim().length() > 0 ? account.getAuthenticationId() : account.getUserName(),
0,
account.getPassword());
acfg.getSipConfig().getAuthCreds().add( authCredInfo );
acfg.getIpChangeConfig().setHangupCalls(false);
acfg.getIpChangeConfig().setShutdownTp(true);
create(acfg);
ConnectivityManager cm = (ConnectivityManager)service.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null && activeNetwork.isConnected();
if (isConnected) {
setRegistration(true);
}
}
#Override
public void onRegStarted(OnRegStartedParam prm) {
super.onRegStarted(prm);
Log.d(TAG, "Status: Registering...");
status.setStatus(AccountStatus.Status.REGISTERING);
service.updateStatus(this);
}
#Override
public void onRegState(OnRegStateParam prm) {
super.onRegState(prm);
try {
Log.d(TAG, "Registration state: " + prm.getCode().swigValue() + " " + prm.getReason());
AccountInfo ai = getInfo();
status.setStatus(ai.getRegIsActive() ? AccountStatus.Status.REGISTERED : AccountStatus.Status.UNREGISTERED);
Log.d(TAG, "Status: " + status.getStatus().name() + " " + super.getInfo().getUri());
service.updateStatus(this);
} catch (Exception e) {
e.printStackTrace();
}
}
.....
}
Finally, how I answer the code at the moment in a class which extends the PJSIP's Call class:
#Override
public void answerCall() {
Log.d(TAG, "Answering call...");
CallOpParam prm = new CallOpParam(true);
prm.setStatusCode(pjsip_status_code.PJSIP_SC_OK);
prm.getOpt().setAudioCount(1);
prm.getOpt().setVideoCount(0);
try {
this.answer(prm);
} catch (Exception e) {
e.printStackTrace();
}
}
I also tried with new CallOpParam(); with just the status code and nothing else, but nothing changes.
One note: I created the IdUri as sip:username#127.0.0.1 because without the host the resulting contact was and I thought that the missing user part may be the cause of the issue or part of it.
The following is the trace of the app <-> my Asterisk server communication during call (linked because of content length exceed).
https://gist.github.com/ivano85/a212ddc9a808f3cd991234725c2bdb45
The ServerIp is an internet public IP, while the MyIp[5.XXX.XXX.XXX] is my phone's public IP.
As you can see from the log, my app sends a 100 Trying, then a 180 Ringing when the phone rings, then the user answers and the app sends a 200 OK. The server replies with a ACK message (I would say it's not a NAT issue, because PJSIP receives the ACK). I see the same from Asterisk.
After this I would expect the call goes from PJSIP_INV_STATE_CONNECTING to PJSIP_INV_STATE_CONFIRMED, but it does not happen, so PJSIP continues to send a 200 OK and receive the ACK every about 2 seconds, until the call times out after 32 seconds and PJSIP disconnects the call (sending a BYE).
I'm starting to think that PJSIP just ignores ACK messages and just has a wrong behaviour. Please help me to understand what is happening here. I would appreciate it so much!
Obviously let me know if you think that more details are needed.

Error while processing request on Azure

I have an app connected with Azure backend. I created a login and some api calls 2 months ago. They worked fine until a few days ago and then it starts to fail "sometimes".
The login log onFailure says: Error while authenticating user
The callback log onFailure says: Error while processing request
And the cause of both says : stream was reset: PROTOCOL_ERROR
This post is to similar to this but didn't work.
Some code here:
LoginFragment.java
private void login(String email, String password){
loginProgressBar.setVisibility(View.VISIBLE);
try {
JsonObject params = new JsonObject();
params.addProperty("Username", email);
params.addProperty("Password", password);
ListenableFuture<MobileServiceUser> listenable = Client.logIn(getContext(), params);
Futures.addCallback(listenable, new FutureCallback<MobileServiceUser>() {
#Override
public void onSuccess(MobileServiceUser mobileServiceUser) {
loginProgressBar.setVisibility(View.GONE);
SharedPreferences settings = getActivity().getSharedPreferences(Client.MS_USER,0);
SharedPreferences.Editor editor = settings.edit();
Client.clientId = mobileServiceUser.getUserId();
Client.token = mobileServiceUser.getAuthenticationToken();
editor.putString(Client.MS_USER_ID, Client.clientId);
editor.putString(Client.MS_AUTH_TOKEN, Client.token);
editor.apply();
Client.getInstance(getContext()).setCurrentUser(mobileServiceUser);
Intent i = new Intent(getContext(), MainActivity.class);
startActivity(i);
}
#Override
public void onFailure(Throwable t) {
loginProgressBar.setVisibility(View.GONE);
Throwable t2 = t.getCause();
Throwable t3 = t2.getCause();
Log.e("LoginFail", t.getMessage());
Log.e("LoginFail", t2.getMessage());
if(t3 != null){
Log.e("LoginFail", t3.getMessage());
}
Toast.makeText(getContext(), getResources().getString(R.string.bad_login), Toast.LENGTH_LONG).show();
}
}, MoreExecutors.directExecutor());
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
Client.java
public class Client {
public static final String MS_USER = "MS_USER";
public static final String MS_USER_ID = "MS_USER_ID";
public static final String MS_AUTH_TOKEN = "MS_AUTH_TOKEN";
public static String clientId;
public static String token;
private static MobileServiceClient instance = null;
public static MobileServiceClient getInstance(Context context) {
if (instance ==null){
try {
instance = new MobileServiceClient(Env.AZURE_URL, context);
instance.setAndroidHttpClientFactory(() -> {
OkHttpClient client = new OkHttpClient();
client.setReadTimeout(20, TimeUnit.SECONDS);
client.setWriteTimeout(20, TimeUnit.SECONDS);
return client;
});
} catch (MalformedURLException e) {
e.printStackTrace();
}
} else{
instance.setContext(context);
}
return instance;
}
public static ListenableFuture<MobileServiceUser> logIn(Context context, JsonObject parameters) throws MalformedURLException {
String deviceID = "gcm:" + Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
parameters.addProperty("device_id", deviceID);
parameters.addProperty("device_dateTime", Env.DATE_FORMAT.format(new Date()));
parameters.addProperty("device_timeZone", API.getTimezone());
parameters.addProperty("device_language", Env.LANGUAGE);
parameters.addProperty("app", Env.APP_NAME);
return getInstance(context).login("auth", parameters);
}
public static ListenableFuture<JsonElement> callApi(Context context, String apiName, JsonObject parameters, String httpMethod){
if(httpMethod.equals("POST")){
String deviceID = "gcm:" + Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
parameters.addProperty("user_id", Client.clientId);
parameters.addProperty("device_id", deviceID);
parameters.addProperty("device_dateTime", Env.DATE_FORMAT.format(new Date()));
parameters.addProperty("device_timeZone", API.getTimezone());
parameters.addProperty("device_language", Env.LANGUAGE);
parameters.addProperty("app", Env.APP_NAME);
parameters.addProperty("role", "Patient");
return getInstance(context).invokeApi(apiName, parameters, httpMethod, null);
} else {
return getInstance(context).invokeApi(apiName, null, httpMethod, null);
}
}
This is probably related to an issue in Azure App Service that is weirdly enough not reported on the public Azure status page.
The message that affected Azure client received was (quoted from the link above):
Starting at 02:00 UTC on 3 Apr 2018, you have been identified as a
customer using App Services who may have received connection failure
notifications when using Android apps with older HTTP clients or
desktop browsers using cross-site scripting calls. Engineers have
identified an issue with a recent deployment and are investigating
mitigation options. Customers experiencing this issue can
self-mitigate by updating the site config setting "http20Enabled" to
false via resources.azure.com. Instructions on how to update site
config can be found here:
https://azure.microsoft.com/en-us/blog/azure-resource-explorer-a-new-tool-to-discover-the-azure-api/
Go to https://resources.azure.com/
Make sure you are in Read/Write mode by clicking in the option to the
left of your name.
Find the affected site and browse to Config > Web:
https://resources.azure.com/subscriptions//resourceGroups//providers/Microsoft.Web/sites//config/web
Change the property: "http20Enabled": from true to false by clicking
in Edit properties, Update to “false” and then clicking PUT to save
change.
If you have tried these steps and are continuing to experience issues
with your App Service, please create a technical support ticket to
further troubleshoot: aka.ms/azsupt. This message will be closed in 7
days.

Setting up Signal R in Android: Crash/Hung Issue

I followed THIS tutorial to set up a .NET Backend for my Android app to implement Signal R. I set up a SignalR Self-Hosted backend.
Here's my Backend Code in a Console Project:
namespace SignalRSelfHost
{
class Program
{
static void Main(string[] args)
{
// This will *ONLY* bind to localhost, if you want to bind to all addresses
// use http://*:8080 to bind to all addresses.
// See http://msdn.microsoft.com/en-us/library/system.net.httplistener.aspx
// for more information.
string url = "http://localhost:8080";
using (WebApp.Start(url))
{
Console.WriteLine("Server running on {0}", url);
Console.ReadLine();
}
}
}
class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR();
}
}
public class MessageHub : Hub
{
public static event Action<string, string> MessageReceived = delegate { };
public void SendMessage(string name, string message)
{
MessageReceived(name, message);
}
}
public class CustomType
{
public string Name;
public int Id;
}
}
My Android Code:
Handler handler;
TextView statusField;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
handler = new Handler();
statusField = (TextView) findViewById(R.id.statusField);
Platform.loadPlatformComponent(new AndroidPlatformComponent());
// Change to the IP address and matching port of your SignalR server.
String host = "http://192.168.1.5:8080/";
HubConnection connection = new HubConnection( host );
HubProxy hub = connection.createHubProxy( "MessageHub" );
ClientTransport transport = new ServerSentEventsTransport(connection.getLogger());
SignalRFuture<Void> awaitConnection = connection.start(transport);
try {
awaitConnection.get();
}
catch (InterruptedException e) {
Log.d("CHECK", e.toString());
e.printStackTrace();
} catch (ExecutionException e) {
Log.d("CHECK", e.toString());
e.printStackTrace();
}
hub.subscribe(this);
try {
hub.invoke( "SendMessage", "Client", "Hello world!" ).get();
hub.invoke( "SendCustomType",
new CustomType() {{ Name = "Universe"; Id = 42; }} ).get();
} catch (InterruptedException e) {
// Handle ...
} catch (ExecutionException e) {
// Handle ...
}
}
public void UpdateStatus(String status) {
final String fStatus = status;
handler.post(new Runnable() {
#Override
public void run() {
statusField.setText(fStatus);
}
});
}
public class CustomType
{
public String Name;
public int Id;
}
However, I end up with a screen that hangs and it displays nothing and the app stops responding. The android logger displays the following error:
java.util.concurrent.ExecutionException: java.net.ConnectException:
failed to connect to localhost/127.0.0.1 (port 80) after 15000ms:
isConnected failed: ECONNREFUSED (Connection refused)
Is my code correct and have I followed the guide properly? It's a very straight forward guide but this issue comes up. Can someone help out?
EDIT:
This is a very similar Question, in fact it describes the same issue. However it didn't do me any good. If you notice my android code, I've already made those changes proposed in that question. Still didn't rectify the issue.
Stacktrace
java.util.concurrent.ExecutionException: java.net.SocketTimeoutException: failed to connect to / 192.168.1.5(port 8080) after 15000ms
at microsoft.aspnet.signalr.client.SignalRFuture.get(SignalRFuture.java: 112)
at microsoft.aspnet.signalr.client.SignalRFuture.get(SignalRFuture.java: 102)
at com.example.dinuka.signalrtest.Main2Activity.onCreate(Main2Activity.java: 40)
at android.app.Activity.performCreate(Activity.java: 6289)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java: 1119)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java: 2655)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java: 2767)
at android.app.ActivityThread.access$900(ActivityThread.java: 177)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java: 1449)
at android.os.Handler.dispatchMessage(Handler.java: 102)
at android.os.Looper.loop(Looper.java: 145)
at android.app.ActivityThread.main(ActivityThread.java: 5951)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java: 372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java: 1400)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java: 1195)
Caused by: java.net.SocketTimeoutException: failed to connect to / 192.168.1.5(port 8080) after 15000ms
at libcore.io.IoBridge.connectErrno(IoBridge.java: 169)
at libcore.io.IoBridge.connect(IoBridge.java: 122)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java: 183)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java: 456)
at java.net.Socket.connect(Socket.java: 882)
at com.android.okhttp.internal.Platform.connectSocket(Platform.java: 139)
at com.android.okhttp.Connection.connect(Connection.java: 1194)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java: 392)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java: 295)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java: 373)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java: 323)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java: 491)
at microsoft.aspnet.signalr.client.http.java.NetworkRunnable.run(NetworkRunnable.java: 72)
at java.lang.Thread.run(Thread.java: 818)
I had similar issue a few days ago and this Github issue helped:
https://github.com/SignalR/java-client/issues/63
Basically what I did was modify the WebsocketTransport.java in the signalr-client-sdk project. Replace:
uri = new URI(url);
with
uri = new URI(url.replace("http://", "ws://"));
around line 86 in the source code.
I can now connect and send message and recieve raw data but cannot subscribe to events...
Hope this helps you get passed your problem.

How to configure connection for file transfer using asmack in android?

In My Android application I get xmpp connection initially using server_nm and 5222 port on login and done single chat message send and receive,but at time of file transfer, How I configure connection with proxy_server and 7777 port which use for file transfer?
public class XmppManager {
private static final int packetReplyTimeout = 500; // millis
private String server=server_nm;
private int port=5222;
private ConnectionConfiguration config;
private XMPPConnection connection;
String group_name,userid;
private ChatManager chatManager;
private MessageListener messageListener;
private Handler mHandler;
PacketFilter filter;
Message message;
Context context;
public static boolean IBB_ONLY = (System.getProperty("ibb") != null);//true;
protected static final String STREAM_DATA_FIELD_NAME = "stream-method";
private StreamNegotiator byteStreamTransferManager;
private StreamNegotiator inbandTransferManager;
// constructor
public XmppManager(String server, int port) {
this.server = server;
this.port = port;
}
// to initialize connection
public void init(Context c) throws XMPPException {
System.out.println(String.format(
"Initializing connection to server %1$s port %2$d", server,
port));
SmackConfiguration.setPacketReplyTimeout(50000);
config = new ConnectionConfiguration(server, port);
config.setSASLAuthenticationEnabled(false);
config.setSecurityMode(SecurityMode.disabled);
// group chat invitation
ProviderManager.getInstance().addExtensionProvider("x",
"http://jabber.org/protocol/muc#user",
new GroupChatInvitation.Provider());
// offline msgtime
ProviderManager.getInstance().addExtensionProvider("x",
"jabber:x:delay", new DelayInformationProvider());
//file transfer method
ProviderManager.getInstance().addIQProvider("query","http://jabber.org/protocol/bytestreams", new BytestreamsProvider());
ProviderManager.getInstance().addIQProvider("query","http://jabber.org/protocol/disco#items", new DiscoverItemsProvider());
ProviderManager.getInstance().addIQProvider("query","http://jabber.org/protocol/disco#info", new DiscoverInfoProvider());
ProviderManager.getInstance().addIQProvider("si","http://jabber.org/protocol/si", new StreamInitiationProvider());
ProviderManager.getInstance().addIQProvider("open","http://jabber.org/protocol/ibb", new OpenIQProvider());
ProviderManager.getInstance().addIQProvider("close","http://jabber.org/protocol/ibb", new CloseIQProvider());
ProviderManager.getInstance().addExtensionProvider("data","http://jabber.org/protocol/ibb", new DataPacketProvider());
// v-card integration
ProviderManager.getInstance().addIQProvider("vCard", "vcard-temp", new VCardProvider());
connection = new XMPPConnection(config);
connection.connect();
System.out.println("Connected: " + connection.isConnected());
chatManager = connection.getChatManager();
context = c;
Intent i = new Intent(context, MyService.class);
context.startService(i);
}
// login to xmpp server
public void performLogin(String username, String password,String resource)
throws XMPPException {
if (connection != null && connection.isConnected()) {
System.out.println("connection on presence send" + connection.isConnected() + " " + username + " " + password);
connection.login(username, password,resource);
setStatus(true, "Online");
Presence presence = new Presence(Presence.Type.available);
connection.sendPacket(presence);
}
}
//using this code I try to send file
public void sendfileafterresponse(String filenm,String filereceiverid )
{
FileTransferNegotiator.IBB_ONLY = true;
this.setServiceEnabled(connection, true);
FileTransferManager manager = new FileTransferManager(connection);
OutgoingFileTransfer transfer = manager.createOutgoingFileTransfer(filereceiverid + "#chat.bobl.us/" + filereceiverid);
File file = new File(filenm);
try {
System.out.println("file send to" + filenm + filereceiverid);
transfer.sendFile(file, "test_file");
} catch (XMPPException e) {
e.printStackTrace();
}
while(!transfer.isDone()) {
if(transfer.getStatus().equals(Status.error)) {
System.out.println("ERROR!!! " + transfer.getError());
} else if (transfer.getStatus().equals(Status.cancelled)
|| transfer.getStatus().equals(Status.refused)) {
System.out.println("Cancelled!!! " + transfer.getError());
}
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(transfer.getStatus().equals(Status.refused) || transfer.getStatus().equals(Status.error)
|| transfer.getStatus().equals(Status.cancelled)){
System.out.println("refused cancelled error " + transfer.getError());
} else {
System.out.println("Success");
}
}
}
}
If you still want to transfer files via smack directly, you basically have too options, as far as I understand the API.
1.
First you can use In Band transmission, that is enabled via
FileTransferNegotiator.IBB_ONLY = true;
This sends your file as base64 encoded message, the same way you are sending a normal message packet.
The second option is to use a streaming proxy. This one is way faster since it does not need to encode / decode the file to base64 but transmitts the data directly. Both devices connnect to the proxy server and share data on this.
To configure a streaming proxy you have to configure it on the server side and add the Providers to your client side connection (this should be done automatically on the latest asmack library).
I configured such a setup using the ejabberd service and mod_proxy65 Mod_proxy65
add to your /etc/ejabberd/ejabberd.yml, your ip adress and host should match the service you are using.
host: "proxy1.example.org"
name: "File Transfer Proxy"
ip: "200.150.100.1"
port: 7777
Then allow the firewall to communicate on this port, and you should be good to go.
However, I figured out, that the file transfer only is functional, if both clients are in the presence "available" if any of them is in another state, the sender receives "service- unavailabe" errors.
Don't rely on XMPP file transfer using aSmack/Smack as it is buly. Instead you can create a plugin which will upload files to the server and after successfully uploading the files send the absolute url of the file to the recipient so that he/she can download the file from there.
Hope this works !

Categories

Resources