Delay application close and make an send a message - android

Actually i have a TCP Client that onStart connect to the server and send the device IP and number to it, but now i want that when the application is getting closed ( onDestroy ) delay it for some seconds ( the right time to reopen the connection and send another message ) and send another message in which i'm saying that the device is offline.
I've tryed to do it onDestroy method but probably it's madness and obviously
that didn't worked ( i tryed to do the following stuff onDestroy :
protected void onDestroy() {
new ConnectTask().execute("");
if (client != null) {
client.sendMessage(trm + "OFFLINE");
}
if (client != null) {
client.stopClient();
}
super.onDestroy();
server.onDestroy();
}
Here is my MainActivity code where i evocate the TCP Client and sending start message:
public class MainActivity extends AppCompatActivity {
Server server;
static Client client;
settings Settings;
public static TextView terminale, indr, msg;
TextView log;
static TextView msgServer;
static String ipp;
static String trm;
static DataBaseHandler myDB;
allert Allert;
SharedPreferences prefs;
String s1 = "GAB Tamagnini SRL © 2017 \n" +
"Via Beniamino Disraeli, 17,\n" +
"42124 Reggio Emilia \n" +
"Telefono: 0522 / 38 32 22 \n" +
"Fax: 0522 / 38 32 72 \n" +
"Partita IVA, Codice Fiscale \n" +
"Reg. Impr. di RE 00168780351 \n" +
"Cap. soc. € 50.000,00 i.v. \n" + "" +
"REA n. RE-107440 \n" +
"presso C.C.I.A.A. di Reggio Emilia";
ImageButton settings, helps, allerts, home;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Utils.darkenStatusBar(this, R.color.colorAccent);
server = new Server(this);
myDB = DataBaseHandler.getInstance(this);
msg = (TextView) findViewById(R.id.msg);
log = (TextView) findViewById(R.id.log_avviso);
settings = (ImageButton) findViewById(R.id.impo);
helps = (ImageButton) findViewById(R.id.aiut);
allerts = (ImageButton) findViewById(R.id.msge);
home = (ImageButton) findViewById(R.id.gab);
terminale = (TextView) findViewById(R.id.terminal);
indr = (TextView) findViewById(R.id.indr);
msgServer = (TextView) findViewById(R.id.serverMSG);
final Cursor cursor = myDB.fetchData();
if (cursor.moveToFirst()) {
do {
indr.setText(cursor.getString(1));
terminale.setText(cursor.getString(2));
Client.SERVER_IP = cursor.getString(1);
trm = cursor.getString(2);
} while (cursor.moveToNext());
}
startService(new Intent(MainActivity.this,FinalizingOperationsService.class));
WifiManager wm = (WifiManager) getSystemService(WIFI_SERVICE);
ipp = Formatter.formatIpAddress(wm.getConnectionInfo().getIpAddress());
startConnection.postDelayed(runnableConnection,5000);
startMessage.postDelayed(runnableMessage,5500);
cursor.close();
server.Parti();
home.setOnClickListener(new View.OnClickListener() {
int counter = 0;
#Override
public void onClick(View view) {
counter++;
if (counter == 10) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setCancelable(true);
builder.setMessage(s1);
builder.show();
counter = 0;
}
}
});
settings.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent impostazioni = new Intent(getApplicationContext(), settingsLogin.class);
startActivity(impostazioni);
}
});
helps.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent pgHelp = new Intent(getApplicationContext(), help.class);
startActivity(pgHelp);
}
});
allerts.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Server.count = 0;
SharedPreferences prefs = getSharedPreferences("MY_DATA", MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.clear();
editor.apply();
msg.setVisibility(View.INVISIBLE);
Intent pgAlert = new Intent(getApplicationContext(), allert.class);
startActivity(pgAlert);
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
server.onDestroy();
}
public static class ConnectTask extends AsyncTask<String, String, Client> {
#Override
protected Client doInBackground(String... message) {
client = new Client(new Client.OnMessageReceived() {
#Override
public void messageReceived(String message) {
publishProgress(message);
}
});
client.run();
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
msgServer.setTextColor(Color.parseColor("#00FF00"));
msgServer.setText("ONLINE");
Log.d("test", "response " + values[0]);
}
}
static Handler startConnection = new Handler();
static Runnable runnableConnection = new Runnable() {
#Override
public void run() {
new ConnectTask().execute("");
}
};
static Handler startMessage = new Handler();
static Runnable runnableMessage = new Runnable() {
#Override
public void run() {
final Cursor cursor = myDB.fetchData();
if (cursor.moveToFirst()) {
do {
Client.SERVER_IP = cursor.getString(1);
trm = cursor.getString(2);
} while (cursor.moveToNext());
}
if (client != null) {
client.sendMessage(ipp + "#" + trm);
}
}
};
static Handler startMessageClose = new Handler();
static Runnable runnableMessageClose = new Runnable() {
#Override
public void run() {
if (client != null) {
client.sendMessage(trm + "IS OFFLINE");
}
}
};
}
The right command for open the connection is new ConnectTask().execute("");
while i'm sending the message with if (client != null) { client.sendMessage(ipp + "#" + trm); }
FinalizingOperationsService.java code:
public class FinalizingOperationsService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("FOService", "Service Started");
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("FOService", "Service Destroyed");
}
#Override
public void onTaskRemoved(Intent rootIntent) {
Log.e("FOService", "Service Ends");
MainActivity.startConnection.removeCallbacks(MainActivity.runnableConnection);
MainActivity.startConnection.postDelayed(MainActivity.runnableConnection,100);
MainActivity.startMessageClose.removeCallbacks(MainActivity.runnableMessageClose);
MainActivity.startMessageClose.postDelayed(MainActivity.runnableMessageClose,110);
stopSelf();
}
}

Create a new service like this,
public class FinalizingOperationsService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("FOService", "Service Started");
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("FOService", "Service Destroyed");
}
#Override
public void onTaskRemoved(Intent rootIntent) {
Log.e("FOService", "Service Ends");
// write server updation code here
// after completing code perform stopself() to stop this service;
}
}
And define this service in manifest file like this,
<service android:name=". FinalizingOperationsService" android:stopWithTask="false"/>
Finally start service in onCreate method of your main activity
startService(newIntent(getContext(),FinalizingOperationsService.class));
Explanation:
onTaskRemoved() method of the service is called when application is killed or destroyed, so in this method you can perform your final operations to notify server and stop your service after operations done. Hope it will help you.

Related

Service still running despite the App is killed

I am trying to understand the difference bwtettn STICKY and NOT_STICKY intent of a service in onStartCommand().
I created the MainActivity and the Service shown in the code below. I expected when I press the button mBtnStopApp, the onDestroy() wil be called and then
I should receive this log ** Log.w(TAG, SubTag.bullet("++++++++ SERVICE IS NOT RUNNING ++++++++")); **
because onStartCommand() returns NOT_STICKY intnet which means, when the App is killed, the service should also be stopped
but that never happens.
what happens is, when i press the button mBtnStopApp, the App is finished but i receive the following log:
** Log.w(TAG, SubTag.bullet("++++++++ SERVICE IS RUNNING ++++++++")); **
please let me know why the service is still running despite it returns START_NOT_STICKY and the App was killed
MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private TextView mTv = null;
private Button mBtnStartStickyService = null;
private Button mBtnStartNonStickyService = null;
private Button mBtnStopApp = null;
private Button mBtnStopNonStickyService = null;
private Button mBtnStopStickyService = null;
private ServicesUtils mServiceUtils = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.w(TAG, SubTag.bullet("#onCreate"));
this.mServiceUtils = new ServicesUtils(this);
this.mBtnStartNonStickyService = (Button) findViewById(R.id.btnNonStickyService);
this.mBtnStartStickyService = (Button) findViewById(R.id.btnStickyService);
this.mBtnStopApp = (Button) findViewById(R.id.btnStopApp);
this.mBtnStopNonStickyService = (Button) findViewById(R.id.btnStopNonStickyService);
this.mBtnStopStickyService = (Button) findViewById(R.id.btnStopStickyService);
this.mTv = (TextView) findViewById(R.id.tv);
this.mBtnStartNonStickyService.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ComponentName componentName = startService(setRunningStateForService(NonStickyService.class, "start"));
Log.i(TAG, "#mBtnStartNonStickyService: componentName: " + componentName);
}
});
this.mBtnStopNonStickyService.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ComponentName componentName = startService(setRunningStateForService(NonStickyService.class, "stop"));
Log.i(TAG, "#mBtnStopNonStickyService: componentName: " + componentName);
}
});
this.mBtnStopApp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
}
private Intent setRunningStateForService(Class<NonStickyService> serviceClass, String state) {
Log.w(TAG, SubTag.bullet("#setRunningStateForService"));
Intent intent = new Intent(this, serviceClass);
intent.putExtra("running", state);
return intent;
}
#Override
protected void onDestroy() {
super.onDestroy();
Log.w(TAG, SubTag.bullet("#onDestroy"));
if (this.isNonStickyServiceRunning()) {
Log.w(TAG, SubTag.bullet("++++++++ SERVICE IS RUNNING ++++++++"));
} else {
Log.w(TAG, SubTag.bullet("++++++++ SERVICE IS NOT RUNNING ++++++++"));
}
}
private boolean isNonStickyServiceRunning() {
ActivityManager manager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (NonStickyService.class.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
}
code:
public class NonStickyService extends Service {
private static final String TAG = NonStickyService.class.getSimpleName();
private HeavyWorkRunnable mHeavyWorkRunnable = null;
private String running = null;
#Override
public void onCreate() {
super.onCreate();
Log.w(TAG, SubTag.bullet("#onCreate"));
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.w(TAG, SubTag.bullet("#onStartCommand"));
running = intent.getStringExtra("running");
if (running != null && !running.isEmpty() && running.equals("start")) {
this.StartHeavyWorkThread();
}
return Service.START_NOT_STICKY;
}
private void StartHeavyWorkThread() {
Log.w(TAG, SubTag.bullet("#StartHeavyWorkThread"));
this.mHeavyWorkRunnable = new HeavyWorkRunnable();
new Thread(this.mHeavyWorkRunnable).start();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
Log.w(TAG, SubTag.bullet("#onBind"));
return null;
}
#Override
public void onDestroy() {
Log.w(TAG, SubTag.bullet("#onDestroy"));
super.onDestroy();
this.running = "stop";
}
class HeavyWorkRunnable implements Runnable {
int counter = 0;
private Bundle b = null;
public void run() {
Log.w(TAG,SubTag.bullet("#HeavyWorkRunnable"));
while(running.equals("start")) {
b = new Bundle();
b.putInt("what", ++counter);
Log.w(TAG,SubTag.bullet("#HeavyWorkRunnable: counter: " + counter));
Log.w(TAG,SubTag.bullet("#HeavyWorkRunnable: b.getInt('what'): " + b.getInt("what")));
Message msg = handler.obtainMessage();
msg.setData(b);
handler.sendMessage(msg);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Log.i(TAG,SubTag.bullet("NonStickyService will Stop"));
stopSelf();
}
}
android.os.Handler handler = new android.os.Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
int what = msg.getData().getInt("what");
Log.w(TAG,SubTag.bullet("#handler: what: " + what));
}
};
}

Application will be slow when service runs in the background

I am using a service in my application in order to get data from the server and save received data in my local database.
But when I am using the application and my service will run in the background the application works too slow.
This is my service class that I used:
public class InternetService extends Service implements Loader.OnLoadCompleteListener<Cursor> {
public static final int notify = 5 * 60 * 60 * 1000; //interval between two services(Here Service run every 1 Minute)
private Handler mHandler = new Handler(); //run on another Thread to avoid crash
private Timer mTimer = null; //timer handling
private ArrayList<FileModel> failedIDDownloads = new ArrayList<>();
private static final String TAG = "BroadcastService";
public static final String BROADCAST_ACTION = "my_package";
Intent intent;
int counter = 0;
private CursorLoader cursorLoader;
private EncycDatabase encycDB;
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
intent = new Intent(BROADCAST_ACTION);
}
#Override
public void onStart(Intent intent, int startId) {
cursorLoader = new CursorLoader(this, Uri.parse(EncycDatabase.CONTENT_PROVIDER_URL),
null, null, null, null);
cursorLoader.registerListener(1, this);
cursorLoader.startLoading();
mHandler.removeCallbacks(sendUpdatesToUI);
mHandler.postDelayed(sendUpdatesToUI, 1000); // 1 second
}
#Override
public void onDestroy() {
super.onDestroy();
// Stop the cursor loader
if (cursorLoader != null) {
cursorLoader.unregisterListener(this);
cursorLoader.cancelLoad();
cursorLoader.stopLoading();
}
}
#Override
public void onLoadComplete(Loader<Cursor> loader, Cursor cursor) {
encycDB = new EncycDatabase();
try {
while (cursor.moveToNext()) {
G.TOKEN = (cursor.getString(cursor.getColumnIndex("user_session_token")));
}
populateEncyclopediaData();
Thread searchTagThread = new Thread(new Runnable() {
#Override
public void run() {
populateSearchTagsEncyc();
populateSearchTags();
}
});
G.handler.postDelayed(new Runnable() {
#Override
public void run() {
checkForDownloadFiles();
}
},10 *60* 1000);
searchTagThread.start();
} catch (Exception e) { //When happened an error in getting Token!
e.printStackTrace();
}
}
private void populateEncyclopediaData() {
final APIService service = ServiceGenerator.createService(APIService.class,
new PreferenceManager(G.context).getLastUpdateForEncyclopediaData(), G.TOKEN);
service.getLastChanges()
.subscribeOn(Schedulers.newThread())
.observeOn(Schedulers.io())
.subscribe(new Observer<Response<ArrayList<ServerLastChangesModel>>>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(Response<ArrayList<ServerLastChangesModel>> response) {
Log.i("LOGO_Encycloedia", "Request code: " + response.code());
if (response.code() == 200) {
G.encyclopediaArray.clear();
for (int i = 0; i < response.body().size(); i++) {
EncyclopediaModel lcModel = new EncyclopediaModel();
lcModel.setEncyclopedia_id(response.body().get(i).getEncyclopediaId());
lcModel.setEncyclopedia_title(response.body().get(i).getEncyclopediaTitle());
lcModel.setEncyclopedia_modified_date(response.body().get(i).getEncyclopediaModifiedDate());
lcModel.setEncyclopedia_deleted(response.body().get(i).getEncyclopediaDeleted());
lcModel.setEncyclopedia_content_id(response.body().get(i).getEncyclopediaContentId());
lcModel.setEncyclopedia_out_desc_text_id(response.body().get(i).getEncyclopediaOutDescTextId());
lcModel.setEncyclopedia_in_desc_text_id(response.body().get(i).getEncyclopediaInDescTextId());
lcModel.setEncyclopedia_order_in_parent(response.body().get(i).getEncyclopediaOrderInParent());
lcModel.setEncyclopedia_parent_id(response.body().get(i).getEncyclopediaParentId());
lcModel.setEncyclopedia_is_inline_parent(response.body().get(i).getEncyclopediaIsInlineParent());
lcModel.setEncyclopedia_style_sheet(response.body().get(i).getEncyclopediaStyleSheet());
G.encyclopediaArray.add(lcModel);
}
}
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
try {
encycDB.insertIntoEncyclopediaDB(G.encyclopediaArray);
new PreferenceManager(G.context).writeLastUpdateForEncyclopediaData();
} catch (Exception e) {
e.printStackTrace();
}
populateContentData(encycDB.getContentIdsFromEncyclopedia());
}
});
}
As you can see, I used threads, but it doesn't help!
I can't find out where is the problem.
The Service runs in background but it runs on the Main Thread of the application. And IntentService runs on separate worker thread.
Move your code to IntentService.

Update android Textview continuously

I am working on an Android Application which have an one activity class and service class. In service, Continuous bulk data (1090 bytes) will be received every 10 milliseconds. I need to update the text view continuously with these bulk data. What is recommended way to update Text view from a continuous background service?
Service Class
public class RecepService extends Service {
public static Handler mHandler;
StringBuilder hexstring;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
init();
}
private void init() {
mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
if (msg.what == 0x123) {
byte[] readBuf = (byte[]) msg.obj;
int readBuflen = msg.arg1;
// here will receive 1090 bytes of data
// every 10 milliseconds
Receivepatientattributes(readBuf,readBuflen);
}
}
};
}
public void Receivepatientattributes(byte[] readBuf, int len) {
String total_data = "";
total_data = bytetohex(readBuf, len);
MainActivity.recep.setText(MainActivity.recep.getText().toString() + "\t" +
"" + total_data );
}
String bytetohex(byte[] txt, int len) {
String p="";
byte[] text = new byte[len];
text = txt;
hexstring = new StringBuilder();
for (int j = 0; j < len; j++) {
String hex= Integer.toHexString(0xFF & txt[j]);
if (hex.length()==1) {
hexstring.append("0");
}
hexstring.append(hex+" ");
}
p=p+hexstring.toString();
return p;
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
}
If you want to use Schedule and timer task then you can See My Answer
To solve current issue follow this bellow instructions.
Suppose your activity has a Broadcast Receiver
private BroadcastReceiver mReceiver;
Then you override methods onResume() where your broadcast receiver will be registered and also onPause() where will your receiver be unregistered:
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
IntentFilter intentFilter = new IntentFilter(
"android.intent.action.MAIN");
mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//extract your message from intent
String msg_for_me = intent.getStringExtra("YOUR_MESSAGE");
//log your message value
Log.i("MyTag", msg_for_me);
}
};
//registering your receiver
this.registerReceiver(mReceiver, intentFilter);
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
//unregister your receiver
this.unregisterReceiver(this.mReceiver);
}
Here the broadcast receiver is filtered via android.intent.action.MAIN and from Service the message will BroadCast using this filter
Now your Method Receivepatientattributes will like this :
public void Receivepatientattributes(byte[] readBuf, int len) {
String total_data = "";
total_data = bytetohex(readBuf, len);
Intent i = new Intent("android.intent.action.MAIN").putExtra("YOUR_MESSAGE", total_data);
this.sendBroadcast(i);
}
Thats it. :)
User LocalBroadcastManager
public void Receivepatientattributes(byte[] readBuf, int len) {
String total_data = "";
total_data = bytetohex(readBuf, len);
Intent intent = new Intent("update-text");
// add data
intent.putExtra("message", total_data);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
In MainActivity
#Override
public void onResume() {
super.onResume();
// Register mMessageReceiver to receive messages.
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("update-text"));
}
private boolean mCanBeUpdated = true;
private static final int ONE_SEC = 1000; //ms
private static final int RECEPTION_SPEED = 10; //ms
private static final int CYCLES = (int) (ONE_SEC / RECEPTION_SPEED);
private int mCurrentCycle = -1;
private String mMsgCache = "";
// handler for received Intents for the "update-text" event
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Extract data included in the Intent
String message = intent.getStringExtra("message");
Log.d("receiver", "Got message: " + message);
mMsgCache = mMsgCache + "\t" + message;
if (mCanBeUpdated) {
// No problem updating UI here, refer --> http://stackoverflow.com/a/5676888/1008278
final Handler handler = new Handler(context.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
MainActivity.recep.append(mMsgCache);
mMsgCache = "";
}
});
mCanBeUpdated = false;
} else if (mCurrentCycle >= CYCLES) {
mCurrentCycle = -1;
mCanBeUpdated = true;
} else {
mCurrentCycle++;
}
}
};
#Override
protected void onPause() {
// Unregister since the activity is not visible
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
super.onPause();
}
Reference
You can use Timer for Continously updating your textview.
Set value in preferences every time when your service is running with the latest value.
Now in Timer get that value from preferences and update your TextView with that value.
Here is some code :
class UpdateTimeTask extends TimerTask {
public void run() {
textview.setText("updated value");
}
}
Set in onCreate ();
Timer timer = new Timer();
UpdateTimeTask UpdateTimeTask = new UpdateTimeTask ();
timer.schedule(UpdateTimeTask, 1000);
Use handler beacuse A Handler allows communicating back with UI thread from other background thread.
boolean handlerStop = false;
void handleHandler(){
Handler handler =new Handler();
final Runnable r = new Runnable() {
public void run() {
handler.postDelayed(this, 30000);
if(!handlerStop) {
updateTextView() //update your text with other thread like asyncronous thread
}
}
};
handler.postDelayed(r, 0000);
}
#Override
public void onResume() {
super.onResume();
handlerStop=false;
handleHandler();
}
#Override
public void onPause() {
super.onPause();
handlerStop=true;
handleHandler();
}
#Override
public void onStop() {
super.onStop();
handlerStop=true;
handleHandler();
}

Discovering local server connection via LAN using Android

I am trying to discover local server(apache tomcat) running on http://localhost:8080 through my android device.To achieve that i thought of using jmdns library from heere
but i am really confused about how to proceed with as i don't understand the networking much.
here is the codei have written with little googling but any help would a be a great help.
public class DnssdDiscovery extends Activity {
protected static final String TAG = DnssdDiscovery.class.getSimpleName();
android.net.wifi.WifiManager.MulticastLock lock;
android.os.Handler handler = new android.os.Handler();
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
handler.postDelayed(new Runnable() {
public void run() {
setUp();
}
}, 1000);
} /** Called when the activity is first created. */
// private String type = "_workstation._tcp.local.";_http._tcp.local.
private String type = "_http._tcp.local.";
private JmDNS jmdns = null;
private ServiceListener listener = null;
private ServiceInfo serviceInfo;
private void setUp() {
android.net.wifi.WifiManager wifi = (android.net.wifi.WifiManager) getSystemService(android.content.Context.WIFI_SERVICE);
lock = wifi.createMulticastLock("mylockthereturn");
lock.setReferenceCounted(true);
lock.acquire();
try {
InetAddress Address = InetAddress.getLocalHost();
Log.e("Local :", Address.getHostName());
jmdns = JmDNS.create(Address);
jmdns.addServiceListener(type, listener = new ServiceListener() {
#Override
public void serviceResolved(ServiceEvent ev) {
notifyUser("Service resolved: " + ev.getInfo().getQualifiedName() + " port:" + ev.getInfo().getPort());
}
#Override
public void serviceRemoved(ServiceEvent ev) {
notifyUser("Service removed: " + ev.getName());
}
#Override
public void serviceAdded(ServiceEvent event) {
// Required to force serviceResolved to be called again (after the first search)
jmdns.requestServiceInfo(event.getType(), event.getName(), 1);
}
});
serviceInfo = ServiceInfo.create("_http._tcp.local.", "AndroidTest", 8080, "plain test service from android");
jmdns.registerService(serviceInfo);
} catch (IOException e) {
e.printStackTrace();
return;
}
}
private void notifyUser(final String msg) {
handler.postDelayed(new Runnable() {
public void run() {
TextView t = (TextView)findViewById(R.id.text);
t.setText(msg+"\n=== "+t.getText());
}
}, 1);
}
#Override
protected void onStart() {
super.onStart();
//new Thread(){public void run() {setUp();}}.start();
}
#Override
protected void onStop() {
if (jmdns != null) {
if (listener != null) {
jmdns.removeServiceListener(type, listener);
listener = null;
}
jmdns.unregisterAllServices();
try {
jmdns.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
jmdns = null;
}
//repo.stop();
//s.stop();
lock.release();
super.onStop();
}
}

Android remote services: no communication

I am trying to make an Activity run a certain service.
I followed the tutorial here but adapted to my code, and I can't make it work, because when I am invoking the service after starting and binding it to the activity, my Interface (IMyRemoteCallsLoggingService) object does not seem to have the connection properly created.
I have been trying to make this work for several days but I can't seem to get rid of a NullPointException.
Not sure if I made myself clear, in which case here's the code:
public class MtprojectActivity extends Activity {
[...]
private boolean started = false;
private RemoteSmsLoggingServiceConnection SmsLoggingConn = null;
private RemoteCallsLoggingServiceConnection CallsLoggingConn = null;
private IMyRemoteCallsLoggingService callsLoggingService;
private IMyRemoteSmsLoggingService smsLoggingService;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
retrievePreferences();
Button prefBtn = (Button) findViewById(R.id.prefsBtn);
prefBtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// Explicit intent to call the preferences
Intent preferencesActivity = new Intent(getBaseContext(),
Preferences.class);
startActivity(preferencesActivity);
}
});
}
private void retrievePreferences() {
// Get the xml/preferences.xml preferences
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(getBaseContext());
callsCheckbox = prefs.getBoolean("callsLogChk", false);
smsCheckbox = prefs.getBoolean("smsLogChk", false);
locationCheckbox = prefs.getBoolean("locationLogChk", false);
if (callsCheckbox) {
startCallsService();
bindCallsService();
try {
invokeCallsService();
} catch (RemoteException e) {
e.printStackTrace();
}
} else {
}
private void startCallsService() {
if (started) {
Toast.makeText(MtprojectActivity.this, "Service already started",
Toast.LENGTH_SHORT).show();
} else {
Intent i = new Intent();
i.setClassName("app.mtproject", "app.mtproject.CallsLoggingService");
startService(i);
started = true;
updateCallsServiceStatus();
Log.d(getClass().getSimpleName(), "startService()");
}
}
private void bindCallsService() {
if (CallsLoggingConn == null) {
CallsLoggingConn = new RemoteCallsLoggingServiceConnection();
Intent i = new Intent();
i.setClassName("app.mtproject", "app.mtproject.CallsLoggingService");
bindService(i, CallsLoggingConn, Context.BIND_AUTO_CREATE);
updateCallsServiceStatus();
Log.d(getClass().getSimpleName(), "bindService()");
} else {
Toast.makeText(MtprojectActivity.this,
"Cannot bind - service already bound", Toast.LENGTH_SHORT)
.show();
}
}
private void invokeCallsService() throws RemoteException {
if (CallsLoggingConn == null) {
Toast.makeText(MtprojectActivity.this,
"Cannot invoke - service not bound", Toast.LENGTH_SHORT)
.show();
} else {
callsLoggingService.dumpCallsLog();
TextView t = (TextView) findViewById(R.id.notApplicable);
t.setText("It worked!");
Log.d(getClass().getSimpleName(), "invokeService()");
}
}
class RemoteCallsLoggingServiceConnection implements ServiceConnection {
public void onServiceConnected(ComponentName className,
IBinder boundService) {
callsLoggingService = IMyRemoteCallsLoggingService.Stub
.asInterface((IBinder) boundService);
Log.d(getClass().getSimpleName(), "onServiceConnected()");
}
public void onServiceDisconnected(ComponentName className) {
callsLoggingService = null;
updateCallsServiceStatus();
Log.d(getClass().getSimpleName(), "onServiceDisconnected");
}
};
I get a NullPointerException right on callsLoggingService.dumpCallsLog() in the invokeCallsService() method, and I'm not sure what's the problem!
Here's the code of the service:
public class CallsLoggingService extends Service {
String date, duration, type;
private Handler serviceHandler;
private Task myTask = new Task();
#Override
public IBinder onBind(Intent arg0) {
Log.d(getClass().getSimpleName(), "onBind()");
return myRemoteCallsServiceStub;
}
private IMyRemoteCallsLoggingService.Stub myRemoteCallsServiceStub = new IMyRemoteCallsLoggingService.Stub() {
public void dumpCallsLog() throws RemoteException {
CallsLoggingService.this.dumpCallsLog();
}
};
#Override
public void onCreate() {
super.onCreate();
Log.d(getClass().getSimpleName(), "onCreate()");
}
#Override
public void onDestroy() {
super.onDestroy();
serviceHandler.removeCallbacks(myTask);
serviceHandler = null;
Log.d(getClass().getSimpleName(), "onDestroy()");
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
serviceHandler = new Handler();
serviceHandler.postDelayed(myTask, 10L);
Log.d(getClass().getSimpleName(), "onStart()");
}
class Task implements Runnable {
public void run() {
try {
myRemoteCallsServiceStub.dumpCallsLog();
} catch (RemoteException e) {
e.printStackTrace();
}
serviceHandler.postDelayed(this, 86400000L);
Log.i(getClass().getSimpleName(), "Calling the dumpCallsLog");
}
}
private synchronized void dumpCallsLog() {
ContentResolver cr = getContentResolver();
String columns[] = new String[] { CallLog.Calls.DATE,
CallLog.Calls.DURATION, CallLog.Calls.TYPE };
Uri mContacts = CallLog.Calls.CONTENT_URI;
Cursor c = cr.query(mContacts, columns, // Which columns to return
null, // WHERE clause; which rows to return(all rows)
null, // WHERE clause selection arguments (none)
CallLog.Calls.DEFAULT_SORT_ORDER // Order-by clause
// (ascending
// by name)
);
if (c.moveToFirst()) {
do {
// Get the field values
date = c.getString(c.getColumnIndex(CallLog.Calls.DATE));
duration = c
.getString(c.getColumnIndex(CallLog.Calls.DURATION));
type = c.getString(c.getColumnIndex(CallLog.Calls.TYPE));
} while (c.moveToNext());
}
}
}
Thanks a lot everybody for the help!
bindService() is asynchronous. You cannot use callsLoggingService until onServiceConnected() is called.

Categories

Resources