KSoap2 on Android freezing the device instead of making a webservice call - java

I'm trying to connect to .NET 4.0 webservice I created for receiving SOAP-calls from Android-devices, now hosted on local IIS for testing purposes.
I found out that ksoap2 would be an excellent class library for doing what i want to do. Downloaded the .jar package from https://code.google.com/p/ksoap2-android/ and started pounding the keyboard in ecstacy... with my fingers.
The amount of information being sent is from few kilobytes to few megabytes.
What is working
HttpTransportSE.call(String, SoapSerializationEnvelope)-method works perfectly while still in Eclipse's Android emulator, sending the call to webservice hosted in local IIS. Even tested that the webservice receives empty calls from trying to open the service address from a web browser in the same local area network.
What doesn't work
When I copy the .apk-file to an Android device, install it, start it and trying to make the call, the whole program freezes without making the call.
As you can see from a code block presented some lines after that possible errors are being taken into account: In emulated environment a successful call returns a SoapPrimitive-object or flows into the correct catch block generating an error message for the user according to the current situation.
Then on live Android device, program loses it's responsivity forever and has to be terminated from application menu.
What have i tried
I removed the call from the asynchronous method, and tried calling it straight from an anonymous inner function assigned for a button click-event.
Tried not trying to get a response, just making the call.
Tried getting a logcat-program for the device to see what's happening behind the UI, found two, they needed root access, which i don't have in the device. This is why i don't have any logcats to show you, and showing the emulator logcat would probably(?) be useless because it works fine there.
Not trying to connect to localhost.
Tried installing the program on older Lenovo-tablet running Android 4.2.2 and on brand new Samsung Galaxy Tab, both would have the same problem while otherwise working well.
The code
Here's the asynchronous method for making the call in device/emulator, where variables str_URL and soapRequest are a correct service address (checked) and a well formed SoapObject respectively:
#Override
protected WebServiceResult doInBackground(Void... v) {
WebServiceResult _ret;
SoapSerializationEnvelope soapEnvelope= new SoapSerializationEnvelope(SoapEnvelope.VER11);
soapEnvelope.dotNet=true;
soapEnvelope.setAddAdornments(false);
soapEnvelope.setOutputSoapObject(soapRequest);
HttpTransportSE conn = new HttpTransportSE(str_URL);
conn.setXmlVersionTag("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
conn.debug = true;
try {
conn.call(str_ACTION, soapEnvelope);
SoapObject o = (SoapObject)soapEnvelope.getResponse();
_ret = new WebServiceResult(o, WebServiceResultEnum.ok);
} catch (NetworkOnMainThreadException e) {
_ret = new WebServiceResult(null, WebServiceResultEnum.keskeytys);
} catch (HttpResponseException e) {
_ret = new WebServiceResult(null, WebServiceResultEnum.httpVirhe);
} catch (XmlPullParserException e) {
_ret = new WebServiceResult(null, WebServiceResultEnum.vaara_muoto);
} catch (SocketTimeoutException e) {
_ret = new WebServiceResult(null, WebServiceResultEnum.aikakatkaisu);
} catch (Exception e) {
_ret = new WebServiceResult(null, WebServiceResultEnum.keskeytys);
}
return _ret;
}
Thank you in advance!

Is it possible you are doing something like this:
YourAsyncTask task = new YourAsyncTask();
WebServiceResult result = task.doInBackground();
Because that would be wrong, completely wrong. If you call doInBackground() directly it will run in the same Thread and not in a new one. You need to start the AsyncTask with execute() like this:
YourAsyncTask task = new YourAsyncTask();
task.execute();
You need to implement the AsyncTask like this:
public class ExampleTask extends AsyncTask<Void, Void, WebServiceResult> {
public interface FinishedListener {
public void onFinished(WebServiceResult result);
}
private final FinishedListener finishedListener;
public ExampleTask(FinishedListener listener) {
this.finishedListener = listener;
}
#Override
protected WebServiceResult doInBackground(Void... params) {
WebServiceResult result = ...;
return result;
}
#Override
protected void onPostExecute(WebServiceResult result) {
super.onPostExecute(result);
if(this.finishedListener != null) {
this.finishedListener.onFinished(result);
}
}
}
And if you implemented it that way you can use it like this:
ExampleTask task = new ExampleTask(new ExampleTask.FinishedListener() {
#Override
public void onFinished(WebServiceResult result) {
// This will be called if the task has finished
}
});
task.execute();

It seems that I had declared the minimum SDK as 14 and target SDK as 17 in AndroidManifest.xml. I didn't use any fancy things in newer sdk's so i lowered the target SDK to the same level as minimum SDK, 14. I also had an Avast! Antivirus service running on the tablet which i removed.
This solved my problem. It could be that probably the Avast! antivirus-program wanted to block all communications from applications not downloaded from Play-store. I don't know if changing the target SDK had much effect really.

Well, I had the same question as you. When it goes to the method transport.call, it pauses, and for a while, it throws a timeout problem. At first, I thought maybe the network was poor, but the server logcat shows it is not the problem. The request was fine and the response was good. My business process is like below:
First, I get a list from the server through ksoap inner a child thread, then cycle the list, send a ksoap request based on every item of the list. It means it will send another list.size() request. When debugging in a real device the above problems occured. I solved it by starting a new child thread after getting the list and making all the list.size requests in the new child thread. So, ksoap use in android may cause thread block which leads to ioexception. So when you put it in a new thread, it escapes from the parent catch exception and works fine.

Related

How to save game data to the cloud using gdx-gamesvcs?

I want to implement Google Play Games Services in my game on the libgdx engine. I tried using gdx-gamesvcs for this. But I am having trouble saving data. I understood from the example that one value is being saved, not the entire state of the game. So I decided to check it out: save and load one value using gsClient.loadGameState and gsClient.saveGameState. I deliberately deleted the game data from the device. But as a result, not only the test value changed, but many others as well. I thought that the state of the entire game is being saved, but the values ​​obtained do not fit into the logic of the game and could not be obtained in it.
How should I use this tool and is it worth it at all, or is it better to use what libgdx itself offers?
Here is a piece of code:
if (gsClient.isSessionActive()) {
try {
gsClient.saveGameState("data", intToByteArray(testValue), 0, null);
} catch (UnsupportedOperationException unsupportedOperationException) {
}
if (gsClient.isSessionActive()) {
try {
gsClient.loadGameState("data", new ILoadGameStateResponseListener() {
#Override
public void gsGameStateLoaded(byte[] gameState) {
if (gameState != null) {
setTestValue(bytesToInt(gameState));
}
}
});
} catch (UnsupportedOperationException unsupportedOperationException) {
}
}
UPD
Yes, saving occurs both to the cloud and to the device, for saving to the device I use Preferences. I have a Google account login button in the game, it works, I have repeatedly seen this standard bar of my account level, which appears at the top when I log in. Everything is set up in the developer console too, I have an id for achievements and leaderboards. In code, I work with the client like this (In the create() method):
public IGameServiceClient gsClient;
if (gsClient == null) {
gsClient = new MockGameServiceClient(1) {
#Override
protected Array<ILeaderBoardEntry> getLeaderboardEntries() {
return null;
}
#Override
protected Array<String> getGameStates() {
return null;
}
#Override
protected byte[] getGameState() {
return new byte[0];
}
#Override
protected Array<IAchievement> getAchievements() {
return null;
}
#Override
protected String getPlayerName() {
return null;
}
};
}
gsClient.setListener(this);
gsClient.resumeSession();
Next is loading.
The exception is not caught, I removed it and everything works as before.
Well, libgdx offers no built-in cloud-save, it is hard to use it for that. :-)
You should in any case save to local AND to cloud, as the cloud is not very fast to load its state.
I can see no problem in your code besides the fact that you swallow an UnsupportedOperationException that is thrown if you did not activate cloud save feature. So the interesting question is: what happens if you don't swallow the exception, and did you intialize GpgsClient with cloud save enabled? Are you really logged in to Gpgs, and is the feature also activated in your developer console?
The main problem was that gameState was null, this arose due to the fact that you had to wait 24 hours after enabling the save function in the developer console, and the advice on clearing the memory of google play games on the test device did not help. After a while gameState began to pass the existing values, but I started having problems with the graphics flow, probably due to the asynchronous loading.

Android - Retrofit web service value problems

I have phone contact numbers list stored in an array and called contactsString[]
and in an online database registered users numbers
I want to count how many registered users are there
and there is my code
for (i=0;i<contactsString.length-1;i++){
Phone phone=new Phone();
phone.phone=contactsString[i]
WebService.getInstance().getApi().checkNumber(phone).enqueue(new Callback<MainResponse>() {
#Override
public void onResponse(Call<MainResponse> call, Response<MainResponse> response) {
if (response.body().status==1){
availableUsers++;
}
}
#Override
public void onFailure(Call<MainResponse> call, Throwable t) {
}
});
}
my problem is the web service response is delayed so it don't count and availableUsers is printed it's initial value which is 0
I would try better sending an array of Phone objects. In this way you would get the correct answer in 1 call.
I would never do this in the way you implemented: imagine you have 500 contacts: you will be doing 500 calls to your server. Now imagine you have 100000 users with 500 contacts each
Try to customize your api call in this format. Which uses async task class.
private void phoneContact() {
new AsyncTask<String,Void,String>() {
#Override
protected String doInBackground(String ... params) {
try {
Platform http = Url_Contacts;
JSONObject resp = http.search(what,where);
Log.d(TAG, "Response: " + resp.toString());
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
return "";
}
}.execute();
}
Make sure that your service works well and the format of json with value status in there.
In onResponse, run on UIThread to update your View with the availableUsers.
The enqueue method is asynchronous. So your code should respect the multithreaded nature of it.
There are many approaches you can take:
Replace enqueue() method with execute(). But that makes all the calls synchronous. If you call it in UI Thread then whole app can stutter. Probably you will get NetworkOnMainThreadException. Not a good approach anyway.
Use RxAndroid or RxJava with Observer pattern.
Simple solution. Create a variable int callsFinished = 0;. In onResponse increment that variable. Then if that callsFinished == contactsString.length that means all calls have been done.
In your activity add a listener
void onAllCallsFinished(int availableUsers) {
//do what you want with availableUsers information
}
Call onAllCallsFinished(availableUsers) when callsFinished == contactsString.length.
There you can do what you want with that data. Update a view, call another service.

Querying Azure's Mobile Service Client efficiently for Android

I am making an Android application and have decided to use Azure's DB platform. I find adding entries to different tables very easy, but querying the DB to be almost impossible.
Currently I am trying to follow this model: How to get the result of OnPostExecute() to main activity because AsyncTask is a separate class?
In short, it uses an interface to implement a AsyncTask with my query executing in doInBackground(). My problem with this is that it is many many lines of code to execute a single simple query, AND I will need to be doing multiple unique queries when running my app and creating tens of separate interfaces/classes seems extremely inefficient.
At the end of the day all I want is to get the results from this query in a managable way:
final MobileServiceList<Users> result = mUser.where().field("username").eq(username).execute().get();
However it seems to not execute without being wrapped in a AsyncTask like this:
new AsyncTask<Users, Void, Users>() {
#Override
protected Users doInBackground(Users... params) {
try {
final MobileServiceList<Users> result = mUser.where().field("username").eq(username).execute().get();
if(result.size() > 0) {
System.out.println("something in list");
return result.get(0);
}
} catch (Exception exception) {
exception.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Users result) {
System.out.println("in post");
if(username.equals((result.username)) && password.equals(result.password)) {
System.out.println("found user");
}
}
}.execute();
Is there any easy way to get around this? All I want is a result from a simple query, I don't understand how this is so hard..
Thanks!
Unfortunately, there is not any simple way to get around this, please refer to AsyncTask reference to know it for helping Android UI thread to get result asynchronously.

How can I DetectFaces in Amazon Rekognition AWS with Android Studio?

I have tried so many way but i can't succeed. I haven't found any source code examples for Android(about rekognition)
there's a source code in JAVA in the Developer Guide but i cannot implement that even though I tried TT
I try to detect faces by sending an image file from an external storage(from the emulator)
I don't know what i did wrong(I'm not good at coding)
Here is my code
AmazonRekognitionClient amazonRekognitionClient;
Image getAmazonRekognitionImage;
DetectFacesRequest detectFaceRequest;
DetectFacesResult detectFaceResult;
File file = new File(Environment.getExternalStorageDirectory(),"sungyeol.jpg.jpg");
public void test_00(View view) {
ByteBuffer imageBytes;
try{
InputStream inputStream = new FileInputStream(file.getAbsolutePath().toString());
imageBytes = ByteBuffer.wrap(IOUtils.toByteArray(inputStream));
Log.e("InputStream: ",""+inputStream);
Log.e("imageBytes: ","");
getAmazonRekognitionImage.withBytes(imageBytes);
// Initialize the Amazon Cognito credentials provider
CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(
getApplicationContext(),
"us-east-2:.......", // Identity Pool ID
Regions.US_EAST_2 // Region
);
//I want "ALL" attributes
amazonRekognitionClient = new AmazonRekognitionClient(credentialsProvider);
detectFaceRequest = new DetectFacesRequest()
.withAttributes(Attribute.ALL.toString())
.withImage(getAmazonRekognitionImage);
detectFaceResult = amazonRekognitionClient.detectFaces(detectFaceRequest);
detectFaceResult.getFaceDetails();
}
catch(Exception ex){
Log.e("Error on something:","Message:"+ex.getMessage());
}
and here is my errors
02-04 09:30:07.268 29405-29405/? E/InputStream:: java.io.FileInputStream#a9b23e7
02-04 09:30:07.271 29405-29405/? E/Error on something:: Message:Attempt to invoke virtual method 'com.amazonaws.services.rekognition.model.Image com.amazonaws.services.rekognition.model.Image.withBytes(java.nio.ByteBuffer)' on a null object reference
what is a null object reference?
i try to change the file path but he said no such file ... and when I change to this path, there's errors above.
by the way I've already asked a user for a permission to access a folder from Emulator in Android
please help me
PS. sorry for my bad English
Thank you in advance.
Now I am ok with the issues. I have been through many many things <3 <3 <3.
Thank you
I'm Thai and I had to try harder to find the solutions because there's lack of information in the particular language. Here are my solutions.
My solutions are:
0.There is an endpoint for setting for the Rekognition-->
http://docs.aws.amazon.com/general/latest/gr/rande.html#rekognition_region
1.On a "null object reference issue" I found that I have to create a new object first such as "Image image = new Image();" <-- The "new" command creates an object instance in that class
2.After the above error, there are more errors (Errors on NetworkOnMainThreadException), so I tried everything until I found this page -->
https://docs.aws.amazon.com/cognito/latest/developerguide/getting-credentials.html the page said that ...
Consequently, I looked up for more information about the AsyncTask and after that I created an AsyncTask class and then I move all my code about the initialize, the request, the response to the AsyncTask class. ตอนรันตอนท้ายๆน้ำตาจิไหล my code worked... TT and by the conclusion the sungyeol.jpg.jpg file worked
for example
private void testTask(){
.... all code in the main thread particularly on the requests and responses
from the services
//print the response or the result
//Log.e() makes the message in the android monitor red like an error
Log.e("Response:", [responseparameter.toString()]);
}
//create the inherited class from the AsyncTask Class
//(you can create within your activity class)
class AsyncTaskRunner extends AsyncTask<String,String,String>{
#Override
public String doInBackground(String ... input){
testTask(); // call the testTask() method that i have created
return null; // this override method must return String
}
}
//I've created a button for running the task
public void buttonTask(View view){
AsyncTaskRunner runner = new AsyncTaskRunner();
runner.execute();
}
for more information about the AsyncTask:
https://developer.android.com/training/basics/network-ops/connecting.html#AsyncTask
http://www.compiletimeerror.com/2013/01/why-and-how-to-use-asynctask.html#.WJdkqVOLTIU
I hope these help :)

How do I get my app to not hang on device

I am new to android development and software programming in general and believe I have a threading issue in my app. What the app does is searches for two sets of results based on two queries to an api and stores each set of results in its own list. A new list is generated containing only the elements that are in both lists. The app runs in a virtual device on my desktop but hangs on my Galaxy Nexus. I am using arraylist for this but I am wondering if perhaps hashset would be faster at accomplishing this type of operation. Below is my main activity. getfirst and secondID are done in an asynctask as well as getfirst and secondtitle in order to prevent networkonmainthread exception. Is that the best way to thread this application? Thanks for any help.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.totlayout);
//set the UI elements
searchOne = (EditText) findViewById(R.id.searchOne);
searchTwo = (EditText) findViewById(R.id.searchTwo);
findMovies = (Button) findViewById(R.id.findMovies);
searchOne.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
//make person search url1
final StringBuilder personSearchURLOne = new StringBuilder(getName.getName1(searchOne));
searchURLOne = personSearchURLOne.toString();
return false;
}
});
searchTwo.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
//make person search url2
final StringBuilder personSearchURLTwo = new StringBuilder(getName.getName2(searchTwo));
searchURLTwo = personSearchURLTwo.toString();
return false;
}
});
}
public void getData(String searchURLOne, String searchURLTwo){
try{
//get ID 1
idOne = new getFirstID().execute(searchURLOne).get();
Log.d("JSONArray idOne", idOne.toString());
//get ID 2
idTwo = new getSecondID().execute(searchURLTwo).get();
Log.d("JSONArray idTwo", idTwo.toString());
//make credit search url1
final StringBuilder creditURLOne = new StringBuilder(buildCreditURL.getCreditURLOne(idOne));
final String creditOne = creditURLOne.toString();
Log.d("creditOne contains", creditOne);
//make credit search url2
final StringBuilder creditURLTwo = new StringBuilder(buildCreditURL.getCreditURLTwo(idTwo));
final String creditTwo = creditURLTwo.toString();
//get array of tiles for credit url 1
titleOne = new getFirstTitle().execute(creditOne).get();
Log.d("titleOne Contains", titleOne.toString());
//get array of titles for credit url 2
titleTwo = new getSecondTitle().execute(creditTwo).get();
//parse out common films into new array
myCommonFilms = new ArrayList<String>(commonFilms.getCommonFilms(titleOne, titleTwo));
}
catch(InterruptedException e){
e.printStackTrace();
}catch(ExecutionException e){
e.printStackTrace();
}
}
public void displayResults(View view) throws InterruptedException, ExecutionException{
//do something in response to button
getData(searchURLOne, searchURLTwo);
Intent intent = new Intent(this, DisplayResultsActivity.class).putStringArrayListExtra("myCommonFilmsList", myCommonFilms);
startActivity(intent);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.totlayout, menu);
return true;
}
}
I think it's the correct way : using AsyncTask is an easy way to prevent your app for freezing the UI.
But I don't really understand what the following line do.
idOne = new getFirstID().execute(searchURLOne).get();
Actually, I never see it before. Anyway, how many records are you managing in your ArrayList ? 10, 100, 1000, 1 000 000 ?
If you're working with a lot of records, your phone will take a certain amount of time to accomplish the operations and you'll not be able to reduce it. The only solution, if the set is too large, is to trying to reduce it maybe directly on your server or when you're building your ArrayList.
I'm not necessarily following where the AsyncTask is created and put into action but it seems like it would be a good idea to put the entire getData method on the AsyncTask. That aside, if it works on the and but not on the device my 1st suspicion would be network access. Make sure your device has access not only to the internet but to the service that it needs to run the remote query on. It's very common to misunderstand that phones cannot see the same host computers as our desktops can. Also, if you're phone is roaming on Wifi check that the Wifi network will allow the service to be accessed. Is the remote query service a web service? Is it a DBMS SQL call you are trying to run? does the query require a specific network port?
this one seems to block the UI thread:
titleOne = new getFirstTitle().execute(creditOne).get();
better use a new thread for doing the long job , and once it finishes , notify the UI thread about the new data .
you can use asyncTask to make it easier for you . if you prefer the normal threads ,either use a handler (and use handler.post) or use runOnUiThread once the thread has finished.
if you use a hanlder , don't forget to create it outside the of thread itself.
as a new android developer , you should watch the google IO videos . they can help a lot . watch videos from 2010 to 2012 .

Categories

Resources