General Info
I'm working on a chat plugin for Spigot (Minecraft server). The idea is to create a chatsystem that allows the use of working chat tabs:
In order to accomplish this, I have to use NMS (ProtocolLib) because Minecraft uses 3 types of messages in chat:
Chat messages
System messages
Game info messages
Chat messages are easily accessible, but the other 2 are not. If I don't catch those messages, they push the tabs menu up instead of ending up in their own chat channel.
The problem
The code (below) I'm using to catch these messages is causing the following exception in connected Minecraft clients and disconnects them upon an ingame plugin reload through /reload:
DecoderException: java.lang.IndexOutOfBoundsException: readerIndex(0)
+ length(1) exceeds writerIndex(0) UnpooledSlicedByteBuf(ridx: 0, widx: 0, cap: 0/0, unwrapped: PooledUnsafeDirectByteBuf(ridx: 2, widx:
6, cap: 16384)) # io.netty.handler.codec.MessageToMessageDecoder:98
Relevant code
private void initPacketListener(){
protocolManager.addPacketListener(new PacketAdapter(this, ListenerPriority.NORMAL, new PacketType[] { PacketType.Play.Server.CHAT })
{
#SuppressWarnings("unused")
#Override
public void onPacketSending(PacketEvent event) {
if ((event.getPacketType() == PacketType.Play.Server.CHAT)){
PacketContainer packet = event.getPacket();
Player player = event.getPlayer();
String message = "";
try {
String jsonMessage = event.getPacket().getChatComponents().getValues().get(0).getJson();
if (jsonMessage!=null&&!jsonMessage.isEmpty()) {
message = jsonToString(jsonMessage);
if (message.isEmpty()) return;
Subscriber subscriber = UMM.plugin.getSubscribers().get(player.getUniqueId());
String uuid = player.getUniqueId().toString();
Channel messageChannel = UMM.serverChannels.get(uuid);
messageChannel.addMessage(message);
ChatListener cl = new ChatListener(UMM.plugin);
cl.notifyChanges(messageChannel);
event.setCancelled(true);
} else {
System.out.println("Not a system msg");
}
} catch (Throwable e){
System.out.println("UMM Packet Error:" + e.getMessage());
}
}
}
});
}
What I've tried myself to solve the issue
I asked some other devs about the problem and was told:
Make sure that the size/length of event.getPacket().getChatComponents().getValues() is greater than 0 before making the #get call.
So I tried this:
List<WrappedChatComponent> wrap = event.getPacket().getChatComponents().getValues();
if(wrap.size() > 0) {
if ((event.getPacketType() == PacketType.Play.Server.CHAT)){
...
}
}
But it had no effect at all. They were unable to help me any further so I hope someone else might know what's going on and how I can solve the problem.
Update
Even after reducing the code to just this, the problem still persists:
private void initPacketListener(){
protocolManager.addPacketListener(new PacketAdapter(this, ListenerPriority.NORMAL, new PacketType[] { PacketType.Play.Server.CHAT })
{
#SuppressWarnings("unused")
#Override
public void onPacketSending(PacketEvent event) {
}
});
}
A "temporary" solution to the problem is using a BukkitRunnable to call the method 1 tick after the server is done reloading. The only down side to this is that any messages appearing before the first tick are pushing the tabs menu up. The plugin fixes this upon the next message event.
You should never use /reload command, see more here for example : https://madelinemiller.dev/blog/problem-with-reload/.
You can implement a reload command in your plugin that does what you want if you need it. Maybe your issue could be gone with an internal reload command because it might be a issue with /reload command.
Related
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.
I'm working with notifications generated by every app (not only mine) on my Android device (android 5.1.1).
By extending NotificationListenerService I'm able to know when a push notification is posted (overriding the "onNotificationPosted" method) and when a notification is removed (overriding the "onNotificationRemoved" method).
The problem is that I would like to know how the notification was removed:
a) by clicking it (so opening the app)
or
b) by swyping it (so it is only removed)
?
Is it possible to know it?
Thank you in advance!
The best way to do it is to get the list of all running processes!
So, in the onNotificationRemoved method we can:
1. obtain the list of running processes using the Android Processes library
2. compare each process name with the packageName
3. if the comparison return a true value, we check if the process is in foreground
public void onNotificationRemoved(StatusBarNotification sbn) {
String packageName = sbn.getPackageName();
try {
List<AndroidAppProcess> processes = ProcessManager.getRunningAppProcesses();
if (processes != null) {
for (AndroidAppProcess process : processes) {
String processName = process.name;
if (processName.equals(packageName)) {
if (process.foreground ==true)
{
//user clicked on notification
}
else
{
//user swipe notification
}
}
}
}
}
catch (Exception e)
{
String error = e.toString();
}
}
I have some problems with use of ContractNet (Interaction Protocol) and GUI with the use of JADE multiagent framework.
In particular, in the override of handlePropose method.
I know that my problem comes from the use of a GUI. Let me explain:
My agent (Initiator) uses a first GUI and, after a click, the
conversation begins with a second agent (Responder). According to the
Protocol, the Initiator has thus sent a CFP to Responder. The agent
Responder responds with a PROPOSE that contains different data.
Since here, everything ok. Now...
I wish that the agent Initiator, BEFORE returning a reply, may examine
the data ... ie publish them on a JTable, for the user! The user will
examine the proposal via GUI and will choose if to accept or not, by
click on a button.
If accept, the Initiator send ACCEPT_PROPOSAL.
If not accept, the Initiator send REJECT_PROPOSAL.
This should be done in the method handleProposal. This is my code:
#Override
protected void handlePropose(final ACLMessage propose, final Vector acceptances) {
try {
System.out.println("Agent "+getLocalName()
+": receive PROPOSE from "+propose.getSender().getLocalName());
final ACLMessage reply = propose.createReply();
Vector<Goods> goods = (Vector<Goods>) propose.getContentObject();
// the JTable's GUI for visualize the list of data:
final GoodsChoiceBox gcb = new GoodsChoiceBox(propose.getSender().getName(), goods);
// the problem:
gcb.getExecuteJButton().addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
reply.setPerformative(ACLMessage.ACCEPT_PROPOSAL);
System.out.println("Agent "+getLocalName()+": send ACCEPT PROPOSAL ");
acceptances.addElement(reply);
}
});
// similar case, but for REJECT:
// gcb.getAbortJButton().addActionListener(... bla bla
gcb.setVisible(true);
} catch (UnreadableException e){
e.printStackTrace();
}
}
..... But, obviously, does not work.
In the Initiator agent, the ContractNet behaviour is aborted... so also handleInform, handleRefuse and handleFailure (for handle the answers) do not work.
The Initiator's principal GUI is blocked. And other problems...
Instead, if I do this (WITHOUT JButton, another GUI and ActionListener):
#Override
protected void handlePropose(final ACLMessage propose, final Vector acceptances) {
try {
System.out.println("Agent "+getLocalName()
+": received PROPOSE from "+propose.getSender().getLocalName());
final ACLMessage reply = propose.createReply();
Vector<Goods> goods = (Vector<Goods>) propose.getContentObject();
// the JTable's GUI for visualize the list of data:
final GoodsChoiceBox gcb = new GoodsChoiceBox(propose.getSender().getName(), goods);
reply.setPerformative(ACLMessage.ACCEPT_PROPOSAL);
System.out.println("Agente "+getLocalName()+": ACCEPT PROPOSAL di "+propose.getSender().getLocalName());
acceptances.addElement(reply);
} catch (UnreadableException e){
e.printStackTrace();
}
}
.... works.
I know that the problem is the ActionListener and its multithread nature.
But I need the GUI there.
How can I fix?
I try to answer myself. I'm not sure it's the best solution, but certainly works.
Note that before coming to this solution I am well documented with the guides and tutorials found (on http://jade.tilab.com/), and confronting myself with other
JADE developers (in mailing lists http://jade.tilab.com/pipermail/jade-develop/)
The answer is complicated, so I'll try to be exhaustive.
In my project I have to deal with two different types of agents.
The ShipperAgent, which represents one shipper: it keeps track of the vehicles owned by the shipper, those available, and the goods "reserved" from it.
The BuyerAgent, which represents customers (or buyers): each customer has a list of goods that want to move from point A to point B.
The two agents are registered to the yellow pages service.
In ShipperAgent, clicking on the "SEARCH" button you start a search: start a Contract Net Interaction Protocol.
Explain the Contract Net Interaction Protocol and my case
In the standard FIPA: http://www.fipa.org/specs/fipa00029/SC00029H.html
In JADE guide can be found here: http://jade.tilab.com/doc/programmersguide.pdf (p. 35)
Further on you will notice the changes that I had to take.
The ShipperAgent sends CFP each BuyerAgent.
Each BuyerAgent:
2.1 if he has goods, send a PROPOSE to ShipperAgent.
2.2 if does not have the goods, send a REFUSE to ShipperAgent. And for buyer, the protocol ends.
Since here is easy. With the sniffer, we can observe:
Now:
The ShipperAgent:
3.1 receives one or more PROPOSE by buyers, and displays (see image below).
3.2 if it receives the REFUSE (or does not receive anything after a certain time), ending communication with those buyer.
Here's how the Shipper graphically displays the proposals:
Now it's up to the user to choose which goods wants and what not.
To achieve this, I had to create some kind of "internal communication" to the agent himself: the GUI (in 3.1), once clicked Execute, sends a message to the agent. It may seem inelegant, but it seems to be the only way to not crash the protocol side ShipperAgent.
The ShipperAgent:
4.1 if the user has selected one or more goods proposals (and click Execute), sends to the corresponding BuyerAgent an ACCEPT_PROPOSAL, where specific goods that want to (a subset of the previous proposal).
4.2 if the user does not select any good (or click on Cancel), sends to the corresponding BuyerAgent an REJECT_PROPOSAL. Ends communication to that buyer.
The BuyerAgent:
5.1 if receives an ACCEPT_PROPOSAL, check that the goods are still available (any other shippers could have them "reserved" in the meanwhile) and, if so, sends an INFORM.
5.2 if receives an ACCEPT_PROPOSAL ma one or more goods are no longer available, sends FAILURE.
5.3 if it receives an REJECT_PROPOSAL, ends communication with the ShipperAgent.
In brief this (for example):
The code
BuyerAgent.java
I create a dispatcher who is always ready to receive the CFP. As soon as it receives and start protocol, buyer-side: start SearchJobResponder.
/*
* ...
*/
final MessageTemplate template = MessageTemplate.and(
MessageTemplate.MatchProtocol(FIPANames.InteractionProtocol.FIPA_CONTRACT_NET),
MessageTemplate.MatchPerformative(ACLMessage.CFP) );
// SSResponderDispatcher:
SSResponderDispatcher dispatcher = new SSResponderDispatcher(this, template) {
BuyerAgent b = (BuyerAgent) this.myAgent;
protected Behaviour createResponder(ACLMessage initiationMsg) {
// SearchJobResponder for single cfp:
return new SearchJobResponder(b, initiationMsg);
}
};
addBehaviour(dispatcher);
/*
* ...
*/
ShipperAgent.java
Search all buyer, creates a CFP and start the protocol, shipper-side: start SearchJobInitiator.
/*
* ...
*/
ACLMessage cfp = new ACLMessage(ACLMessage.CFP);
AID[] buyerAgents = searchBuyers(); // search all buyerAgents
for (AID buyer : buyerAgents)
cfp.addReceiver(buyer);
addBehaviour(new SearchJobInitiator(this, cfp));
/*
* ...
*/
SearchJobInitiator.java
This was the hard part...
/*
* ...
*/
public class SearchJobInitiator extends ContractNetInitiator {
ShipperAgent shipperAgent;
public SearchJobInitiator(ShipperAgent a, ACLMessage cfp) {
super(a, cfp);
shipperAgent=a;
// Very important:
registerHandleAllResponses(new HandleProposes());
}
#Override
protected Vector<?> prepareCfps(ACLMessage cfp) {
long now = System.currentTimeMillis();
cfp.setConversationId("contractNet-by-"
+shipperAgent.getAID().getLocalName()+now);
cfp.setContent("Fammi delle proposte di lavoro");
/*
* filtering...
*/
cfp.setProtocol(FIPANames.InteractionProtocol.FIPA_CONTRACT_NET);
cfp.setReplyByDate(new Date(now+10000));
//cfp.setReplyWith("cfp"+System.currentTimeMillis()) //useless, is overwrited at the end
return super.prepareCfps(cfp);
}
//inner class for handling a single proposal
public class HandleProposes extends Behaviour {
private static final long serialVersionUID = 1L;
private Vector<ACLMessage> proposes;
private Vector<ACLMessage> acceptances;
private int numberOfProposes;
public void onStart() {
proposes = (Vector<ACLMessage>) getDataStore().get(ALL_RESPONSES_KEY);
acceptances = (Vector<ACLMessage>) getDataStore().get(ALL_ACCEPTANCES_KEY);
numberOfProposes=proposes.size();
for (Iterator I=proposes.iterator(); I.hasNext();) {
ACLMessage propose = (ACLMessage) I.next();
// Very important:
if (propose.getPerformative()==ACLMessage.PROPOSE)
myAgent.addBehaviour(new HandleSinglePropose(propose, acceptances));
else
numberOfProposes--;
}
}
public void action() {
if (!done())
block();
}
public boolean done() {
return (acceptances.size()==numberOfProposes);
}
/*
* Inner class for handle a single proposal and display it:
*/
public class HandleSinglePropose extends Behaviour {
private ACLMessage propose;
private Vector<ACLMessage> acceptances;
private boolean finish=false;
public HandleSinglePropose (ACLMessage propose, Vector<ACLMessage> acceptances) {
this.propose=propose;
this.acceptances=acceptances;
// This is GUI in 3.1 point
GoodsChoiceBox gcb = new GoodsChoiceBox(shipperAgent, this, propose); // fill the JTable
gcb.setVisible(true);
}
#Override
public void action() {
MessageTemplate mt = MessageTemplate.and(
MessageTemplate.MatchSender(shipperAgent.getAID()),
MessageTemplate.and(
MessageTemplate.MatchReplyWith("response"+propose.getReplyWith()),
MessageTemplate.or(
MessageTemplate.MatchPerformative(ACLMessage.ACCEPT_PROPOSAL),
MessageTemplate.MatchPerformative(ACLMessage.REJECT_PROPOSAL)
) ) ) ;
// Read data from GUI. The user accept or reject:
ACLMessage decisionFromGUI = shipperAgent.receive(mt);
if (decisionFromGUI != null) {
ACLMessage reply = propose.createReply();
// bla bla...
finish=true;
HandleProposes.this.restart();
} else {
block();
}
}
public boolean done() {
return finish;
}
public void handleChoice(ACLMessage propose, boolean bool, Vector<Goods> selectedGoods) {
ACLMessage reply;
if (bool){
reply = new ACLMessage(ACLMessage.ACCEPT_PROPOSAL);
//...
} else {
reply = new ACLMessage(ACLMessage.REJECT_PROPOSAL);
//...
}
reply.addReceiver(shipperAgent.getAID());
reply.setReplyWith("response"+propose.getReplyWith());
shipperAgent.send(reply);
}
} // closes HandleSinglePropose
} // closes HandleProposes
}
SearchJobResponder.java
The responder is simple. The only thing of note: I extends SSContractNetResponder, don't extends ContractNetResponder.
public class SearchJobResponder extends SSContractNetResponder {
BuyerAgent buyerAgent;
public SearchJobResponder(BuyerAgent a, ACLMessage cfp) {
super(a, cfp);
buyerAgent = a;
}
/*
* override methods...
*/
}
GoodsChoiceBox.java
The GUI for show the proposals...
public GoodsChoiceBox(final Agent agent, final HandleSinglePropose behaviour, final ACLMessage propose){
/*
* graphics stuff
*/
// if goods selected and press Execute
behaviour.handleChoice(propose,true,selectedGoods);
//else
behaviour.handleChoice(propose,false,null);
/*
* bla bla
*/
}
I know, I have dwelt much, but I did not know how else to explain.
However, now my project work. But I'm open to any suggestions.
I often run into this problems of this sort. These are Finite State machine behaviours so you should be able to pause and resume a behavior but I'm not sure how. What I do is create two separate Interaction behaviors on the initiator side and one on the responder side.
Initiator Responder
| |
| |
| First behaviour |The responder only has 1 behaviour
|| CFP-> ||
|| <-Proposal ||
| ||
| Second behaviour ||
|| Accept prop-> ||
|| <-Response ||
| |
Two points to remember
(1)
Make sure that you save the conversationID
msgRecieved.getConversationID
from the first behaviour and use it in the second Behaviour.
msg.setConversationID().
(2)
The second behavior is another Contract net initiator but in prepareCFPs method set MESSAGE performative to accept proposal
class ContractServiceList extends ContractNetInitiator
{
protected Vector prepareCfps(ACLMessage cfp) {
ACLmessage AP= new ACLmessage(ACLmessage.ACCEPT_PROPOSAL)
.....
These things are hard to explain so I tried to attached a picture but have 2 little rep points.
I now have enough rep points to attach the picture which I am doing.
I just realized that there is another solution to this problem. The second solution involves using ChildBehaviours and data stores. A child behaviour can be initiated pausing the parent behaviour. The parent behaviour must then be resumed one the child is complete.
I'm attaching a pic to better explain this interaction.
So at point A in your CNI (ContractNetInitiator) parent behaviour you want to initiate the Child behaviour. You would do this by using the CNI.registerHandlePropose(new Childbehaviour).
This is what the setup() method should look like:
protected void setup()
{
ContractNetInitiator parentBehave= new ContractNetInitiator (null, null, GlobDataStore);
ContractNetInitiator.registerHandlePropose(new ChildBehavoiur (GlobDataStore));
addBehaviour(CNI);
}
In you Child behaviour you will have to check the data from the parent (GlobDataStore) and return a message to be passed back. Code to follow:
class ChildBehaviour extends OneShotBehaviour{
#Override
public void action() {
//evaluate globalestore here;
ACLMessage CNIresponse=new ACLMessage();
if(true)
{
storeNotification(ACLMessage.ACCEPT_PROPOSAL, CNIresponse);
}
else
{
storeNotification(ACLMessage.REJECT_PROPOSAL, CNIresponse);
}
}
public void storeNotification(int performative, ACLMessage original)
{
// Retrieve the incoming request from the DataStore
String incomingCFPkey = (String) ((ContractNetResponder) parent).CFP_KEY;
incomingCFPkey = (String) ((ContractNetResponder) parent).CFP_KEY;
ACLMessage incomingCFP = (ACLMessage) getDataStore().get(incomingCFPkey);
// Prepare the notification to the request originator and store it in the DataStore
ACLMessage notification = incomingCFP.createReply();
notification.setPerformative(performative);
notification.setContent(original.getContent());
String notificationkey = (String) ((ContractNetResponder) parent).PROPOSE_KEY;
getDataStore().put(notificationkey, notification);
}
}
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.
I tried to set the UsbDeviceListener but nothing happens when I disconnect the device nor when I create a new file on the device.
Can someone tell me where is the problem in my code?
public static void listPeripherique(UsbHub hub) {
List perepheriques = hub.getAttachedUsbDevices();
Iterator iterator = perepheriques.iterator();
while (iterator.hasNext()) {
UsbDevice perepherique = (UsbDevice) iterator.next();
perepherique.addUsbDeviceListener(new UsbDeviceListener() {
#Override
public void usbDeviceDetached(UsbDeviceEvent arg0) {
System.out.println("connect " + arg0);
}
#Override
public void errorEventOccurred(UsbDeviceErrorEvent arg0) {
System.out.println("disconect " + arg0);
}
#Override
public void dataEventOccurred(UsbDeviceDataEvent arg0) {
System.out.println("new data on " + arg0);
}
});
}
if (perepherique.isUsbHub()) {
listPeripherique((UsbHub) perepherique);
}
}
Edit: It's work only for usb Detached.
Do you mind giving use more details on your environment (Linux, Win, OSX) and what kind of USB device (Stick, Gamepad, DVD-Burner, Dongle, iP(a|o)d, iPhone, Smartphone)? However, if you use Windows, it seems the driver is out-of-date: JSR80: This is an ABANDONED Windows implementation. it does not work, it needs a kernel driver.
Keep us posted on your project and progress.
Edit
I tried it with my Logitech Wingman controller and I can confirm that only usbDeviceDetached events are raised. I think the driver is really outdated :(
Sounds like it is working correctly.
Your code iterates once over all currently connected devices and registers a device listener on it. When the device is disconnected then the usbDeviceDetached event is triggered. The other two events are triggered after data is transfered from or to the device by your own program or when an error occurred when your program tried to communicate with the device.
javax-usb can't monitor data transfers made by other programs. Maybe this is what you expected? For this you need a special USB monitor tool like usbmon on Linux.