I would like to make method onSenzorChange run into thread. To run more smooth. And get information of x axis everytime change. And pass it to main class (Activity) into TextView.
MainActivity class :
public class MainActivity extends AppCompatActivity {
TextView textView;
TestOfPassUIThread t;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
t = new TestOfPassUIThread(this);
}
public void onStart(View view) {
t.register();
}
}
TestOfPassUIThread class ( not an activity or anything )
public class TestOfPassUIThread implements SensorEventListener {
private SensorManager sensorManager;
private Sensor sensor;
public TestOfPassUIThread (Context context) {
sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
public void register(){
sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL);
}
public void unregister() {
sensorManager.unregisterListener(this);
}
// Want this method be in Thread
//How can I do this ?
#Override
public void onSensorChanged(SensorEvent event) {
float xAxis = event.values[0];
// And I want it to display in TextView!
// In main activity would be textView.setText("" + xAxis);
//How to pass it to MainActivity class ?
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
There are multiple ways to achieve writing on the textview, the following is one way to do it. (you may wanna read about callbacks, check How to implement callbacks in Java).
As for accessing the UI thread from the background, there multiple ways to do it as well (check: Running code in main thread from another thread).
For why we used a HandlerThread below, you can read about it here: Acclerometer Sensor in Separate Thread.
So your listener becomes:
public abstract class TestOfPassUIThread implements SensorEventListener {
private SensorManager sensorManager;
private Sensor sensor;
private HandlerThread handlerThread;
private Context context;
private Runnable uiRunnable;
private float xAxis;
public TestOfPassUIThread (Context context) {
this.context = context;
sensorManager = (SensorManager) context.getSystemService (Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor (Sensor.TYPE_ACCELEROMETER);
}
public void register () {
initUiRunnable ();
handlerThread = new HandlerThread ("sensorHandler");
handlerThread.start ();
sensorManager.registerListener (
this,
sensor,
SensorManager.SENSOR_DELAY_NORMAL,
new Handler (handlerThread.getLooper ())
);
}
public void unregister () {
sensorManager.unregisterListener (this);
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
handlerThread.quitSafely ();
return;
}
handlerThread.quit ();
} finally {
uiRunnable = null;
}
}
#Override
public void onSensorChanged (SensorEvent event) {
xAxis = event.values [0];
// your other background operations
((Activity)context).runOnUiThread (uiRunnable);
// your other background operations
}
#Override
public void onAccuracyChanged (Sensor sensor, int accuracy) {
}
private void initUiRunnable () {
uiRunnable = new Runnable () {
#Override
public void run () {
// ...... your other UI operations
fillTextView (xAxis);
// ...... your other UI operations
}
};
}
public abstract void fillTextView (float xAxis);
}
And your activity:
public class MainActivity extends AppCompatActivity {
private TextView textView;
private TestOfPassUIThread t;
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate (savedInstanceState);
setContentView (R.layout.activity_main);
textView = (TextView)findViewById (R.id.textView);
t = new TestOfPassUIThread (this) {
#Override
public void fillTextView (float xAxis) {
textView.setText ("Current xAxis: " + xAxis);
}
};
}
#Override
protected void onResume () {
super.onResume ();
t.register ();
}
#Override
protected void onPause () {
t.unregister ();
super.onPause ();
}
}
Also, when you override LifeCycle methods of Activities such as onStart, onResume etc..., make sure to call the super.lifeCycleMethod.
Related
There will be a lot of code. I had to leave it for you to understand logic of an application.
Here is the MainActivity. Called on starting.
public class MainActivity extends AppCompatActivity {
private GameView gameView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//some unnecessary code
setContentView(R.layout.activity_main);
}
public void startSurvival(View view) {
gameView = new GameView(this, this, "survival");
setContentView(gameView);
}
public void chooseData(View view){
setContentView(new DView(this, this));
}
public void backToMenu(){
setContentView(R.layout.activity_main);
gameView = null;
}
#Override
protected void onResume() {
super.onResume();
try {
gameView.update();
} catch (NullPointerException e) {}
}
}
This Activity is a List of options. You choose one and then GameView sets as content View with appropriate parameters.
Here is no questions so I cut almost all the code.
public class DView extends ListView {
DView(final Context context, final MainActivity mainActivity){
super(context);
this.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String[] columns = {"data"};
String having = "id = " + ids[position];
SQLiteDatabase db = dbHelper.getWritableDatabase();
Cursor cursor = db.query("levels", columns, null, null, ID, having, null);
if (cursor.moveToFirst()){
int dataInd = cursor.getColumnIndex(DATA);
mainActivity.setContentView(new GameView(context, mainActivity, cursor.getString(dataInd)));
}//everything here works fine. This just shows that setContentView can be done multiple times
//without bugs
cursor.close();
dbHelper.close();
}
});
}
}
And here comes the problem. When win() method is called display turns black. Application does not crash.
public class GameView extends SurfaceView{
public MainActivity mainActivity;
GameThread gameThread;
public Player player = null;
public Canvas canvas;
public ExtraData data;
public GameView (Context context, MainActivity mainActivity, String data){
super(context);
this.mainActivity = mainActivity;
if (data.equals("survival")) {
this.data = new ExtraData("RandomSpawn47",null, this);
} else {
this.data = new ExtraData("UsingData", data, this);
}
update();
}
void update(){
gameThread = new GameThread(this);
getHolder().addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
gameThread.running(true);
if (gameThread.getState() == Thread.State.NEW)
gameThread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
gameThread.running(false);
}
});
if (player == null)
player = new Player(this);
}
public class GameThread extends Thread{
private GameView gameView;
public GameThread(GameView gameView) {
this.gameView = gameView;
}
public void running(boolean run){
running = run;
}
#Override
public void run() {
while (running){
canvas = null;
try{
canvas = gameView.getHolder().lockCanvas(null);
synchronized (gameView.getHolder()){
draw(canvas);
this.wait(45);
}
} catch(Exception e) {}
finally {
if((canvas != null)&&(running)){
gameView.getHolder().unlockCanvasAndPost(canvas);
}
}
}
}
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
canvas.drawColor(Color.BLUE);
data.onDraw();
}
public void win(){
mainActivity.backToMenu();//not switching the menu
}
}
Other classes like ExtraData and Player are not important.
GameThread and SurfaceView destroyes (I checked them with Logs in onDestroy() and in the end of run() method).
You are calling method of Activity from another class. Instead of mainActivity.backToMenu(), create one interface, implement it in MainActivity and pass the reference in GameView to initialize the interface. And where you are calling win method, call interface method instead of calling the public method of MainActivity.
Create one interface like:
public interface UpdateActivity{
void updateActivity();
}
In MainActivity
public class MainActivity extends AppCompatActivity implements UpdateActivity
then override the method of interface
void updateActivity(){
setContentView(R.layout.activity_main);
gameView = null;
}
Pass the reference in GameView instead of passing the MainActivity reference.
public GameView (Context context, UpdateActivity updateActivity , String data) {
super(context);
this.updateActivity = updateActivity ;
if (data.equals("survival")) {
this.data = new ExtraData("RandomSpawn47",null, this);
} else {
this.data = new ExtraData("UsingData", data, this);
}
update();
}
Now call the method where you want to call:
updateActivity.updateActivity();
I am working on a step counter and I want to store the steps taken last day and reset the step count next day while still storing the previous data in another textView.
Here's my code:
public class StepsActivity extends AppCompatActivity implements SensorEventListener {
SensorManager sensorManager;
TextView textView;
boolean running=false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_steps);
textView = (TextView)findViewById(R.id.tv_steps);
sensorManager =(SensorManager)getSystemService(Context.SENSOR_SERVICE);
}
#Override
protected void onResume() {
super.onResume();
running = true;
Sensor countSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
if (countSensor != null) {
sensorManager.registerListener(this, countSensor, SensorManager.SENSOR_DELAY_UI);
} else {
Toast.makeText(this,"Sensor not found", Toast.LENGTH_SHORT).show();
}
}
#Override
protected void onPause() {
super.onPause();
running = false;
sensorManager.unregisterListener(this);
}
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
if (running) {
textView.setText(String.valueOf(sensorEvent.values[0]));
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
}
I want to convert my project according to MVP structure, & I had done it but it violate the MVP design, as it holds the activity instance in the presenter layer.
So, I just wanted to know how can I convert this project into pure MVP. Here Validation class is recursive and validate many fields & for here it is just for signup, and I had put the Validate method into separate thread.
This is my MVP interface
import android.app.Activity;
public class IMVP_Login {
/**
* View mandatory methods. Available to Presenter
* Presenter -> View
*/
public interface RequiredViewOps {
void showToast(String msg);
}
/**
* Operations offered from Presenter to View
* View -> Presenter
*/
public interface PresenterOps{
void submit(Activity activity);
}
}
This is my presenter with thread and containing the activity instance, which is against the design pattern of MVP, the code is as follows
import android.app.Activity;
import java.lang.ref.WeakReference;
import cp.utility.CustomException;
import cp.utility.Validation;
public class PresenterLogin implements Runnable,IMVP_Login.PresenterOps
{
private WeakReference<IMVP_Login.RequiredViewOps> mView;
// this is against the architectural law of MVP
private WeakReference<Activity> activity;
public PresenterLogin(IMVP_Login.RequiredViewOps mView) {
this.mView = new WeakReference<>(mView);
}
#Override
public void run() {
try
{
Validation.validate(activity.get());
}catch (CustomException e)
{
mView.get().showToast(e.getMessage());
}
}
//how should i do this with MVP PATTERN,as it is holding the activity instance
#Override
public void submit(Activity activity) {
this.activity=new WeakReference<>(activity);
Thread validationThread = new Thread(this,"Validation");
validationThread.start();
}
}
This is my activity,
public class Login extends AppCompatActivity implements View.OnClickListener,IMVP_Login.RequiredViewOps
{
private TextInputEditText edPhone,edCountrycode,edPassword;
private IMVP_Login.PresenterOps presenterLogin;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_signin);
initialize();
}
private void initialize()
{
presenterLogin= new PresenterLogin(this);
Button btSignIn=GeneralFunction.findViewByIdAndCast(this,R.id.btnSignIn);
btSignIn.setOnClickListener(this);
edCountrycode = GeneralFunction.findViewByIdAndCast(this, R.id.etCode);
edPhone = GeneralFunction.findViewByIdAndCast(this, R.id.etPhone);
edPassword = GeneralFunction.findViewByIdAndCast(this, R.id.etPassword);
edPassword.setTypeface(Typekit.getInstance().get(getString(R.string.str_regular)));
edPassword.setTransformationMethod(new PasswordTransformationMethod());
}
#Override
public void onClick(View view) {
switch (view.getId())
{
case R.id.btnSignIn:
presenterLogin.submit(this);
break;
}
}
#Override
public void showToast(String msg) {
//show toast
}
}
This is the validation class depending on tag of editext,
public class Validation {
public static boolean validateFields(final ViewGroup parentView) throws CustomException
{
for (int i = 0; i < parentView.getChildCount(); i++)
{
if (parentView.getChildAt(i) instanceof ViewGroup) {
if ((parentView.getChildAt(i)).getVisibility() == View.VISIBLE)
validateFields((ViewGroup) parentView.getChildAt(i));
}
else if((parentView.getChildAt(i) instanceof TextView) && ((parentView.getChildAt(i)).getVisibility() == View.VISIBLE))
{
TextView editText = (TextView) parentView.getChildAt(i);
if(null!=editText.getTag())
{
String type = editText.getTag().toString().toLowerCase();
String text=GeneralFunction.getTextFromView(editText);
//validation depending on tag
}
}
}
return true;
}
public static boolean validate(Activity activity) {
final ViewGroup viewGroup = (ViewGroup) activity.findViewById(android.R.id.content);
return validateFields(viewGroup);
}
}
Let me start by saying that there are many different ways of doing MVP, each of them valid in their own right. The important things to keep in mind are:
The View should not know about the model, it doesn't care at all where its data is coming from.
The Presenter should not know about Android. You should be able to run your Presenter class entirely on the JVM.
Your Activity/Fragment/ViewGroup should implement the View interface which is how the Presenter communicates with them.
Why do we do this?
Separation of concerns.
You can change the network library you use in your Model and the View/Presenter should just work still. You could switch your View from a horizontal ViewPager to a vertical RecyclerView and the Presenter/Model equally wouldn't care.
Testing.
We can mock our Presenter and unit test the View or Model. Mock the View & Model and unit test the Presenter.
As long as the implementation of MVP that you are using allows the above then in my mind it is valid.
Onto your specific problem. I would set it up something like this:
View:
public interface LoginView {
Map<String,String> getLoginFields();
}
Activity:
public class LoginActivity extends AppCompatActivity implements LoginView {
private EditText emailView;
private EditText phoneView;
private EditText passwordView;
private Button loginView;
private LoginPresenter presenter;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
presenter = new LoginPresenter();
presenter.bindView(this);
emailView = findViewById(R.id.login_email);
phoneView = findViewById(R.id.login_phone);
passwordView = findViewById(R.id.login_password);
loginView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
presenter.login();
}
});
}
#Override
protected void onDestroy() {
presenter.unbindView();
super.onDestroy();
}
#Override
public Map<String, String> getLoginFields() {
Map<String, String> fields = new HashMap<>();
fields.put(emailView.getTag().toString(), emailView.getText().toString());
fields.put(phoneView.getTag().toString(), phoneView.getText().toString());
fields.put(passwordView.getTag().toString(), passwordView.getText().toString());
return fields;
}
}
You may wish to do something fancy with the getLoginFields method and loop through your container. Even if you had 100 fields though it shouldn't require offloading onto another thread. I'd be a very upset user if I had to fill out 100 fields...
Presenter:
public class LoginPresenter {
private LoginView view;
private LoginValidator validator;
public void bindView(LoginView view) {
this.view = view;
}
public void unbindView() {
view = null;
}
public void login() {
validator = new LoginValidator();
Map<String, String> fields = view.getLoginFields();
boolean isValid = validator.validate(fields);
}
}
Validator:
public class LoginValidator {
public boolean validate(Map<String, String> fields) {
//validation depending on tag
return true;
}
}
Threading
If the need does arise to process something on another thread in the Activity then you have several approaches you could take:
Pass a listener to the getLoginFields() method which gets called when the work is done.
Expose another method in the Presenter, something like onLoginFieldsProcessed which would get called once the work is done.
Have getLoginFields() return Observable (RxJava) or Future.
I would personally probably use RxJava, especially if I was already using it in the app.
The main reason why there is separate presenter class added in this MVP framework ( especially in android ) is to remove the OutOfMemory or if by chance the activity fails the presenter calls is not affected i.e why there is MVP approach followed instead of MV framework.
Consider the below example that is from below link :-
public class MainActivity extends Activity {
public static final String DEFAULT_NAME = "Chuck Norris";
private ArrayAdapter<ServerAPI.Item> adapter;
private Subscription subscription;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView)findViewById(R.id.listView);
listView.setAdapter(adapter = new ArrayAdapter<>(this, R.layout.item));
requestItems(DEFAULT_NAME);
}
#Override
protected void onDestroy() {
super.onDestroy();
unsubscribe();
}
public void requestItems(String name) {
unsubscribe();
subscription = App.getServerAPI()
.getItems(name.split("\\s+")[0], name.split("\\s+")[1])
.delay(1, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<ServerAPI.Response>() {
#Override
public void call(ServerAPI.Response response) {
onItemsNext(response.items);
}
}, new Action1<Throwable>() {
#Override
public void call(Throwable error) {
onItemsError(error);
}
});
}
public void onItemsNext(ServerAPI.Item[] items) {
adapter.clear();
adapter.addAll(items);
}
public void onItemsError(Throwable throwable) {
Toast.makeText(this, throwable.getMessage(), Toast.LENGTH_LONG).show();
}
private void unsubscribe() {
if (subscription != null) {
subscription.unsubscribe();
subscription = null;
}
}
}
In the above example the activity failure causes the presenter layer to stop working .Similarly ,if there is any object associated with this activity class ( View ) will be affected .
Referencing by static will make the activity die out while there is a crash but the presenter class will not be affected.( Please refer to below code for MVP ).
public class MainPresenter {
public static final String DEFAULT_NAME = "Chuck Norris";
private ServerAPI.Item[] items;
private Throwable error;
private MainActivity view;
public MainPresenter() {
App.getServerAPI()
.getItems(DEFAULT_NAME.split("\\s+")[0], DEFAULT_NAME.split("\\s+")[1])
.delay(1, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<ServerAPI.Response>() {
#Override
public void call(ServerAPI.Response response) {
items = response.items;
publish();
}
}, new Action1<Throwable>() {
#Override
public void call(Throwable throwable) {
error = throwable;
publish();
}
});
}
public void onTakeView(MainActivity view) {
this.view = view;
publish();
}
private void publish() {
if (view != null) {
if (items != null)
view.onItemsNext(items);
else if (error != null)
view.onItemsError(error);
}
}
}
public class MainActivity extends Activity {
private ArrayAdapter<ServerAPI.Item> adapter;
private static MainPresenter presenter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView)findViewById(R.id.listView);
listView.setAdapter(adapter = new ArrayAdapter<>(this, R.layout.item));
if (presenter == null)
presenter = new MainPresenter();
presenter.onTakeView(this);
}
#Override
protected void onDestroy() {
super.onDestroy();
presenter.onTakeView(null);
if (!isChangingConfigurations())
presenter = null;
}
public void onItemsNext(ServerAPI.Item[] items) {
adapter.clear();
adapter.addAll(items);
}
public void onItemsError(Throwable throwable) {
Toast.makeText(this, throwable.getMessage(), Toast.LENGTH_LONG).show();
}
}
MainActivity creates MainPresenter and keeps it outside of reach of onCreate/onDestroy cycle. MainActivity uses a static variable to reference MainPresenter, so every time a process restarts due to out-of-memory event, MainActivity should check if the presenter is still here and create it if needed.( As stated in the doc ).
Hope this helps :)
I have a simple Android program that calculates how long it takes the phone to compute a certain mathematical problem. I want the mathematical problem to start when I hit the button, and while it is running I want a spinning progress bar to be displayed, and I want it to disappear after the math problem is done. This is the code I currently have:
public class main extends AppCompatActivity {
private TextView mScore;
private Button mRunButton;
private TextView mScoreText;
private ProgressBar mSpinner;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mScore = (TextView) findViewById(R.id.score);
mRunButton = (Button) findViewById(R.id.runbutton);
mScoreText = (TextView) findViewById(R.id.scoreText);
mSpinner = (ProgressBar) findViewById(R.id.progress);
mSpinner.setVisibility(View.GONE);
View.OnClickListener listener = new View.OnClickListener(){
#Override
public void onClick(View v) {
mSpinner.setVisibility(View.VISIBLE);
long startTime = System.nanoTime();
long start = System.currentTimeMillis();
long count = 0l;
for(long x=0;x<Integer.MAX_VALUE ;x++){
count+=1;
}
long end = System.currentTimeMillis();
long endTime = System.nanoTime();
long duration = ((endTime - startTime) / 1000000);
mScore.setText(duration + "");
mSpinner.setVisibility(View.GONE);
}
};
mRunButton.setOnClickListener(listener);
}
}
From what I can tell, nothing in the view of the app updates until after the phone is done with the entire onClick method, which is not what I want it to do. I want the progress bar to be displayed ONLY while the program is 'working'. How would I go about doing this?
Thank you
As Blackbelt and vilpe89 mentioned, you have to separate the threads. You can do this by having another class that extends ASyncTask which will handle the calculations. The problem with that is that the progress dialog needs to run on the UI thread. You can have an interface that changes the progress dialog in the main class.
Calculator class:
public final class Calculator extends AsyncTask<Void, Void, Void> {
Context context;
calcCallback mCallback;
public Calculator(Context c) {
this.context = c;
this.mCallback = (calcCallback) c;
}
//The main class needs to implement this interface
public interface calcCallback {
Void calcDone();
Void calcStarted();
//Other methods if necessary
}
#Override
protected Boolean doInBackground(Void... params) {
mCallback.calcStarted();
//Your calculations here
mCallback.calcDone();
return null;
}
}
MainActivity
public class MainActivity extends Activity implements Calculator.calcCallback, {
private TextView mScore;
private Button mRunButton;
private TextView mScoreText;
private ProgressBar mSpinner;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mScore = (TextView) findViewById(R.id.score);
mRunButton = (Button) findViewById(R.id.runbutton);
mScoreText = (TextView) findViewById(R.id.scoreText);
mSpinner = (ProgressBar) findViewById(R.id.progress);
mSpinner.setVisibility(View.GONE);
View.OnClickListener listener = new View.OnClickListener(){
#Override
public void onClick(View v) {
Calculator calculator = new Calculator(MainActivity.this);
calculator.execute();
}
};
mRunButton.setOnClickListener(listener);
}
#Override
public Void calcStarted() {
runOnUiThread(new Runnable() {
#Override
public void run() {
mSpinner.setVisibility(View.VISIBLE);
}
});
}
return null;
}
#Override
public Void calcDone() {
runOnUiThread(new Runnable() {
#Override
public void run() {
mSpinner.setVisibility(View.GONE);
}
});
}
return null;
}
}
You can also set up your calcDone() as calcDone(int duration) so that you can pass the calculated duration back to the main thread.
I have w problem with simple code: In mainActivity i need check if sensor for example Light sensor is available on phone, and if is available i need to reed and show the results of this senson on screen, but code responsible for read data from sensor must be in separate class. I wrote simple code, but it doesn't work. When i run this code, my phone show me only : "Light level: 0.0". I'm beginner in programming so please help me..
Main class:
public class MainActivity extends Activity {
LightSensor mLightSensor = null;
protected SensorManager mSensorManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView wyswietl = (TextView)findViewById(R.id.res);
mLightSensor = new LightSensor();
mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
if (mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT) != null){
LightSensor lS = new LightSensor();
wyswietl.setText("Light level: " + Float.toString(lS.lux));
}
else{
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
protected void onResume(){
super.onResume();
mLightSensor.register();
}
#Override
protected void onPause(){
super.onPause();
mLightSensor.unregister();
}
}
and LightSensor class:
public class LightSensor implements SensorEventListener {
SensorManager mSensorManager;
Sensor lightManager;
public float lux;
public Context context;
public void onCreateLight(Context context){
this.context = context;
mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
lightManager = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
lux = event.values[0];
}
public void register(){
mSensorManager.registerListener(this, lightManager, SensorManager.SENSOR_DELAY_NORMAL);
}
public void unregister(){
mSensorManager.unregisterListener(this);
}
}
I haven't tested it, but you could possibly make a new method in your LightSensor class to return the lux variable to the main class
Something like:
public float getLux(){
return lux;
}
and then in your "MainActivity" class you can call
float newLux = mLightSensor.getLux();
If it doesn't work I might have a slightly more complex solution.
You never call mLightSensor.onCreateLight();
How about changing onCreateLight to be your LightSensor class' constructor. That would solve the problem and not require you to remember to call onCreateLight.
public LightSensor(Context context){
this.context = context;
mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
lightManager = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
}