I am facing an error during using service in android .I call an activity CallingScreenActivity which I call by intent and putting a number string to which I have make a call .
So what I did in CallingScreenActivity is first I initialize a class member like this
private boolean serviceConnected = false;
private ISipService service;
private ServiceConnection connection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName arg0, IBinder arg1) {
service = ISipService.Stub.asInterface(arg1);
try {
// Log.d(THIS_FILE,
// "Service started get real call info "+callInfo.getCallId());
Log.e("onservice connected", "on service connected");
serviceConnected = true;
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
Log.e("service disconnected", "desconnected service ");
serviceConnected = false;
}
};
then I have bind service in onCreate() like this :
bindService(new Intent(this, SipService.class), connection, Context.BIND_AUTO_CREATE);
and finally get number from intent and call a method :
private void placeCallWithOption(String number) {
if (service == null) {
Log.e("servcie is null ", "service is null");
return;
}
try {
service.makeCallWithOptions(num, 1, null);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Now my problem is every time I call this activity to make a call it calls method placeCallWithoutOption first and service connected later so every time it prints service is null in method and return then service is connected in service connected method .
How should I manage this please help ..
call this function placeCallWithOption inside onServiceConnected.
create variable in activity:
private String number;
and in onCreate of activity
number=getIntent().getStringExtra("<number_key>",null);
and in onServiceConnected
#Override
public void onServiceConnected(ComponentName arg0, IBinder arg1) {
service = ISipService.Stub.asInterface(arg1);
try {
placeCallWithOption(number);
// Log.d(THIS_FILE,
// "Service started get real call info "+callInfo.getCallId());
Log.e("onservice connected", "on service connected");
serviceConnected = true;
} catch (Exception e) {
e.printStackTrace();
}
}
You can't call any method from service before it connected. So, you can:
1) add progress dialog "Connecting service..." on activity's start
2) hide progress dialog after service connected and call placeCallWithOption() from onServiceConnected() (not early).
Related
I've implemented an action button in my android PhoneGap app Push Notification window that performs HTTP request to my server to handle server actions.
Probably we have an exception when we perform the HTTP request because it doesn't seem to work. (currently, we can't view the exception itself for reason I won't get into here)
We implemented by calling the HTTP request in a different thread because we saw answers here in Stackoverflow that you can't implement calling the HTTP request on the main thread.
Any help will be appreciated.
This is my BroadcastReceiver class:
public class ExpressPayRequest extends BroadcastReceiver{
#Override
public void onReceive(Context Context, Intent arg1) {
Context.startService(new Intent(Context, PostRequestService.class));
}
}
And the service looks like this:
public class PostRequestService extends Service{
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try{
URL url = new URL("http://someGETRequest");
HttpURLConnection client = (HttpURLConnection)url.openConnection();
int responseCode = client.getResponseCode();
}
catch(IOException e){
Log.e("LOGEntry", "error log: " + e.getMessage(),e);
}
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
}
I have figured it out myself
if anyone interested the solution was creating a new thread instead of starting a new service
this is the code I used:
Thread thread = new Thread(){
public void run(){
try{
URL url = new URL("http://test");
HttpURLConnection client = (HttpURLConnection)url.openConnection();
client.connect();
int responseCode = client.getResponseCode();
} catch (IOException e) {
e.printStackTrace();
}
}
};
thread.start();
I am trying to set up iAP for a Premium membership.
I've added my app and my signed apk to the developer console and then I started following this example: Implementing In-app Billing
I've noticed a tricky part that says:
Warning: Do not call the getSkuDetails method on the main thread. Calling this method triggers a network request which could block your main thread. Instead, create a separate thread and call the getSkuDetails method from inside that thread.
so this is the code I wrote:
public class class...
Bundle querySkus = new Bundle();
/** gestisce gli acquisti in app */
IInAppBillingService mService;
ServiceConnection mServiceConn = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = IInAppBillingService.Stub.asInterface(service);
}
#Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
};
and in my onCreate() method:
Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
serviceIntent.setPackage("com.android.vending");
bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
ArrayList<String> skuList = new ArrayList<String>();
skuList.add("premiumUpgrade");
querySkus.putStringArrayList("chords_premium", skuList);
AsyncTask.execute(new Runnable() {
#Override
public void run() {
Bundle skuDetails = mService.getSkuDetails(3, getPackageName(), "inapp", querySkus);
}
});
now on Bundle skuDetails = mService.getSkuDetails(3, getPackageName(), "inapp", querySkus); I'm getting:
Unhandled Exception: android.os.RemoteException
First of all, how do I fix it?
I'm implementing this code in my main activity even though the button the should redirect to the buying dialog is in another activity. Am I doing it right? Do I need to pass it to the other Activity? if so, how? Is it better that I put the whole code that handles iAP inside the specific activity?
**EDIT: **
I've tried to catch the exception like this:
AsyncTask.execute(new Runnable() {
#Override
public void run() {
try {Bundle skuDetails = mService.getSkuDetails(3, getPackageName(), "inapp", querySkus); }
catch (RemoteException e) {e.printStackTrace();};
}
});
It won't work becuase I cannot set int response = skuDetails... (in the doc linked above)
Haven't tested your code.. but I think you can try this:
AsyncTask.execute(new Runnable() {
#Override
public void run() {
Bundle skuDetails = null;
try {
skuDetails = mService.getSkuDetails(3,
getPackageName(), "inapp", querySkus);
} catch (RemoteException e) {
e.printStackTrace();
}
int response = skuDetails.whateverYouWantToDoWithThis();
}
});
OR
AsyncTask.execute(new Runnable() {
#Override
public void run() throws RemoteException {
Bundle skuDetails = mService.getSkuDetails(3,
getPackageName(), "inapp", querySkus);
int response = skuDetails.whateverYouWantToDoWithThis();
}
});
Read more about throws vs try-catch here: try/catch versus throws Exception
I am trying to send a notification in an thread, but it somehow does not work.
public void start_progressbar(View v) {
final ProgressDialog pd = ProgressDialog.show(this,
"Sending Notification", "Working... ", true, false);
new Thread() {
public void run() {
try {
sleep(3000);
notification();
} catch (Exception e) {
final String ERROR = e.toString();
Log.e(TAG + "He's dead Jim!!", "" + e);
}
pd.dismiss();
}
private void notification() {
// TODO Auto-generated method stub
Notification not = new NotificationCompat.Builder(this)
.setContentTitle("New Event")
.setContentText("Monday 12. 11. 2014 meeting")
.build();
}
}.start();
}
In an inner class, use OuterClassName.this to refer to the outer class instance. this alone refers to the inner class instance i.e. the anonymous Thread subclass in your case.
I am writing an IRC Client. The socket connection to the IRC Server is handled via a service. I have managed to stabilize all the UI elements of the Activities in question during the orientation change, but somehow the socket that is maintained by the service is being closed during the change.
Here is what I believe to be the relevant code. Please let me know if you need to see more.
//This is the Service in question
public class ConnectionService extends Service{
private BlockingQueue<String> MessageQueue;
public final IBinder myBind = new ConnectionBinder();
public class ConnectionBinder extends Binder {
ConnectionService getService() {
return ConnectionService.this;
}
}
private Socket socket;
private BufferedWriter writer;
private BufferedReader reader;
private IRCServer server;
private WifiManager.WifiLock wLock;
private Thread readThread = new Thread(new Runnable() {
#Override
public void run() {
try {
String line;
while ((line = reader.readLine( )) != null) {
if (line.toUpperCase().startsWith("PING ")) {
SendMessage("PONG " + line.substring(5));
}
else
queueMessage(line);
}
}
catch (Exception e) {}
}
});
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(MessageQueue == null)
MessageQueue = new LinkedBlockingQueue<String>();
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
return myBind;
}
#Override
public boolean stopService(Intent name) {
try {
socket.close();
wLock.release();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return super.stopService(name);
}
#Override
public void onDestroy()
{//I put this here so I had a breakpoint in place to make sure this wasn't firing instead of stopService
try {
socket.close();
wLock.release();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
super.onDestroy();
}
public void SendMessage(String message)
{
try {
writer.write(message + "\r\n");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public String readLine()
{
try {
if(!isConnected())
return null;
else
return MessageQueue.take();
} catch (InterruptedException e) {
return "";
}
}
public boolean ConnectToServer(IRCServer newServer)
{
try {
//create a new message queue (connecting to a new server)
MessageQueue = new LinkedBlockingQueue<String>();
//lock the wifi
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, "LockTag");
wLock.acquire();
server = newServer;
//connect to server
socket = new Socket();
socket.setKeepAlive(true);
socket.setSoTimeout(60000);
socket.connect(new InetSocketAddress(server.NAME, Integer.parseInt(server.PORT)), 10000);
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//run basic login scripts.
if(server.PASS != "")
SendMessage("PASS " + server.PASS);
//write nickname
SendMessage("NICK " + server.NICK);
//write username login
SendMessage("USER " + server.NICK + " 0 * :Fluffy IRC");
String line;
while ((line = reader.readLine( )) != null) {
if (line.indexOf("004") >= 0) {
// We are now logged in.
break;
}
else if (line.indexOf("433") >= 0) {
//change to alt Nick
if(!server.NICK.equals(server.ALT_NICK) && !server.ALT_NICK.equals(""))
{
server.NICK = server.ALT_NICK;
SendMessage("NICK " + server.NICK);
}
else
{
queueMessage("Nickname already in use");
socket.close();
return false;
}
}
else if (line.toUpperCase().startsWith("PING ")) {
SendMessage("PONG " + line.substring(5));
}
else
{
queueMessage(line);
}
}
//start the reader thread AFTER the primary login!!!
CheckStartReader();
if(server.START_CHANNEL == null || server.START_CHANNEL == "")
{
server.WriteCommand("/join " + server.START_CHANNEL);
}
//we're done here, go home everyone
} catch (NumberFormatException e) {
return false;
} catch (IOException e) {
return false;
}
return true;
}
private void queueMessage(String line) {
try {
MessageQueue.put(line);
} catch (InterruptedException e) {
}
}
public boolean isConnected()
{
return socket.isConnected();
}
public void CheckStartReader()
{
if(this.isConnected() && !readThread.isAlive())
readThread.start();
}
}
//Here are the relevant portions of the hosting Activity that connects to the service
//NOTE: THE FOLLOWING CODE IS PART OF THE ACTIVITY, NOT THE SERVICE
private ConnectionService conn;
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
conn = ((ConnectionService.ConnectionBinder)service).getService();
Toast.makeText(main_tab_page.this, "Connected", Toast.LENGTH_SHORT)
.show();
synchronized (_serviceConnWait) {
_serviceConnWait.notify();
}
}
#Override
public void onServiceDisconnected(ComponentName name) {
conn = null;
}
};
#Override
protected void onSaveInstanceState(Bundle state){
super.onSaveInstanceState(state);
state.putParcelable("Server", server);
state.putString("Window", CurrentTabWindow.GetName());
unbindService(mConnection);
}
#Override
protected void onDestroy()
{
super.onDestroy();
if(this.isFinishing())
stopService(new Intent(this, ConnectionService.class));
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_tab_page);
localTabHost = (TabHost)findViewById(R.id.tabHostMain);
localTabHost.setup();
localTabHost.setOnTabChangedListener(new tabChange());
_serviceConnWait = new Object();
if(savedInstanceState == null)
{//initial startup, coming from Intent to start
//get server definition
server = (IRCServer)this.getIntent().getParcelableExtra(IRC_WINDOW);
server.addObserver(this);
AddTabView(server);
startService(new Intent(this, ConnectionService.class));
}
else
{
server = (IRCServer)savedInstanceState.getParcelable("Server");
String windowName = savedInstanceState.getString("Window");
//Add Needed Tabs
//Server
if(!(windowName.equals(server.GetName())))
AddTabView(server);
//channels
for(IRCChannel c : server.GetAllChannels())
if(!(windowName.equals(c.GetName())))
AddTabView(c);
//reset each view's text (handled by tabChange)
if(windowName.equals(server.GetName()))
SetCurrentTab(server.NAME);
else
SetCurrentTab(windowName);
ResetMainView(CurrentTabWindow.GetWindowTextSpan());
//Rebind to service
BindToService(new Intent(this, ConnectionService.class));
}
}
#Override
protected void onStart()
{
super.onStart();
final Intent ServiceIntent = new Intent(this, ConnectionService.class);
//check start connection service
final Thread serverConnect = new Thread(new Runnable() {
#Override
public void run() {
if(!BindToService(ServiceIntent))
return;
server.conn = conn;
conn.ConnectToServer(server);
server.StartReader();
if(server.START_CHANNEL != null && !server.START_CHANNEL.equals(""))
{
IRCChannel chan = server.FindChannel(server.START_CHANNEL);
if(chan != null)
{
AddTabView(chan);
}
else
{
server.JoinChannel(server.START_CHANNEL);
chan = server.FindChannel(server.START_CHANNEL);
AddTabView(chan);
}
}
}
});
serverConnect.start();
}
private boolean BindToService(Intent ServiceIntent)
{
int tryCount = 0;
bindService(ServiceIntent, mConnection, Context.BIND_AUTO_CREATE);
while(conn == null && tryCount < 10)
{
tryCount++;
try {
synchronized (_serviceConnWait) {
_serviceConnWait.wait(1500);
}
}
catch (InterruptedException e) {
//do nothing
}
}
return conn != null;
}
Im not entirely certain what I am doing wrong there. Obviously there's something I'm missing, haven't found yet, or haven't even thought to check. What happens though is that after the orientation change my Send command gives me this message and nothing happens:
06-04 22:02:27.637: W/System.err(1024): java.net.SocketException: Socket closed
06-04 22:02:27.982: W/System.err(1024): at com.fluffyirc.ConnectionService.SendMessage(ConnectionService.java:90)
I have no idea when the socket is getting closed, or why.
Update
I have changed the code so that rather than binding to the service and using that to start it, instead I call startService and stopService at appropriate points as well as binding to it, on the thought that the service was being destroyed when the binding was lost. This is working exactly like it was before I changed it. The socket still closes on an orientation change, and I have no idea why.
Update :- Code and description
I added the code changes recently made for Start/Stop service and START_STICKY. I also recently read a very good article explaining how the orientation change process flow works and why its NOT a bad idea to add the android:configChanges="orientation|screenSize" line to your manifest. So this fixed the orientation issue, but its still doing the same thing if I put the activity into background mode, and then bring it back to the foreground. That still follows the same Save/Destroy/Create process that the orientation does without that manifest line...and it still closes my socket, and I still don't know why.
I do know that it doesn't close the socket until the re-create process...I know this because the message queue will display messages that were received while the app was in the background, but once I bring it back forward it closes the socket and nothing else can be sent or received.
'Socket closed' means that you closed the socket and then continued to use it. It isn't a 'disconnect'.
You need to put something into that catch block. Never just ignore an exception. You might get a surprise when you see what the exception actually was.
NB Socket.isConnected() doesn't tell you anything about the state of the connection: only whether you have ever connected the Socket. You have, so it returns true.
As I can refresh the content of an activity?, for example, I have a menu and a button send me an application content that displays information online, but to go back and return again, the information is not updated.
This is my Activity.
public class Bovalpo extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bovalpo);
Button buttonExit = (Button)this.findViewById(R.id.cerrar);
buttonExit.setOnClickListener(
new View.OnClickListener() {
public void onClick(View v) {
System.exit(0);
}
}
);
TextView myListView = (TextView) findViewById(R.id.tv);
try {
myListView.setText(getPage());
if(getPage().contains("Abierto")){
myListView.setTextColor(Color.parseColor("#008000"));
}else{
myListView.setTextColor(Color.parseColor("#FF0000"));
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private String getPage() throws MalformedURLException, IOException {
HttpURLConnection con = (HttpURLConnection) new URL("http://www.bovalpo.com/cgi-local/xml_bcv.pl?URL=1").openConnection();
con.connect();
if (con.getResponseCode() == HttpURLConnection.HTTP_OK) {
return inputStreamToString(con.getInputStream());
} else {
return null;
}
}
private String inputStreamToString(InputStream in) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in));
StringBuilder stringBuilder = new StringBuilder();
String line = null;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append("Mercado: " + line + "\n");
}
bufferedReader.close();
return stringBuilder.toString();
}
public void lanzar(View view){
Intent i = new Intent(this, xml7009.class);
startActivity(i);
}
public void lanzar3(View view){
Intent i = new Intent(this, tabla7009.class);
startActivity(i);
}
public void lanzar4(View view){
Intent i = new Intent(this, xml6503.class);
startActivity(i);
}
public void onClick(View arg0) {
// TODO Auto-generated method stub
finish();
}
}
put your code here
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
// make your work to data bind
}
The code that fetches your data and sets list view color should be put in onResume() instead of onCreate if you want it to run each time your Activity is shown.
Simply you can put your update code in the onResume() method of the activity. OnResume() method will be called when ever you return from the other activity.
But onResume() method is often called when your activity is resume for example. If you open and dismiss the dialog then your activity will be Resume. SO if you are calling some network call in onResume then it will consume the process and Network speed.
The alternate solution is use startActivityForResult() method to receive the result from the next activity and bases of the activity result you can call your web API or any work. You can get the result of the next activity in onActivityResult() method.
But before using the startActivityForResult method ensure that the next activity will set the result by calling setResult() method.
If you want to update your data every time you came to activity, you need to set your updated values in onResume
like below
#Override
protected void onResume() {
super.onResume();
try {
myListView.setText(getPage());
if(getPage().contains("Abierto")){
myListView.setTextColor(Color.parseColor("#008000"));
}else{
myListView.setTextColor(Color.parseColor("#FF0000"));
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}