I have created a service for my android app to get messages from a server, the service is working fine when calling the app normally, but when the service is started at boot it fails!
I have tried debugging it and setting the app to debugging mode on the Developers tools, but there is no logcat being displayed?? The app however does show that it is waiting for the bugger to attach before running so I know it is running on boot.
I tested on an actual device.
When the app is not in debugging mode it goes into a crashing and restarting LOOP
Hope someone could help me as I can't find the problem seeing that I am still new in android development
Below is the relevant code..
IMService.java
package com.app1.services;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.RingtoneManager;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.util.Log;
import com.app1.FriendList;
import com.app1.Login;
import com.app1.Messaging;
import com.app1.R;
import com.app1.communication.SocketOperator;
import com.app1.interfaces.IAppManager;
import com.app1.interfaces.ISocketOperator;
import com.app1.interfaces.IUpdateData;
import com.app1.tools.FriendController;
import com.app1.tools.LocalStorageHandler;
import com.app1.tools.MessageController;
import com.app1.tools.XMLHandler;
import com.app1.types.FriendInfo;
import com.app1.types.MessageInfo;
/**
* This is an example of implementing an application service that runs locally
* in the same process as the application. The {@link LocalServiceController}
* and {@link LocalServiceBinding} classes show how to interact with the
* service.
*
* <p>
* Notice the use of the {@link NotificationManager} when interesting things
* happen in the service. This is generally how background services should
* interact with the user, rather than doing something more disruptive such as
* calling startActivity().
*/
public class IMService extends Service implements IAppManager, IUpdateData {
// private NotificationManager mNM;
public static String USERNAME;
public static final String TAKE_MESSAGE = "Take_Message";
public static final String FRIEND_LIST_UPDATED = "Take Friend List";
public static final String MESSAGE_LIST_UPDATED = "Take Message List";
public ConnectivityManager conManager = null;
private final int UPDATE_TIME_PERIOD = 15000;
// private static final INT LISTENING_PORT_NO = 8956;
private String rawFriendList = new String();
private String rawMessageList = new String();
ISocketOperator socketOperator = new SocketOperator(this);
private final IBinder mBinder = new IMBinder();
public static String username;
public static String password;
private boolean authenticatedUser = false;
// timer to take the updated data from server
private Timer timer;
private LocalStorageHandler localstoragehandler;
private NotificationManager mNM;
public class IMBinder extends Binder {
public IAppManager getService() {
return IMService.this;
}
}
@Override
public void onCreate() {
mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
localstoragehandler = new LocalStorageHandler(this);
// Display a notification about us starting. We put an icon in the
// status bar.
conManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
new LocalStorageHandler(this);
// Timer is used to take the friendList info every UPDATE_TIME_PERIOD;
timer = new Timer();
Thread thread = new Thread() {
@Override
public void run() {
// socketOperator.startListening(LISTENING_PORT_NO);
Random random = new Random();
int tryCount = 0;
while (socketOperator.startListening(10000 + random
.nextInt(20000)) == 0) {
tryCount++;
if (tryCount > 10) {
// if it can't listen a port after trying 10 times, give
// up...
break;
}
}
}
};
thread.start();
///\\\ TODO GET THIS TO WORK AUTOLOG
SharedPreferences prefs = getPreferences(IMService.this);
prefs = PreferenceManager.getDefaultSharedPreferences(IMService.this);
String remUsername = prefs.getString("username", null);
String remPassword = prefs.getString("password", null);
if (remUsername != null && remPassword != null)
{
try {
authenticateUser(
remUsername.toString(),
remPassword.toString());
} catch (UnsupportedEncodingException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
}
///\\\
}
/*
* @Override public void onDestroy() { // Cancel the persistent
* notification. mNM.cancel(R.string.local_service_started);
*
* // Tell the user we stopped. Toast.makeText(this,
* R.string.local_service_stopped, Toast.LENGTH_SHORT).show(); }
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
String vAppName = getResources().getString(R.string.app_name);
Notification notification = new Notification(R.drawable.ic_action_sociochat_logo_connected, vAppName+" is starting", System.currentTimeMillis());
Intent main = new Intent(this, FriendList.class);
main.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, main, PendingIntent.FLAG_UPDATE_CURRENT);
notification.setLatestEventInfo(this, vAppName, "Connected", pendingIntent);
notification.flags |= Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE | Notification.FLAG_NO_CLEAR;
startForeground(2, notification);
return START_STICKY;
}
private SharedPreferences getPreferences(IMService imService) {
// TODO Auto-generated method stub
return null;
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/**
* Show a notification while this service is running.
*
* @param msg
**/
private void showNotification(String username, String msg) {
// define sound URI, the sound to be played when there's a notification
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
// intent triggered, you can add other intent for other actions
Intent intent = new Intent(this, Messaging.class);
intent.putExtra(FriendInfo.USERNAME, username);
intent.putExtra(MessageInfo.MESSAGETEXT, msg);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0);
// this is it, we'll build the notification!
// in the addAction method, if you don't want any icon, just set the first param to 0
Notification mNotification = new Notification.Builder(this)
.setContentTitle("New Message")
.setContentText(username + ": " + msg)
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pIntent)
.setSound(soundUri)
// The below 2 lines are only for jelly bean
//.addAction(R.drawable.ic_launcher, "View", pIntent)
//.addAction(0, "Remind", pIntent)
.build();
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// If you want to hide the notification after it was selected, do the code below
mNotification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(0, mNotification);
}
@Override
public String getUsername() {
return IMService.username;
}
@Override
public String getPassword() {
return IMService.password;
}
@Override
public String sendMessage(String username, String tousername, String message)
throws UnsupportedEncodingException {
String params = "username=" + URLEncoder.encode(IMService.username, "UTF-8")
+ "&password=" + URLEncoder.encode(IMService.password, "UTF-8")
+ "&to=" + URLEncoder.encode(tousername, "UTF-8") + "&message="
+ URLEncoder.encode(message, "UTF-8") + "&action="
+ URLEncoder.encode("sendMessage", "UTF-8") + "&";
Log.i("PARAMS", params);
return socketOperator.sendHttpRequest(params);
}
@Override
public String updateUserDetails(String username, String statusMessage, String presence)
throws UnsupportedEncodingException {
String params = "username=" + URLEncoder.encode(IMService.username.toString(), "UTF-8")
+ "&password=" + URLEncoder.encode(IMService.password.toString(), "UTF-8")
+ "&statusmessage=" + URLEncoder.encode(statusMessage, "UTF-8")
+ "&presence=" + URLEncoder.encode(presence, "UTF-8")
+ "&action=" + URLEncoder.encode("updateUserData", "UTF-8") + "&";
Log.i("PARAMS", params);
return socketOperator.sendHttpRequest(params);
}
private String getFriendList() throws UnsupportedEncodingException {
// after authentication, server replies with friendList xml
rawFriendList = socketOperator
.sendHttpRequest(getAuthenticateUserParams(username, password));
if (rawFriendList != null) {
this.parseFriendInfo(rawFriendList);
}
return rawFriendList;
}
private String getMessageList() throws UnsupportedEncodingException {
// after authentication, server replies with friendList xml
rawMessageList = socketOperator
.sendHttpRequest(getAuthenticateUserParams(username, password));
if (rawMessageList != null) {
this.parseMessageInfo(rawMessageList);
}
return rawMessageList;
}
/**
* authenticateUser: it authenticates the user and if succesful it returns
* the friend list or if authentication is failed it returns the "0" in
* string type
*
* @throws UnsupportedEncodingException
* */
@Override
public String authenticateUser(String usernameText, String passwordText)
throws UnsupportedEncodingException {
IMService.username = usernameText;
IMService.password = passwordText;
this.authenticatedUser = false;
String result = this.getFriendList(); // socketOperator.sendHttpRequest(getAuthenticateUserParams(username,
// password));
if (result != null && !result.equals(Login.AUTHENTICATION_FAILED)) {
// if user is authenticated then return string from server is not
// equal to AUTHENTICATION_FAILED
this.authenticatedUser = true;
//REMEMBER USER
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(IMService.this);
SharedPreferences.Editor editor = prefs.edit();
editor.putString("username",IMService.username);
editor.putString("password",IMService.password);
editor.commit();
//
rawFriendList = result;
USERNAME = IMService.username;
Intent i = new Intent(FRIEND_LIST_UPDATED);
i.putExtra(FriendInfo.FRIEND_LIST, rawFriendList);
sendBroadcast(i);
timer.schedule(new TimerTask() {
@Override
public void run() {
try {
// rawFriendList = IMService.this.getFriendList();
// sending friend list
Intent i = new Intent(FRIEND_LIST_UPDATED);
Intent i2 = new Intent(MESSAGE_LIST_UPDATED);
String tmp = IMService.this.getFriendList();
String tmp2 = IMService.this.getMessageList();
if (tmp != null) {
i.putExtra(FriendInfo.FRIEND_LIST, tmp);
sendBroadcast(i);
Log.i("friend list broadcast sent ", "");
if (tmp2 != null) {
i2.putExtra(MessageInfo.MESSAGE_LIST, tmp2);
sendBroadcast(i2);
Log.i("friend list broadcast sent ", "");
}
} else {
Log.i("friend list returned null", "");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}, UPDATE_TIME_PERIOD, UPDATE_TIME_PERIOD);
}
return result;
}
@Override
public void messageReceived(String username, String message) {
// FriendInfo friend = FriendController.getFriendInfo(username);
MessageInfo msg = MessageController.checkMessage(username);
if (msg != null) {
Intent i = new Intent(TAKE_MESSAGE);
i.putExtra(MessageInfo.USERID, msg.userid);
i.putExtra(MessageInfo.MESSAGETEXT, msg.messagetext);
i.putExtra(MessageInfo.SENDT, msg.sendt);
sendBroadcast(i);
String activeFriend = FriendController.getActiveFriend();
if (activeFriend == null || activeFriend.equals(username) == false) {
localstoragehandler.insert(username, this.getUsername(),
message.toString());
showNotification(username, message);
}
Log.i("TAKE_MESSAGE broadcast sent by im service", "");
}
}
private String getAuthenticateUserParams(String usernameText,
String passwordText) throws UnsupportedEncodingException {
String params = "username="
+ URLEncoder.encode(usernameText, "UTF-8")
+ "&password="
+ URLEncoder.encode(passwordText, "UTF-8")
+ "&action="
+ URLEncoder.encode("authenticateUser", "UTF-8")
+ "&port="
+ URLEncoder.encode(
Integer.toString(socketOperator.getListeningPort()),
"UTF-8") + "&";
return params;
}
public void setUserKey(String value) {
}
@Override
public boolean isNetworkConnected() {
return conManager.getActiveNetworkInfo().isConnected();
}
@Override
public boolean isUserAuthenticated() {
return authenticatedUser;
}
@Override
public String getLastRawFriendList() {
return this.rawFriendList;
}
@Override
public void onDestroy() {
Log.i("IMService is being destroyed", "...");
super.onDestroy();
}
@Override
public void exit() {
timer.cancel();
socketOperator.exit();
socketOperator = null;
this.stopSelf();
}
@Override
public String signUpUser(String usernameText, String passwordText,
String emailText) {
String params = "username=" + usernameText + "&password="
+ passwordText + "&action=" + "signUpUser" + "&email="
+ emailText + "&";
String result = socketOperator.sendHttpRequest(params);
return result;
}
@Override
public String addNewFriendRequest(String friendUsername) {
String params = "username=" + IMService.username + "&password="
+ IMService.password + "&action=" + "addNewFriend"
+ "&friendUserName=" + friendUsername + "&";
String result = socketOperator.sendHttpRequest(params);
return result;
}
@Override
public String sendFriendsReqsResponse(String approvedFriendNames,
String discardedFriendNames) {
String params = "username=" + IMService.username + "&password="
+ IMService.password + "&action=" + "responseOfFriendReqs"
+ "&approvedFriends=" + approvedFriendNames
+ "&discardedFriends=" + discardedFriendNames + "&";
String result = socketOperator.sendHttpRequest(params);
return result;
}
private void parseFriendInfo(String xml) {
try {
SAXParser sp = SAXParserFactory.newInstance().newSAXParser();
sp.parse(new ByteArrayInputStream(xml.getBytes()), new XMLHandler(
IMService.this));
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void parseMessageInfo(String xml) {
try {
SAXParser sp = SAXParserFactory.newInstance().newSAXParser();
sp.parse(new ByteArrayInputStream(xml.getBytes()), new XMLHandler(
IMService.this));
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void updateData(MessageInfo[] messages, FriendInfo[] friends,
FriendInfo[] unApprovedFriends, String userKey) {
this.setUserKey(userKey);
// FriendController.
MessageController.setMessagesInfo(messages);
// Log.i("MESSAGEIMSERVICE","messages.length="+messages.length);
int i = 0;
while (i < messages.length) {
messageReceived(messages[i].userid, messages[i].messagetext);
// appManager.messageReceived(messages[i].userid,messages[i].messagetext);
i++;
}
FriendController.setFriendsInfo(friends);
FriendController.setUnapprovedFriendsInfo(unApprovedFriends);
}
}
BootReceiver.java
package com.cyberscene.app1;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import com.app1.services.IMService;
public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
Intent pushIntent = new Intent(context, IMService.class);
context.startService(pushIntent);
}
}
}
AndroidManifest.xml
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<service android:name="com.app1.services.IMService" >
</service>
<receiver android:name=".BootReceiver" android:enabled="true" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
Finaly got logcat messages, here they are:
11-08 22:58:47.634 E/AndroidRuntime(14916): java.lang.RuntimeException: Unable to
create service com.app1.services.IMService: android.os.NetworkOnMainThreadException
11-08 22:58:47.634 E/AndroidRuntime(14916): at android.app.ActivityThread.handleCreateService(ActivityThread.java:2695)
11-08 22:58:47.634 E/AndroidRuntime(14916): at android.app.ActivityThread.access$1700(ActivityThread.java:159)
11-08 22:58:47.634 E/AndroidRuntime(14916): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1404)
11-08 22:58:47.634 E/AndroidRuntime(14916): at android.os.Handler.dispatchMessage(Handler.java:99)
11-08 22:58:47.634 E/AndroidRuntime(14916): at android.os.Looper.loop(Looper.java:137)
11-08 22:58:47.634 E/AndroidRuntime(14916): at android.app.ActivityThread.main(ActivityThread.java:5414)
11-08 22:58:47.634 E/AndroidRuntime(14916): at java.lang.reflect.Method.invokeNative(Native Method)
11-08 22:58:47.634 E/AndroidRuntime(14916): at java.lang.reflect.Method.invoke(Method.java:525)
11-08 22:58:47.634 E/AndroidRuntime(14916): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1187)
11-08 22:58:47.634 E/AndroidRuntime(14916): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
11-08 22:58:47.634 E/AndroidRuntime(14916): at dalvik.system.NativeStart.main(Native Method)
11-08 22:58:47.634 E/AndroidRuntime(14916): Caused by: android.os.NetworkOnMainThreadException
11-08 22:58:47.634 E/AndroidRuntime(14916): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1144)
11-08 22:58:47.634 E/AndroidRuntime(14916): at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:84)
11-08 22:58:47.634 E/AndroidRuntime(14916): at libcore.io.IoBridge.connectErrno(IoBridge.java:127)
11-08 22:58:47.634 E/AndroidRuntime(14916): at libcore.io.IoBridge.connect(IoBridge.java:112)
11-08 22:58:47.634 E/AndroidRuntime(14916): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
11-08 22:58:47.634 E/AndroidRuntime(14916): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:460)
11-08 22:58:47.634 E/AndroidRuntime(14916): at java.net.Socket.connect(Socket.java:832)
11-08 22:58:47.634 E/AndroidRuntime(14916): at libcore.net.http.HttpConnection.<init>(HttpConnection.java:76)
11-08 22:58:47.634 E/AndroidRuntime(14916): at libcore.net.http.HttpConnection.<init>(HttpConnection.java:50)
11-08 22:58:47.634 E/AndroidRuntime(14916): at libcore.net.http.HttpConnection$Address.connect(HttpConnection.java:340)
11-08 22:58:47.634 E/AndroidRuntime(14916): at libcore.net.http.HttpConnectionPool.get(HttpConnectionPool.java:87)
11-08 22:58:47.634 E/AndroidRuntime(14916): at libcore.net.http.HttpConnection.connect(HttpConnection.java:128)
11-08 22:58:47.634 E/AndroidRuntime(14916): at libcore.net.http.HttpEngine.openSocketConnection(HttpEngine.java:316)
11-08 22:58:47.634 E/AndroidRuntime(14916): at libcore.net.http.HttpEngine.connect(HttpEngine.java:311)
11-08 22:58:47.634 E/AndroidRuntime(14916): at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)
11-08 22:58:47.634 E/AndroidRuntime(14916): at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)
11-08 22:58:47.634 E/AndroidRuntime(14916): at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:81)
11-08 22:58:47.634 E/AndroidRuntime(14916): at libcore.net.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:197)
11-08 22:58:47.634 E/AndroidRuntime(14916): at com.cyberscene.sociochat.communication.SocketOperator.sendHttpRequest(SocketOperator.java:91)
11-08 22:58:47.634 E/AndroidRuntime(14916): at com.cyberscene.sociochat.services.IMService.getFriendList(IMService.java:284)
11-08 22:58:47.634 E/AndroidRuntime(14916): at com.cyberscene.sociochat.services.IMService.authenticateUser(IMService.java:317)
11-08 22:58:47.634 E/AndroidRuntime(14916): at com.cyberscene.sociochat.services.IMService.onCreate(IMService.java:153)
11-08 22:58:47.634 E/AndroidRuntime(14916): at android.app.ActivityThread.handleCreateService(ActivityThread.java:2685)
11-08 22:58:47.634 E/AndroidRuntime(14916): ... 10 more
11-08 22:58:47.634 I/dumpstate(14942): begin