I have used the OrientationEventListener which I have coupled with a Handler to update a TextView when the screen rotates:
MainHandler handler;
TextView tv;
MyOrientationEventListener listener;
class MainHandler extends Handler
{
#Override
public void handleMessage(Message msg)
{
switch(msg.what)
{
case MSG_ORIENTATION:
if(tv!=null)
tv.setText(msg.arg1);
break;
default:
if(tv!=null)
tv.setText("Nothing to see here");
}
}
}
This is my OrientationEventListener here:
class MyOrientationEventListener extends OrientationEventListener
{
public MyOrientationEventListener(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public MyOrientationEventListener(Context context,int attrs)
{
super(context,attrs);
}
#Override
public void onOrientationChanged(int orientation) {
// TODO Auto-generated method stub
Log.d("MainActivity", "Orientation before rounding: "+orientation);
orientation=roundRotation(orientation,0);
Log.d("MainActivity", "Orientation after rounding: "+orientation);
Message msg=handler.obtainMessage(MSG_ORIENTATION);
msg.arg1=orientation;
handler.sendMessage(msg);
}
public int getDisplayOrientation()
{
int rotation=getWindowManager().getDefaultDisplay().getRotation();
switch(rotation)
{
case Surface.ROTATION_0:
return 0;
case Surface.ROTATION_90:
return 90;
case Surface.ROTATION_180:
return 180;
case Surface.ROTATION_270:
return 270;
}
return 0;
}
public int roundRotation(int orientation,int orientationHistory)
{
final int ORIENTATION_HYSTERESIS=5;
boolean changeOrientation=false;
if(orientationHistory==ORIENTATION_UNKNOWN)
changeOrientation=true;
else
{
int dist=Math.abs(orientation-orientationHistory);
dist=Math.min(dist, 360-dist);
changeOrientation=(dist>=45+ORIENTATION_HYSTERESIS);
}
if(changeOrientation)
{
int nOrientation=((orientation+45)/90*90)%360;
Log.d("OrientationEventHandler", "New orientation: "+nOrientation);
return nOrientation;
}
return orientationHistory;
}
}
I am using the Handler in onCreate to register my Handler to the UI thread,thus it can be used to update the Views on screen.However,this code does not seem to work:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv=(TextView)findViewById(R.id.tv);
handler=new MainHandler();
listener=new MyOrientationEventListener(this);
}
I am using listener.enable() in onResume and listener.disable() in onPause methods after invoking their respective superclass methods.When I try to rotate the screen and the rounding occurs:
MainActivity(9724): Orientation before rounding: 55
OrientationEventHandler(9724): New orientation: 90
MainActivity(9724): Orientation after rounding: 90
ResourceType(9724): No package identifier when getting value for resource number 0x0000005a
dalvikvm(9724): threadid=1: thread exiting with uncaught exception (group=0x41fdf700)
AndroidRuntime(9724): FATAL EXCEPTION: main
AndroidRuntime(9724): android.content.res.Resources$NotFoundException: String resource ID #0x5a
AndroidRuntime(9724): at android.content.res.Resources.getText(Resources.java:239)
AndroidRuntime(9724): at android.widget.TextView.setText(TextView.java:3837)
AndroidRuntime(9724): at com.example.calllogproject.MainActivity$MainHandler.handleMessage(MainActivity.java:30)
AndroidRuntime(9724): at android.os.Handler.dispatchMessage(Handler.java:99)
AndroidRuntime(9724): at android.os.Looper.loop(Looper.java:137)
AndroidRuntime(9724): at android.app.ActivityThread.main(ActivityThread.java:5103)
AndroidRuntime(9724): at java.lang.reflect.Method.invokeNative(Native Method)
AndroidRuntime(9724): at java.lang.reflect.Method.invoke(Method.java:525)
AndroidRuntime(9724): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
AndroidRuntime(9724): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
AndroidRuntime(9724): at dalvik.system.NativeStart.main(Native Method)
Try this class:
class MainHandler extends Handler
{
#Override
public void handleMessage(Message msg)
{
switch(msg.what)
{
case MSG_ORIENTATION:
if(tv!=null)
tv.setText(String.valueOf(msg.arg1));
break;
default:
if(tv!=null)
tv.setText("Nothing to see here");
}
}
}
I've changed
tv.setText(msg.arg1);
into
tv.setText(String.valueOf(msg.arg1));
Related
I am trying to make glsurfaceview a part of my layout. It returns an error at a line I am sure about and I don't understand why.
My GLGame class:
public abstract class GLGame extends Activity implements Game, Renderer {
enum GLGameState {
Initialized,
Running,
Paused,
Finished,
Idle
}
GLSurfaceView glView;
GLGraphics glGraphics;
Audio audio;
Input input;
FileIO fileIO;
Screen screen;
GLGameState state = GLGameState.Initialized;
Object stateChanged = new Object();
long startTime = System.nanoTime();
WakeLock wakeLock;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
glView =(GLSurfaceView) this.findViewById (R.id.glSurface);
glView.setRenderer(this); //Failing line
setContentView(R.layout.main);
glGraphics = new GLGraphics(glView);
fileIO = new AndroidFileIO(getAssets());
audio = new AndroidAudio(this);
input = new AndroidInput(this, glView, 1, 1);
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "GLGame");
}
public void onResume() {
super.onResume();
glView.onResume();
wakeLock.acquire();
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
glGraphics.setGL(gl);
synchronized(stateChanged) {
if(state == GLGameState.Initialized)
screen = getStartScreen();
state = GLGameState.Running;
screen.resume();
startTime = System.nanoTime();
}
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
}
#Override
public void onDrawFrame(GL10 gl) {
GLGameState state = null;
synchronized(stateChanged) {
state = this.state;
}
if(state == GLGameState.Running) {
float deltaTime = (System.nanoTime()-startTime) / 1000000000.0f;
startTime = System.nanoTime();
screen.update(deltaTime);
screen.present(deltaTime);
}
if(state == GLGameState.Paused) {
screen.pause();
synchronized(stateChanged) {
this.state = GLGameState.Idle;
stateChanged.notifyAll();
}
}
if(state == GLGameState.Finished) {
screen.pause();
screen.dispose();
synchronized(stateChanged) {
this.state = GLGameState.Idle;
stateChanged.notifyAll();
}
}
}
#Override
public void onPause() {
synchronized(stateChanged) {
if(isFinishing())
state = GLGameState.Finished;
else
state = GLGameState.Paused;
while(true) {
try {
stateChanged.wait();
break;
} catch(InterruptedException e) {
}
}
}
wakeLock.release();
glView.onPause();
super.onPause();
}
public GLGraphics getGLGraphics() {
return glGraphics;
}
#Override
public Input getInput() {
return input;
}
#Override
public FileIO getFileIO() {
return fileIO;
}
#Override
public Graphics getGraphics() {
throw new IllegalStateException("We are using OpenGL!");
}
#Override
public Audio getAudio() {
return audio;
}
#Override
public void setScreen(Screen screen) {
if (screen == null)
throw new IllegalArgumentException("Screen must not be null");
this.screen.pause();
this.screen.dispose();
screen.resume();
screen.update(0);
this.screen = screen;
}
#Override
public Screen getCurrentScreen() {
return screen;
}
}
Logcat:
03-25 16:44:51.683 4919-4919/com.badlogic.androidgames.glbasics E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.badlogic.androidgames.glbasics, PID: 4919
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.badlogic.androidgames.glbasics/com.badlogic.androidgames.glbasics.GLGameTest}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.opengl.GLSurfaceView.setRenderer(android.opengl.GLSurfaceView$Renderer)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2329)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2391)
at android.app.ActivityThread.access$900(ActivityThread.java:147)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1296)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5256)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:898)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:693)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.opengl.GLSurfaceView.setRenderer(android.opengl.GLSurfaceView$Renderer)' on a null object reference
at com.badlogic.androidgames.framework.impl.GLGame.onCreate(GLGame.java:51)
at android.app.Activity.performCreate(Activity.java:5933)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2282)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2391)
at android.app.ActivityThread.access$900(ActivityThread.java:147)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1296)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5256)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:898)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:693)
Everything worked fine until I decided I want other things than just glsurfaceview.
I think I am just making a silly mistake, but since the time presses I would be glad if you helped.
Thanks
EDIT: the issue turned out to be that I am unable to findviewbyid from here for some reason. I also tried this:
GLGame.glView = (GLSurfaceView) ((Activity)getApplicationContext()).findViewById (R.id.glSurface);
As it turned out, I am incredibly dumb for writing in in the wrong order. It is supposed to be like this:
setContentView(R.layout.main);
GLGame.glView = (GLSurfaceView) this.findViewById(R.id.glSurface);
glView.setRenderer(this);
Sorry because I am coming with stupid questions, is my first time here.I will try first to explain my application.
I have 3 objects ( or 3 java class in android ) Every class is basically an ImageView with a textView ( first 2 class, the last class is only an Imageview ).I succeed to open the same Pop-up where I change values of the text views or doing other stuffs.
So basically I have 3 images views with fiew text views where I want to open the same pop-up and change some values of the textViews or changing some backgrounds etc.I have implemented this only for 2 classes and when I open the pop-up from 1 object I get null to Other one, same to second object when I open it I get Null Pointer at first object.I will put some commented lines of my code below:
MainActivity:
RelativeLayout mylayout; //Getting my Layout
mylayout = (RelativeLayout) rootView.findViewById(R.id.mylayout);
RelativeLayout inflator = new RelativeLayout(getActivity().getApplicationContext());
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
lp.addRule(RelativeLayout.CENTER_IN_PARENT);
inflator.setLayoutParams(lp);
mylayout.addView(inflator);
inflator.setBackgroundColor(Color.CYAN);
TemperatureSymbol mytempsymbol = new TemperatureSymbol(getActivity(), inflator);
HumiditySymbol myhumiditysymbol = new HumiditySymbol(getActivity(), inflator);
Ok, in mainActivity I am creating the objects and add them to a layout, I want those object to stick together in a tiny layout and move only the layout, inflator is the layout where I am adding them.
TemperatureSymbol.class
public class TemperatureSymbol extends LinearLayout{
private int[] location = new int[2];
private ImageView temperature;
private int value = 20;
private GestureDetectorCompat mDetector;
private ControlListener controlListener;
private TextView celsius;
public interface ControlListener {
public void onLongStatement();
}
public void setControlListener(ControlListener controlListener) {
this.controlListener = controlListener;
}
public TemperatureSymbol getSymbol(){
return this;
}
void setValue(int counter){
value = counter;
celsius.setText("" + value + "°C");
}//THIS IS IMPORTANT BECAUSE WITH THIS METHOD I SET THE VALUE ON TextView WHEN I INCREMENT/DECREMENT A BUTTON
public TemperatureSymbol(Context context, RelativeLayout inflator) {
super(context);
// TODO Auto-generated constructor stub
temperature = (ImageView) new ImageView(context);
temperature.setBackgroundResource(drawable.termometruoff);
celsius = new TextView(context);
inflator.addView(temperature);
celsius.setText("°C");
inflator.addView(celsius);
inflator.getLocationOnScreen(location);
//Gather informations for GestureListener
MyGestureListener gestList = new MyGestureListener(location, context, inflator);
gestList.setTemperatureSymbol(this);
mDetector = new GestureDetectorCompat(context, gestList);
temperature.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
mDetector.onTouchEvent(event);
Log.i("TEST","Simple touch");
return true;
}
});
}
}
TemperatureSymbol.class is one of my object, basically is only an ImageView with a textview where to display a value like: 20 degrees Celsius.Basically the HumiditySymbol.class is the same as Temperature, same textview same ImageView only the image are changed.
Below is myGestureListener class where I open the same pop-up window from both objects.
class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
// Handler that is used for OnLongPress to Continue Decrementin/Incrementing Value
public class RptUpdater implements Runnable {
public void run() {
if (mAutoIncrement && tvalue < 35) {
increment();
repeatUpdateHandler.postDelayed(new RptUpdater(), REP_DELAY);
} else if (mAutoDecrement && tvalue > 10) {
decrement();
repeatUpdateHandler.postDelayed(new RptUpdater(), REP_DELAY);
}
}
private void decrement() {
// TODO Auto-generated method stub
if (tvalue > 10) {
tvalue--;
localTempSymbol.setValue(tvalue);
}
}
private void increment() {
// TODO Auto-generated method stub
if (tvalue < 35) {
tvalue++;
localTempSymbol.setValue(tvalue);
}
}
// Handler that is used for OnLongPress
public class RptUpdaterHumidity implements Runnable {
public void run() {
if (mAutoIncrementHumidity && hvalue < 100) {
increment();
repeatUpdateHandler.postDelayed(new RptUpdaterHumidity(),
REP_DELAY);
} else if (mAutoDecrementHumidity && hvalue > 0) {
decrement();
repeatUpdateHandler.postDelayed(new RptUpdaterHumidity(),
REP_DELAY);
}
}
private void decrement() {
// TODO Auto-generated method stub
if (hvalue > 0) {
hvalue--;
localHumSymbol.setHumidity(hvalue);
}
}
private void increment() {
// TODO Auto-generated method stub
if (hvalue < 100) {
hvalue++;
localHumSymbol.setHumidity(hvalue);
}
}
public void setTemperatureSymbol(TemperatureSymbol tempSymbol) {
localTempSymbol = tempSymbol;
}
public void setHumiditySymbol(HumiditySymbol tempSymbol) {
localHumSymbol = tempSymbol;
}
public MyGestureListener(int[] showLocation, Context context,
RelativeLayout inflator) {
super();
add = new Button(context);
sub = new Button(context);
addH = new Button(context);
subH = new Button(context);
popUp = new PopupWindow(context);
popUp.setBackgroundDrawable(new ShapeDrawable());
popUp.setOutsideTouchable(true);
popUp.setBackgroundDrawable(new ColorDrawable(
android.graphics.Color.TRANSPARENT));
layout = new LinearLayout(context);
layout.addView(add);
layout.addView(sub);
layout.addView(addH);
layout.addView(subH);
popUp.setContentView(layout);
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (tvalue < maxTvalue) {
tvalue++;
localTempSymbol.setValue(tvalue);
}
}
});
sub.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (tvalue > minTvalue) {
tvalue--;
Log.i("TEST", "localTemp = " + localTempSymbol);
localTempSymbol.setValue(tvalue);
}
}
});
// Long click listener to enable the value to increment
add.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
mAutoIncrement = true;
repeatUpdateHandler.post(new RptUpdater());
return false;
}
});
add.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if ((event.getAction() == MotionEvent.ACTION_UP || event
.getAction() == MotionEvent.ACTION_CANCEL)
&& mAutoIncrement)
mAutoIncrement = false;
return false;
}
});
// Long click listener to enable the value to decrement
sub.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
mAutoDecrement = true;
repeatUpdateHandler.post(new RptUpdater());
return false;
}
});
sub.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if ((event.getAction() == MotionEvent.ACTION_UP || event
.getAction() == MotionEvent.ACTION_CANCEL)
&& mAutoDecrement)
mAutoDecrement = false;
return false;
}
});
addH.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (hvalue < 100) {
hvalue++;
localHumSymbol.setHumidity(hvalue);
}
}
});
subH.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (hvalue > 0) {
hvalue--;
Log.i("TEST", "localTemp = " + localHumSymbol);
localHumSymbol.setHumidity(hvalue);
}
}
});
// Long click listener to enable the value to increment
addH.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
mAutoIncrementHumidity = true;
repeatUpdateHandlerHumidity.post(new RptUpdaterHumidity());
return false;
}
});
addH.setOnTouchListener(new View.OnTouchListener() {
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if ((event.getAction() == MotionEvent.ACTION_UP || event
.getAction() == MotionEvent.ACTION_CANCEL)
&& mAutoIncrementHumidity)
mAutoIncrementHumidity = false;
return false;
}
});
// Long click listener to enable the value to decrement
subH.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
mAutoDecrementHumidity = true;
repeatUpdateHandlerHumidity.post(new RptUpdaterHumidity());
return false;
}
});
subH.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if ((event.getAction() == MotionEvent.ACTION_UP || event
.getAction() == MotionEvent.ACTION_CANCEL)
&& mAutoDecrementHumidity)
mAutoDecrementHumidity = false;
return false;
}
});
}
#Override
public void onLongPress(MotionEvent event) {
//Here I read in logcat for example if I open the pop-up from TemperatureSymbol that Humidity is null
popUp.showAtLocation(layout, Gravity.TOP | Gravity.LEFT, 10, 10);
popUp.update(location[0], location[1], LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
}
}
I have this problem from days and I couldn't find a solution, the only Ideea I had is to change the values through setter method of every symbol.I don't want to do everywhint in one class, I just want to keep them like this but get rid of null pointer.
UPDATE:
When I am running the application, open the pop-up from first Symbol and trying to modify the Second:
10-30 09:35:17.583: I/TEST(12117): localTemp = com.example.symbol_temp_med.TemperatureSymbol{4246d188 V.E..... ......I. 0,0-0,0}
10-30 09:35:21.997: I/TEST(12117): localTemp = null
10-30 09:35:21.997: D/AndroidRuntime(12117): Shutting down VM
10-30 09:35:21.997: W/dalvikvm(12117): threadid=1: thread exiting with uncaught exception (group=0x41b72ba8)
10-30 09:35:22.007: E/AndroidRuntime(12117): FATAL EXCEPTION: main
10-30 09:35:22.007: E/AndroidRuntime(12117): Process: com.example.symbol_temp_med, PID: 12117
10-30 09:35:22.007: E/AndroidRuntime(12117): java.lang.NullPointerException
10-30 09:35:22.007: E/AndroidRuntime(12117): at com.example.symbol_temp_med.MyGestureListener$9.onClick(MyGestureListener.java:348)
10-30 09:35:22.007: E/AndroidRuntime(12117): at android.view.View.performClick(View.java:4438)
10-30 09:35:22.007: E/AndroidRuntime(12117): at android.view.View$PerformClick.run(View.java:18422)
10-30 09:35:22.007: E/AndroidRuntime(12117): at android.os.Handler.handleCallback(Handler.java:733)
10-30 09:35:22.007: E/AndroidRuntime(12117): at android.os.Handler.dispatchMessage(Handler.java:95)
10-30 09:35:22.007: E/AndroidRuntime(12117): at android.os.Looper.loop(Looper.java:136)
10-30 09:35:22.007: E/AndroidRuntime(12117): at android.app.ActivityThread.main(ActivityThread.java:5001)
10-30 09:35:22.007: E/AndroidRuntime(12117): at java.lang.reflect.Method.invokeNative(Native Method)
10-30 09:35:22.007: E/AndroidRuntime(12117): at java.lang.reflect.Method.invoke(Method.java:515)
10-30 09:35:22.007: E/AndroidRuntime(12117): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
10-30 09:35:22.007: E/AndroidRuntime(12117): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
10-30 09:35:22.007: E/AndroidRuntime(12117): at dalvik.system.NativeStart.main(Native Method)
The error line indicate herE:
localHumSymbol.setHumidity(hvalue);
I am writing a simple stopwatch application for android which will just keep the counter updating each second when pressed start, and pause it with the same button. In my main.xml layout I have a TextView and a Button, and nothing else.
Here's what I've written so far.
public class MainActivity extends Activity implements View.OnClickListener {
private Button btnToggle;
private TextView tvStopwatch;
public Handler updateStopwatch;
private enum Status {
WORKING,
STOPPED
}
private Status stopwatchStatus;
private void toggleStatus() {
if (stopwatchStatus == Status.WORKING) {
stopwatchStatus = Status.STOPPED;
Stopwatch.getStopwatch().dispose();
btnToggle.setText("Start");
}else{
stopwatchStatus = Status.WORKING;
Stopwatch.getStopwatch().start();
btnToggle.setText("Stop");
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initView();
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnToggle:
toggleStatus();
break;
}
}
private void initView() {
btnToggle = (Button) findViewById(R.id.btnToggle);
tvStopwatch = (TextView) findViewById(R.id.tvStopwatch);
updateStopwatch = new Handler(){
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
tvStopwatch.setText(msg.what);
}
};
Stopwatch.getStopwatch().setHandler(updateStopwatch);
btnToggle.setOnClickListener(this);
stopwatchStatus = Status.STOPPED;
}
public static class Stopwatch {
private int timestamp;
private boolean working;
private Handler updateStopwatch;
private Stopwatch() {
}
private static Stopwatch stopwatch;
public static Stopwatch getStopwatch() {
if (stopwatch == null) {
stopwatch = new Stopwatch();
}
return stopwatch;
}
public void setHandler(Handler updateStopwatch){
this.updateStopwatch = updateStopwatch;
}
public void start() {
if (!working) {
working = true;
Thread tick = new Thread() {
public void run() {
while (working) {
try {
sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
} finally {
timestamp++;
updateStopwatch.sendEmptyMessage(timestamp);
}
}
}
};
tick.start();
}
}
public void dispose() {
working = false;
}
}
}
The point is, I want my Stopwatch work in it's separate thread, and to have a handler in my main UI thread which will keep updating the TextView, but when I debug my app, it keeps throwing an exception on this line
tvStopwatch.setText(msg.what);
I am quite new to Handlers, so I guess I'm just missing something fundamental.
Here is also the log for the exception
android.content.res.Resources$NotFoundException: String resource ID #0x1
at android.content.res.Resources.getText(Resources.java:1057)
at android.widget.TextView.setText(TextView.java:4186)
at unisoftdevelopment.com.stopwatch.MainActivity$1.handleMessage(MainActivity.java:61)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5279)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
at dalvik.system.NativeStart.main(Native Method)
Please help to find out the problem, thanks in advance.
Common mistake to make: setText() has an overload that takes an integer (which must be a string resource ID, e.g. R.string.my_string).
When you receive the message:
tvStopwatch.setText(msg.what);
It's attempting to resolve msg.what as a string resource, and crashing when it can't be found. You should instead cast the timestamp to a string, and use that instead:
tvStopwatch.setText(String.valueOf(msg.what));
I try to get current location and user activity, following the guide from
http://j.mp/io13-location the "checkpoint_final"
but i got those error when i run the program.
my logCat:
02-21 18:12:38.439: E/AndroidRuntime(3798): FATAL EXCEPTION: main
02-21 18:12:38.439: E/AndroidRuntime(3798): Process: com.android.google.codelab.location, PID: 3798
02-21 18:12:38.439: E/AndroidRuntime(3798): java.lang.RuntimeException: Unable to resume activity {com.android.google.codelab.location/com.android.google.codelab.location.LocationActivity}: java.lang.IllegalStateException: Not connected. Call connect() and wait for onConnected() to be called.
02-21 18:12:38.439: E/AndroidRuntime(3798): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2788)
02-21 18:12:38.439: E/AndroidRuntime(3798): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2817)
02-21 18:12:38.439: E/AndroidRuntime(3798): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2250)
02-21 18:12:38.439: E/AndroidRuntime(3798): at android.app.ActivityThread.access$800(ActivityThread.java:135)
02-21 18:12:38.439: E/AndroidRuntime(3798): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
02-21 18:12:38.439: E/AndroidRuntime(3798): at android.os.Handler.dispatchMessage(Handler.java:102)
02-21 18:12:38.439: E/AndroidRuntime(3798): at android.os.Looper.loop(Looper.java:136)
02-21 18:12:38.439: E/AndroidRuntime(3798): at android.app.ActivityThread.main(ActivityThread.java:5017)
02-21 18:12:38.439: E/AndroidRuntime(3798): at java.lang.reflect.Method.invokeNative(Native Method)
02-21 18:12:38.439: E/AndroidRuntime(3798): at java.lang.reflect.Method.invoke(Method.java:515)
02-21 18:12:38.439: E/AndroidRuntime(3798): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
02-21 18:12:38.439: E/AndroidRuntime(3798): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
02-21 18:12:38.439: E/AndroidRuntime(3798): at dalvik.system.NativeStart.main(Native Method)
02-21 18:12:38.439: E/AndroidRuntime(3798): Caused by: java.lang.IllegalStateException: Not connected. Call connect() and wait for onConnected() to be called.
02-21 18:12:38.439: E/AndroidRuntime(3798): at com.google.android.gms.internal.dk.bB(Unknown Source)
02-21 18:12:38.439: E/AndroidRuntime(3798): at com.google.android.gms.internal.fm.a(Unknown Source)
02-21 18:12:38.439: E/AndroidRuntime(3798): at com.google.android.gms.internal.fm$c.bB(Unknown Source)
02-21 18:12:38.439: E/AndroidRuntime(3798): at com.google.android.gms.internal.fl.requestLocationUpdates(Unknown Source)
02-21 18:12:38.439: E/AndroidRuntime(3798): at com.google.android.gms.internal.fm.requestLocationUpdates(Unknown Source)
02-21 18:12:38.439: E/AndroidRuntime(3798): at com.google.android.gms.internal.fm.requestLocationUpdates(Unknown Source)
02-21 18:12:38.439: E/AndroidRuntime(3798): at com.google.android.gms.location.LocationClient.requestLocationUpdates(Unknown Source)
02-21 18:12:38.439: E/AndroidRuntime(3798): at com.android.google.codelab.location.LocationActivity.restartLocationClient(LocationActivity.java:248)
02-21 18:12:38.439: E/AndroidRuntime(3798): at com.android.google.codelab.location.LocationActivity.onResume(LocationActivity.java:197)
02-21 18:12:38.439: E/AndroidRuntime(3798): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1192)
02-21 18:12:38.439: E/AndroidRuntime(3798): at android.app.Activity.performResume(Activity.java:5310)
02-21 18:12:38.439: E/AndroidRuntime(3798): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2778)
02-21 18:12:38.439: E/AndroidRuntime(3798): ... 12 more
my Code
public class LocationActivity extends FragmentActivity {
public static String TAG = "LocationActivity";
public static boolean isAppForeground = false;
private static final int ERROR_DIALOG_ON_CREATE_REQUEST_CODE = 4055;
private static final int ERROR_DIALOG_ON_RESUME_REQUEST_CODE = 4056;
// Shared variables
private GoogleMap mMap;
private Dialog errorDialog;
// Location Request variables
private LocationClient mLocationClient;
private TextView mLocationStatus;
private LocationCallback mLocationCallback = new LocationCallback();
private Location mLastLocation;
private static final int LOCATION_UPDATES_INTERVAL = 10000; // Setting 10 sec interval for location updates
// Activity Recognition variables
private ActivityRecognitionClient mActivityRecognitionClient;
private ActivityRecognitionCallback mActivityRecognitionCallback = new ActivityRecognitionCallback();
public static final String ACTION_ACTIVITY_RECOGNITION =
"com.android.google.codelab.location.LocationActivity.ACTIVITY_RECOGNITION";
private static final int ACTIVITY_UPDATES_INTERVAL = 4000;
private PendingIntent mActivityRecognitionPendingIntent;
private Switch mSwitch;
private ActivityRecognitionIntentReceiver mActivityRecognitionIntentReceiver;
// Geo Fencing variables
private GeoFenceCallback mGeoFenceCallback = new GeoFenceCallback();
private int id = 0;
private static final float GEOFENCE_RADIUS = 100;
private HashMap<String, Circle> mGeoFences;
private HashMap<String, Circle> mTriggeringFences;
public static final String ACTION_GEOFENCE =
"com.android.google.codelab.location.LocationActivity.GEOFENCE";
private TextView mGeoFenceStatus;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
checkGooglePlayServiceAvailability(ERROR_DIALOG_ON_CREATE_REQUEST_CODE);
}
private void init() {
// Initialize map
if (mMap == null) {
FragmentManager myFragmentManager = getSupportFragmentManager();
SupportMapFragment myMapFragment =
(SupportMapFragment) myFragmentManager.findFragmentById(R.id.map);
mMap = myMapFragment.getMap();
}
// Initialize Location Client
mLocationStatus = (TextView) findViewById(R.id.location_status);
if (mLocationClient == null) {
mLocationClient = new LocationClient(this, mLocationCallback, mLocationCallback);
Log.v(LocationActivity.TAG, "Location Client connect");
if (!(mLocationClient.isConnected() || mLocationClient.isConnecting())) {
mLocationClient.connect();
}
}
// Initialize Action Recognition
if (mActivityRecognitionClient == null) {
mActivityRecognitionClient =
new ActivityRecognitionClient(this,
mActivityRecognitionCallback, mActivityRecognitionCallback);
}
mSwitch = (Switch) findViewById(R.id.swtich);
mSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
startActivityDetection(buttonView);
} else {
stopActivityDetection(buttonView);
}
}
});
if (mActivityRecognitionIntentReceiver == null) {
mActivityRecognitionIntentReceiver = new ActivityRecognitionIntentReceiver();
registerReceiver(mActivityRecognitionIntentReceiver,
new IntentFilter(LocationActivity.ACTION_ACTIVITY_RECOGNITION));
}
// Initialize Geo Fencing
mGeoFenceStatus = (TextView) findViewById(R.id.geo_fence_status);
if (mGeoFences == null) {
mGeoFences = new HashMap<String, Circle>();
}
if (mTriggeringFences == null) {
mTriggeringFences = new HashMap<String, Circle>();
}
// Setup map to allow adding Geo Fences
mMap.getUiSettings().setAllGesturesEnabled(true);
mMap.setOnMapLongClickListener(mGeoFenceCallback);
}
#Override
public void onPause() {
super.onPause();
// Indicate the application is in background
isAppForeground = false;
if (mLocationClient.isConnected()) {
mLocationClient.removeLocationUpdates(mLocationCallback);
mLocationClient.disconnect();
}
}
#Override
public void onResume() {
super.onResume();
// Indicate the application is in foreground
isAppForeground = true;
checkGooglePlayServiceAvailability(ERROR_DIALOG_ON_RESUME_REQUEST_CODE);
restartLocationClient();
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(mActivityRecognitionIntentReceiver);
mActivityRecognitionIntentReceiver = null;
}
private void checkGooglePlayServiceAvailability(int requestCode) {
// Query for the status of Google Play services on the device
int statusCode = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(getBaseContext());
if (statusCode == ConnectionResult.SUCCESS) {
init();
} else {
if (GooglePlayServicesUtil.isUserRecoverableError(statusCode)) {
errorDialog = GooglePlayServicesUtil.getErrorDialog(statusCode,
this, requestCode);
errorDialog.show();
} else {
// Handle unrecoverable error
}
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case ERROR_DIALOG_ON_CREATE_REQUEST_CODE:
init();
break;
case ERROR_DIALOG_ON_RESUME_REQUEST_CODE:
restartLocationClient();
break;
}
}
}
private void restartLocationClient() {
if (!(mLocationClient.isConnected() || mLocationClient.isConnecting())) {
mLocationClient.connect(); // Somehow it becomes connected here
return;
}
LocationRequest request = LocationRequest.create();
request.setInterval(LOCATION_UPDATES_INTERVAL);
request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationClient.requestLocationUpdates(request, mLocationCallback);
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuItem menuItem = menu.add(R.string.clear_map);
menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
menuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
clearMap();
return true;
}
});
return true;
}
public void clearMap() {
mMap.clear();
mLastLocation = null;
mGeoFenceCallback.removeGeoFences();
}
private class LocationCallback implements ConnectionCallbacks, OnConnectionFailedListener,
LocationListener {
#Override
public void onConnected(Bundle connectionHint) {
Log.v(LocationActivity.TAG, "Location Client connected");
// Display last location
Location location = mLocationClient.getLastLocation();
if (location != null) {
handleLocation(location);
}
// Request for location updates
LocationRequest request = LocationRequest.create();
request.setInterval(LOCATION_UPDATES_INTERVAL);
request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationClient.requestLocationUpdates(request, mLocationCallback);
}
#Override
public void onDisconnected() {
Log.v(LocationActivity.TAG, "Location Client disconnected by the system");
}
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.v(LocationActivity.TAG, "Location Client connection failed");
}
#Override
public void onLocationChanged(Location location) {
if (location == null) {
Log.v(LocationActivity.TAG, "onLocationChanged: location == null");
return;
}
// Add a marker iff location has changed.
if (mLastLocation != null &&
mLastLocation.getLatitude() == location.getLatitude() &&
mLastLocation.getLongitude() == location.getLongitude()) {
return;
}
handleLocation(location);
}
private void handleLocation(Location location) {
// Update the mLocationStatus with the lat/lng of the location
Log.v(LocationActivity.TAG, "LocationChanged == #" +
location.getLatitude() + "," + location.getLongitude());
mLocationStatus.setText("Location changed #" + location.getLatitude() + "," +
location.getLongitude());
// Add a marker of that location to the map
LatLng latlongzoom = new LatLng(location.getLatitude(),
location.getLongitude());
String snippet = location.getLatitude() + "," + location.getLongitude();
Marker marker = mMap.addMarker(
new MarkerOptions().position(latlongzoom));
marker.setSnippet(snippet);
marker.setTitle(snippet);
// Center the map to the first marker
if (mLastLocation == null) {
mMap.moveCamera(CameraUpdateFactory.
newCameraPosition(CameraPosition.fromLatLngZoom(
new LatLng(location.getLatitude(), location.getLongitude()),
(float) 16.0)));
}
mLastLocation = location;
}
};
public void startActivityDetection(View v) {
if (!mActivityRecognitionClient.isConnected()) {
mActivityRecognitionClient.connect();
}
}
public void stopActivityDetection(View v) {
if (mActivityRecognitionClient.isConnected()) {
mActivityRecognitionClient.removeActivityUpdates(mActivityRecognitionPendingIntent);
mActivityRecognitionClient.disconnect();
}
}
private class ActivityRecognitionCallback implements ConnectionCallbacks, OnConnectionFailedListener {
#Override
public void onConnected(Bundle connectionHint) {
Log.v(LocationActivity.TAG, "Activity Recognition Client connected");
// Request activity updates
Intent intent = new Intent(LocationActivity.this,
ActivityRecognitionIntentService.class);
intent.setAction(LocationActivity.ACTION_ACTIVITY_RECOGNITION);
mActivityRecognitionPendingIntent = PendingIntent.getService(LocationActivity.this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
mActivityRecognitionClient.requestActivityUpdates(ACTIVITY_UPDATES_INTERVAL,
mActivityRecognitionPendingIntent);
}
#Override
public void onDisconnected() {
Log.v(LocationActivity.TAG, "Activity Recognition Client disconnected by the system");
}
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.v(LocationActivity.TAG,
"Activity Recognition Client connection failed " + result.getErrorCode());
}
};
private class GeoFenceCallback implements OnMapLongClickListener,
OnAddGeofencesResultListener, OnRemoveGeofencesResultListener {
#Override
public void onMapLongClick(LatLng point) {
Log.v(LocationActivity.TAG,
"onMapLongClick == " + point.latitude + "," + point.longitude);
CircleOptions circleOptions = new CircleOptions();
circleOptions.center(point).radius(GEOFENCE_RADIUS).strokeColor(
android.graphics.Color.BLUE).strokeWidth(2);
Circle circle = mMap.addCircle(circleOptions);
String key = Integer.toString(id);
id++;
mGeoFences.put(key, circle);
addGeoFences();
}
// Creates Geofence objects from all circles on the map and calls addGeofences API.
private void addGeoFences() {
List<Geofence> list = new ArrayList<Geofence>();
for (Map.Entry<String, Circle> entry : mGeoFences.entrySet()) {
Circle circle = entry.getValue();
Log.v(LocationActivity.TAG, "points == " +
circle.getCenter().latitude + "," +
circle.getCenter().longitude);
Geofence geofence = new Geofence.Builder()
.setRequestId(entry.getKey())
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER |
Geofence.GEOFENCE_TRANSITION_EXIT)
.setCircularRegion(circle.getCenter().latitude,
circle.getCenter().longitude,
(float) circle.getRadius())
.setExpirationDuration(Geofence.NEVER_EXPIRE).build();
list.add(geofence);
}
if (list.isEmpty()) {
return;
}
// Clear off all the currently triggering geo_fences before new fences
// are added.
for (Circle triggeringGeoFence : mTriggeringFences.values()) {
triggeringGeoFence.remove();
}
mTriggeringFences.clear();
Log.v(LocationActivity.TAG, "addingGeoFences size = " + list.size());
mLocationClient.addGeofences(list, getPendingIntent(), this);
}
private PendingIntent getPendingIntent() {
Intent intent = new Intent(ACTION_GEOFENCE);
intent.setComponent(new ComponentName(LocationActivity.this,
GeoFenceIntentReceiver.class));
return PendingIntent.getBroadcast(LocationActivity.this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
}
private void removeGeoFences() {
List<String> requestIdsForRemoval = new ArrayList<String>();
if (mGeoFences.isEmpty()) return;
for (Map.Entry<String, Circle> entry : mGeoFences.entrySet()) {
String requestId = entry.getKey();
Circle circle = entry.getValue();
if (circle != null) {
circle.remove();
id --;
Log.v(LocationActivity.TAG, "RemoveGeoFence requestId == " + requestId);
Circle triggeringCircle = mTriggeringFences.get(requestId);
if (triggeringCircle != null) {
triggeringCircle.remove();
}
requestIdsForRemoval.add(requestId);
}
}
mGeoFences.clear();
mTriggeringFences.clear();
mLocationClient.removeGeofences(requestIdsForRemoval, this);
}
#Override
public void onAddGeofencesResult(int statusCode,
String[] geofenceRequestIds) {
StringBuilder builder = new StringBuilder();
for (int i = 0 ; i < geofenceRequestIds.length - 1; ++i) {
builder.append(geofenceRequestIds[i]);
builder.append(",");
}
builder.append(geofenceRequestIds[geofenceRequestIds.length - 1]);
Log.v(LocationActivity.TAG, "Added Geofences == "
+ statusCodeToString(statusCode) + " " + builder.toString());
mGeoFenceStatus.setText("Added Geofences "
+ statusCodeToString(statusCode) + " " + builder.toString());
}
private String statusCodeToString(int statusCode) {
switch(statusCode) {
case LocationStatusCodes.SUCCESS :
return "SUCCESS";
case LocationStatusCodes.GEOFENCE_NOT_AVAILABLE :
return "GEOFENCE_NOT_AVAILABLE";
case LocationStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES :
return "GEOFENCE_TOO_MANY_GEOFENCES";
case LocationStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS :
return "GEOFENCE_TOO_MANY_PENDING_INTENTS";
case LocationStatusCodes.ERROR :
return "ERROR";
}
return "UNKNOWN";
}
#Override
public void onRemoveGeofencesByPendingIntentResult(int statusCode, PendingIntent pendingIntent) {
// Do nothing
}
#Override
public void onRemoveGeofencesByRequestIdsResult(int statusCode,
String[] geofenceRequestIds) {
StringBuilder builder = new StringBuilder();
for (int i = 0 ; i < geofenceRequestIds.length - 1; ++i) {
builder.append(geofenceRequestIds[i]);
builder.append(",");
}
builder.append(geofenceRequestIds[geofenceRequestIds.length - 1]);
Log.v(LocationActivity.TAG, "Removed Geofence " +
statusCodeToString(statusCode) + " " + builder.toString());
mGeoFenceStatus.setText("Removed Geofences request_ids = " +
builder.toString() + " " + statusCodeToString(statusCode));
}
};
// Triggered when startAcitivity method is called in GeoFenceIntentReceiver.
// Updates UI as geofences are entered/exited.
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
// getIntent() should always return the most recent
setIntent(intent);
boolean receiverStarted =
intent.getBooleanExtra("RECEIVER_STARTED", false);
if (!receiverStarted) {
return;
}
Bundle bundle = intent.getParcelableExtra("geo_fences");
ArrayList<String> requestIds =
bundle.getStringArrayList("request_ids");
if (requestIds == null) {
Log.v(LocationActivity.TAG, "request_ids == null");
return;
}
int transition = intent.getIntExtra("transition", -2);
for (String requestId : requestIds) {
Log.v(LocationActivity.TAG, "Triggering Geo Fence requestId "
+ requestId);
if (transition == Geofence.GEOFENCE_TRANSITION_ENTER) {
Circle circle = mGeoFences.get(requestId);
if (circle == null) {
continue;
}
Log.v(LocationActivity.TAG, "triggering_geo_fences enter == "
+ requestId);
// Add a superimposed red circle when a geofence is entered and
// put the corresponding object in triggering_fences.
CircleOptions circleOptions = new CircleOptions();
circleOptions.center(circle.getCenter())
.radius(circle.getRadius())
.fillColor(Color.argb(100,100, 0, 0));
Circle newCircle = mMap.addCircle(circleOptions);
mTriggeringFences.put(requestId, newCircle);
} else if (transition == Geofence.GEOFENCE_TRANSITION_EXIT) {
Log.v(LocationActivity.TAG, "triggering_geo_fences exit == "
+ requestId);
Circle circle = mTriggeringFences.get(requestId);
if (circle == null) {
continue;
}
// Remove the superimposed red circle from the map and the
// corresponding Circle object from triggering_fences hash_map.
circle.remove();
mTriggeringFences.remove(requestId);
}
}
return;
}
}
2nd class
public class ActivityRecognitionIntentService extends IntentService {
public ActivityRecognitionIntentService() {
super("ActivityRecognitionIntentService");
}
public ActivityRecognitionIntentService(String name) {
super(name);
}
#Override
protected void onHandleIntent(Intent intent) {
if (intent.getAction() != LocationActivity.ACTION_ACTIVITY_RECOGNITION) {
return;
}
if (ActivityRecognitionResult.hasResult(intent)) {
ActivityRecognitionResult result = ActivityRecognitionResult
.extractResult(intent);
DetectedActivity detectedActivity = result
.getMostProbableActivity();
int activityType = detectedActivity.getType();
Log.v(LocationActivity.TAG, "activity_type == " + activityType);
// Put the activity_type as an intent extra and send a broadcast.
Intent send_intent = new Intent(
LocationActivity.ACTION_ACTIVITY_RECOGNITION);
send_intent.putExtra("activity_type", activityType);
sendBroadcast(send_intent);
}
}
}
edited add the main part of the code
Please Modify your restartLocationClient() Method like this:
private void restartLocationClient() {
if (mLocationClient == null) {
mLocationClient = new LocationClient(this, mLocationCallback, mLocationCallback);
Log.v(LocationActivity.TAG, "Location Client connect");
if (!(mLocationClient.isConnected() || mLocationClient.isConnecting()))
{
mLocationClient.connect(); // Somehow it becomes connected here
return;
}
}
LocationRequest request = LocationRequest.create();
request.setInterval(LOCATION_UPDATES_INTERVAL);
request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationClient.requestLocationUpdates(request, mLocationCallback);
}
It seems that your mLocationClient is null in this Method.
I hope this helps.
I know it's pretty late for this answer.
But for future reference, I'll post it anyways.
Basically, we have to understand the onConnect() method better. I find the explanation in this thread to be useful.
From there the workaround for this issue is pretty much straightforward.
Solution: restartLocationClient() is only called when mLocationClient.isConnected() returns true.
So, in your onResume method should look like the following:
if (mLocationClient.isConnected()) {
restartLocationClient();
}
Now it will work.
I've implemented an SlidingMenu, I set it up with SlidingMenu sm = getSlidingMenu() in the activity I want to use the menu. The problem I've got I want to toggle it via a button I've created on a canvas. If I click these area on the canvas it will stop drawing and open the sliding menu - works until here. But then I added some content with an linearlayout and a textview in it, on clicking the textview the text changes (kind of menu to change some options). And after it changed once the next click should toggle the sliding menu again.
I've created the behind view's in another class, and triggered a method in the activity containing the slidingmenu, it looks like this:
public void toggleSM() {
Thread splash = new Thread(new Runnable() {
#SuppressWarnings("static-access")
#Override
public void run() {
try {
Thread.currentThread().sleep(500);
getSlidingMenu().toggle(true);
Thread.currentThread().sleep(1000);
animateButton.setLeftState(false);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
splash.start();
}
I added the sleep to avoid any problems caused by the sm animation or changing content, the aninamteButton is to trigger the drawing of the canvas again. But it throws a nullpointer exception. With and without animation of the slidingmenu.
EDIT:
The two classes I'm using:
public class Ingame extends SlidingActivity implements OnTouchListener{
private LeftMenu lm;
private SlidingMenu sm;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sh = new ScreenHandler(this);
fh = new FilesHandler(this);
animateMap = new AnimateMap(this);
ch = new CoordsHandler(this);
animateButton = new AnimateButton();
sched = new Schedule();
lm = new LeftMenu(this);
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setupViews();
lm.setupLeftMenu();
setBehindContentView(lm.getLayout());
setupSlidingMenu();
}
#Override
protected void onPause() {
super.onPause();
gb.pause();
}
#Override
protected void onResume() {
super.onResume();
gb.resume();
}
#SuppressWarnings("deprecation")
public void setupViews() {
FrameLayout fl = new FrameLayout(getBaseContext());
LayoutParams sizeP = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
fl.setLayoutParams(sizeP);
fl.setBackgroundColor(Color.rgb(0, 153, 204));
gb = new GameBoard(getBaseContext());
LayoutParams fillP = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
gb.setLayoutParams(fillP);
gb.setOnTouchListener(Ingame.this);
fl.addView(gb);
setContentView(fl);
}
public void setupSlidingMenu() {
sm = getSlidingMenu();
sm.setTouchModeAbove(SlidingMenu.TOUCHMODE_NONE);
sm.setMenu(lm.getLayout());
}
#SuppressWarnings("static-access")
#Override
public boolean onTouch(View v, MotionEvent e) {
float distX, distY;
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = e.getX();
startY = e.getY();
gb.movedDist.put("startX", startX);
gb.movedDist.put("startY", startY);
finX = finY = -1;
gb.movedDist.put("finX", finX);
gb.movedDist.put("finY", finY);
break;
case MotionEvent.ACTION_MOVE:
finX = e.getX();
finY = e.getY();
distX = startX - finX;
distY = startY - finY;
if(!checkUnvalidValues() && (Math.abs(distX) > sh.getTSize() || Math.abs(distY) > sh.getTSize())) {
int rectDistX = (int) (distX/sh.getTSize());
int rectDistY = (int) (distY/sh.getTSize());
noMove = false;
if(!checkEdges(rectDistX, rectDistY)) {
animateMap.animateXYDistance(rectDistX, rectDistY);
startX = e.getX();
startY = e.getY();
}
}
break;
case MotionEvent.ACTION_UP:
finX = e.getX();
finY = e.getY();
if(checkButton() == IngameButton.PP) {
animateButton.changePPState();
break;
}
if(checkButton() == IngameButton.LEFT) { //WHERE I TRIGGER THE SLIDINGMENU
animateButton.setLeftState(true);
if(!animateButton.getPPState())
animateButton.setPPState(true);
sm.toggle(true);
lm.openLeftMenu();
break;
}
if(noMove && !checkUnvalidValues())
animateMap.tellCoordinate(finX, finY);
noMove = true;
break;
}
return true;
}
private boolean checkUnvalidValues() {
if(startX <= sh.getSideSize()-1 || startX >= (sh.getScreenWidth()-sh.getSideSize()))
return true;
if(startY <= -1 || startY >= (sh.getScreenHeight()-sh.getBottomGUISize()))
return true;
if(finX <= sh.getSideSize()-1 || finX >= (sh.getScreenWidth()-sh.getSideSize()))
return true;
if(finY <= -1 || finY >= (sh.getScreenHeight()-sh.getBottomGUISize()))
return true;
return false;
}
public SlidingMenu getSM() {
return sm;
}
public void toggleSM() {
runOnUiThread(new Runnable() {
#SuppressWarnings("static-access")
#Override
public void run(){
getSlidingMenu().toggle(true);
SlidingMenu sm = getSlidingMenu();
sm.getAlpha();
try {
Thread.currentThread().sleep(1000);
animateButton.setLeftState(false);
} catch(InterruptedException e) {
e.printStackTrace();
}
}
});
}
LeftMenu:
public class LeftMenu {
private Context context;
private Ingame ingame;
private AnimateButton animateButton;
private LinearLayout ll;
private LinearLayout.LayoutParams llp;
private static LeftMenuPage page;
private static int buttonTextSize = 15;
public LeftMenu(Context context) {
this.context = context;
ingame = new Ingame();
animateButton = new AnimateButton();
}
public void setupLeftMenu() {
page = LeftMenuPage.OVERVIEW;
setupLinearLayout();
setupButtons();
}
#SuppressWarnings("deprecation")
private void setupLinearLayout() {
ll = new LinearLayout(context);
ll.setOrientation(LinearLayout.VERTICAL);
ll.setBackgroundColor(0xff000000);
llp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT);
ll.setLayoutParams(llp);
}
public LinearLayout getLayout() {
return ll;
}
private void setupButtons() {
final TextView t1 = new TextView(context);
t1.setBackgroundColor(0xff000000);
t1.setTextColor(0xffffffff);
t1.setTypeface(null, Typeface.NORMAL);
t1.setTextSize(buttonTextSize);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
lp.weight = 1.0f;
lp.gravity=1;
t1.setLayoutParams(lp);
String content = null;
if(page == LeftMenuPage.OVERVIEW) {
content = "Creation Mode";
}
else {
content = "Back";
}
t1.setText(content);
ll.addView(t1);
t1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
t1.setTextColor(0xffcccccc);
switch(page) {
case OVERVIEW:
page = LeftMenuPage.CREATE;
t1.setText("Create Dwarves");
ingame.toggleSM();
if(!animateButton.getPPState())
animateButton.setPPState(true);
break;
case CREATE:
ingame.toggleSM();
if(!animateButton.getPPState())
animateButton.setPPState(true);
break;
}
t1.setTextColor(0xffffffff);
}
});
}
public void openLeftMenu() {
page = LeftMenuPage.OVERVIEW;
}
}
EDIT 2:
05-10 15:14:53.535: E/AndroidRuntime(25064): FATAL EXCEPTION: main
05-10 15:14:53.535: E/AndroidRuntime(25064): java.lang.NullPointerException
05-10 15:14:53.535: E/AndroidRuntime(25064): at com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivity.getSlidingMenu(SlidingActivity.java:104)
05-10 15:14:53.535: E/AndroidRuntime(25064): at me.G4meM0ment.DwarvenSkill.Ingame$1.run(Ingame.java:234)
05-10 15:14:53.535: E/AndroidRuntime(25064): at android.os.Handler.handleCallback(Handler.java:615)
05-10 15:14:53.535: E/AndroidRuntime(25064): at android.os.Handler.dispatchMessage(Handler.java:92)
05-10 15:14:53.535: E/AndroidRuntime(25064): at android.os.Looper.loop(Looper.java:137)
05-10 15:14:53.535: E/AndroidRuntime(25064): at android.app.ActivityThread.main(ActivityThread.java:4918)
05-10 15:14:53.535: E/AndroidRuntime(25064): at java.lang.reflect.Method.invokeNative(Native Method)
05-10 15:14:53.535: E/AndroidRuntime(25064): at java.lang.reflect.Method.invoke(Method.java:511)
05-10 15:14:53.535: E/AndroidRuntime(25064): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:994)
05-10 15:14:53.535: E/AndroidRuntime(25064): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:761)
05-10 15:14:53.535: E/AndroidRuntime(25064): at dalvik.system.NativeStart.main(Native Method)
StackTrace, as I already mentionen in some comments, getSlidingMenu returns null and mHelper (SlidingActivityHelper) causes this because it's null
getSlidingMenu().toggle(true);
has to run on the UI Thread. Move it inside and Handler or if your are inside an Activity use
runOnUiThread(new Runnable() {
public void run(){
getSlidingMenu().toggle(true);
}
});