main xml :
Code:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
tools:context="com.justforum.yotamarker.mytimeservice.MainActivity" >
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="-80dp"
android:src="@mipmap/ic_launcher" />
<Button
android:id="@+id/print_timestamp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="130dp"
android:text="Print Timestamp" />
<TextView
android:id="@+id/timestamp_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/print_timestamp"
android:layout_centerHorizontal="true"
android:layout_marginTop="120dp"
android:text=""
android:textAppearance="?android:attr/textAppearanceLarge" />
<Button
android:id="@+id/stop_service"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/print_timestamp"
android:layout_centerHorizontal="true"
android:text="Stop Service" />
</RelativeLayout>
BoundService.java
Code:
package com.justforum.yotamarker.mytimeservice;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.SystemClock;
import android.util.Log;
import android.widget.Chronometer;
public class BoundService extends Service {
private static String LOG_TAG = "BoundService";
private IBinder mBinder = new MyBinder();
private Chronometer mChronometer;
@Override
public void onCreate() {
super.onCreate();
Log.v(LOG_TAG, "in onCreate");
mChronometer = new Chronometer(this);
mChronometer.setBase(SystemClock.elapsedRealtime());
mChronometer.start();
}
@Override
public IBinder onBind(Intent intent) {
Log.v(LOG_TAG, "in onBind");
return mBinder;
}
@Override
public void onRebind(Intent intent) {
Log.v(LOG_TAG, "in onRebind");
super.onRebind(intent);
}
@Override
public boolean onUnbind(Intent intent) {
Log.v(LOG_TAG, "in onUnbind");
return true;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.v(LOG_TAG, "in onDestroy");
mChronometer.stop();
}
public String getTimestamp() {
long elapsedMillis = SystemClock.elapsedRealtime()
- mChronometer.getBase();
int hours = (int) (elapsedMillis / 3600000);
int minutes = (int) (elapsedMillis - hours * 3600000) / 60000;
int seconds = (int) (elapsedMillis - hours * 3600000 - minutes * 60000) / 1000;
int millis = (int) (elapsedMillis - hours * 3600000 - minutes * 60000 - seconds * 1000);
return hours + ":" + minutes + ":" + seconds + ":" + millis;
}
public class MyBinder extends Binder {
BoundService getService() {
return BoundService.this;
}
}
}
add :
<service android:name="com.justforum.yotamarker.mytimeservice.BoundService">
</service>
like this :
Code:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.justforum.yotamarker.mytimeservice">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.justforum.yotamarker.mytimeservice.BoundService">
</service>
</application>
</manifest>
(package name varies for you)
MainActivity.java
Code:
package com.justforum.yotamarker.mytimeservice;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import com.justforum.yotamarker.mytimeservice.BoundService;
public class MainActivity extends AppCompatActivity {
BoundService mBoundService;
boolean mServiceBound = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView timestampText = (TextView) findViewById(R.id.timestamp_text);
Button printTimestampButton = (Button) findViewById(R.id.print_timestamp);
Button stopServiceButon = (Button) findViewById(R.id.stop_service);
printTimestampButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mServiceBound) {
timestampText.setText(mBoundService.getTimestamp());
}
}
});
stopServiceButon.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mServiceBound) {
unbindService(mServiceConnection);
mServiceBound = false;
}
Intent intent = new Intent(MainActivity.this,
BoundService.class);
stopService(intent);
}
});
}
@Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, BoundService.class);
startService(intent);
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
if (mServiceBound) {
unbindService(mServiceConnection);
mServiceBound = false;
}
}
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
mServiceBound = false;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
BoundService.MyBinder myBinder = (BoundService.MyBinder) service;
mBoundService = myBinder.getService();
mServiceBound = true;
}
};
}
hadouken.
example 2 : police siren service : displays police lights on main activity layout upon screen click event :
activity_main.xml :
Code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/llyBack"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/tvLight1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:textSize="50sp" />
<TextView
android:id="@+id/tvLight2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:textSize="50sp" />
</LinearLayout>
MyService.java
Code:
package com.justforum.yotamarker.serviceviews;
import android.app.Activity;
import android.app.Service;
import android.content.Intent;
import android.graphics.Color;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.View;
public class MyService extends Service {
//create binder
private final IBinder myBinder = new MyBinder();
//set state to 0
private int state = 0;
//set activity to null to avoid exception
private Activity myActivity = null;
//set two views for our text view
private View light1, light2;
//hold sequence of light
private State[] myStates;
//set mode to 0
private int mode = 0;
//since when services is created, he run it's default c'tor, we override it with our c'tor
public MyService() {
//get the first sequence
myStates = setPolice();
//create new thread, which run separated from our main thread
new Thread(new Runnable() {
@Override
public void run() {
//will run until we set the activity to nu
while (true) {
//get state
state = (state + 1) % myStates.length;
Log.d("TESTING", "state=" + state);
if (myActivity != null) {
//since we are inside a thread, and we can not access to other thread, we run it on ui thre
myActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
//set the colour
light1.setBackgroundColor(myStates[state].color1);
light2.setBackgroundColor(myStates[state].color2);
}
});
}
try {
//make thread some sleep, for biker effect
Thread.sleep(myStates[state].delay);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
//our sequence builders
public State[] setPolice() {
State[] police = new State[12];
police[0] = new State(Color.RED, Color.BLACK, 120);
police[1] = new State(Color.BLACK, Color.BLACK, 50);
police[2] = new State(Color.RED, Color.BLACK, 120);
police[3] = new State(Color.BLACK, Color.BLACK, 50);
police[4] = new State(Color.RED, Color.BLACK, 120);
police[5] = new State(Color.BLACK, Color.BLACK, 70);
police[6] = new State(Color.BLACK, Color.BLUE, 120);
police[7] = new State(Color.BLACK, Color.BLACK, 50);
police[8] = new State(Color.BLACK, Color.BLUE, 120);
police[9] = new State(Color.BLACK, Color.BLACK, 50);
police[10] = new State(Color.BLACK, Color.BLUE, 120);
police[11] = new State(Color.BLACK, Color.BLACK, 70);
return police;
}
public State[] setPolice1() {
State[] police = new State[12];
police[0] = new State(Color.BLUE, Color.BLACK, 120);
police[1] = new State(Color.BLACK, Color.BLACK, 50);
police[2] = new State(Color.BLUE, Color.BLACK, 120);
police[3] = new State(Color.BLACK, Color.BLACK, 50);
police[4] = new State(Color.BLUE, Color.BLACK, 120);
police[5] = new State(Color.BLACK, Color.BLACK, 70);
police[6] = new State(Color.BLACK, Color.BLUE, 120);
police[7] = new State(Color.BLACK, Color.BLACK, 50);
police[8] = new State(Color.BLACK, Color.BLUE, 120);
police[9] = new State(Color.BLACK, Color.BLACK, 50);
police[10] = new State(Color.BLACK, Color.BLUE, 120);
police[11] = new State(Color.BLACK, Color.BLACK, 70);
return police;
}
public State[] setFire() {
State[] fire = new State[12];
fire[0] = new State(Color.RED, Color.BLACK, 120);
fire[1] = new State(Color.BLACK, Color.BLACK, 50);
fire[2] = new State(Color.RED, Color.BLACK, 120);
fire[3] = new State(Color.BLACK, Color.BLACK, 50);
fire[4] = new State(Color.RED, Color.BLACK, 120);
fire[5] = new State(Color.BLACK, Color.BLACK, 70);
fire[6] = new State(Color.BLACK, Color.RED, 120);
fire[7] = new State(Color.BLACK, Color.BLACK, 50);
fire[8] = new State(Color.BLACK, Color.RED, 120);
fire[9] = new State(Color.BLACK, Color.BLACK, 50);
fire[10] = new State(Color.BLACK, Color.RED, 120);
fire[11] = new State(Color.BLACK, Color.BLACK, 70);
return fire;
}
//handle our binder
@Nullable
@Override
public IBinder onBind(Intent intent) {
return myBinder;
}
//we use inner class for less coding
public class MyBinder extends Binder {
public MyService getService() {
return MyService.this;
}
}
//return activity
public Activity getActivity() {
return myActivity;
}
//set pointers to activity xml, which we provide from main activity
public void setActivity(Activity activity, View light1, View light2) {
this.myActivity = activity;
this.light1 = light1;
this.light2 = light2;
}
//clear activity and pointers for garbage collector
public void setNoActivity() {
this.myActivity = null;
this.light1 = null;
this.light2 = null;
}
//inner class for better sequance builder
private class State {
int color1;
int color2;
int delay;
public State(int color1, int color2, int delay) {
this.color1 = color1;
this.color2 = color2;
this.delay = delay;
}
}
//changeing modes....
public void changeMode() {
mode = (mode + 1) % 3;
switch (mode) {
case 0:
myStates = setPolice();
break;
case 1:
myStates = setFire();
break;
case 2:
myStates = setPolice1();
break;
}
}
}
AndroidManifest.xml
Code:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.justforum.yotamarker.serviceviews">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.justforum.yotamarker.serviceviews.MyService">
</service>
</application>
</manifest>
MainActivity.java :
Code:
package com.justforum.yotamarker.serviceviews;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
//we use onclick & onLonclick listener for implementing the methods here
public class MainActivity extends AppCompatActivity implements View.OnClickListener, View.OnLongClickListener {
//declare of our bounded services
private MyService myService;
//a boolean which indicates if the service is bounded or not
private boolean isBound = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setPointer();
}
private void setPointer() {
//since we need only declare of click events, we don't need to create an instanc
findViewById(R.id.llyBack).setOnClickListener(this);
findViewById(R.id.llyBack).setOnLongClickListener(this);
}
@Override
public void onClick(View v) {
//if service is null, we will create it, else, we set null so garbage collector will clean the memory
if (myService.getActivity() == null) {
//we send here the activity, and pointers to our layout elements
myService.setActivity(this, findViewById(R.id.tvLight1), findViewById(R.id.tvLight2));
} else {
myService.setNoActivity();
}
}
@Override
protected void onStart() {
//when activity is started, bound the service
super.onStart();
bind();
}
private void bind() {
// Bind to LocalService
Intent intent = new Intent(this, MyService.class);
//create the service automatic by the connection and send the intent
bindService(intent, myConnection, Context.BIND_AUTO_CREATE);
}
/**
* Defines callbacks for service binding, passed to bindService()
*/
private ServiceConnection myConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to MyService, cast the IBinder and get MyService instance
MyService.MyBinder myBinder = (MyService.MyBinder) service;
myService = myBinder.getService();
isBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
isBound = false;
}
};
@Override
protected void onStop() {
//when our app is stopped, clear the service
super.onStop();
myService.setNoActivity();
}
@Override
public boolean onLongClick(View v) {
//if we use long click , change mode
myService.changeMode();
return true;
}
}
siren service
in MyService :
@Override
public int onStartCommand (Intent intent, int flags, int startId){
// several lines of awesome code
return START_STICKY;
}
or
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
startForeground(ONGOING_NOTIFICATION_ID, notification);
return super.onStartCommand(intent, flags, startId);
}
will make it sticky to run even if the device was restarted as long as it's app is installed
Last edited by Moti Barski on Wed Oct 10, 2018 1:54 am; edited 5 times in total