So i'm trying to implement a timer in a custom view class which is a subclass that I call from an activity but its throwing me this error
FATAL EXCEPTION: main java.lang.NullPointerException
at com.alfredochapa.crazymaze.Nivel$1.onTick(Nivel.java:133)
This is my current code and i cannot get what im implementing wrong, any suggestions o how i can make it to work, i do really need the countdown timer to be in this class
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.CountDownTimer;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;
import java.util.concurrent.TimeUnit;
import java.util.logging.Handler;
/**
* Created by alfredochapa on 27/11/15.
*/
public class Nivel extends View{
TextView text1;
private static final String FORMAT = "%02d:%02d:%02d";
int seconds , minutes;
int width, height;
int tiempo;
private Ball ball;
private Vector<Rect> listaRects;
private Display mDisplay;
public Nivel(Context context, AttributeSet attrs) throws IOException, JSONException {
super(context, attrs);
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
mDisplay = wm.getDefaultDisplay();
width = mDisplay.getWidth();
height = mDisplay.getHeight();
//Obtenemos el valor del atributo level que esta en el layout
int level = Integer.parseInt(attrs.getAttributeValue(null, "level"));
//Se lee el archivo con el JSON
InputStream is = getResources().openRawResource(R.raw.levels);
Writer writer = new StringWriter();
char[] buffer = new char[1024];
try {
Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
int n;
while ((n = reader.read(buffer)) != -1) {
writer.write(buffer, 0, n);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
is.close();
}
String jsonString = writer.toString();
//Obtenemos los valores dependiendo del nivel
JSONArray myListsAll= new JSONArray(jsonString);
for(int i=0;i<myListsAll.length();i++){
JSONObject jsonobject= (JSONObject) myListsAll.get(i);
int id= Integer.parseInt(jsonobject.optString("level"));
if(id == level){
//Tiempo que tarda el nivel
tiempo = Integer.parseInt(jsonobject.optString("time"));
//Obtener coordenadas para la bola
JSONObject jsonobjectBall = jsonobject.getJSONObject("ball");
double bx = Integer.parseInt(jsonobjectBall.optString("x")) /100.0;
double by = Integer.parseInt(jsonobjectBall.optString("y")) /100.0;
//Se crea la bola con las coordenadas
Drawable drawableBall = context.getResources().getDrawable(R.drawable.ball);
ball = new Ball(this, drawableBall, (int)(width*bx), (int)(height*by), (int)(width*.1), (int)(width*.1));
listaRects = new Vector<Rect>();
JSONArray wallList = jsonobject.getJSONArray("wall");
for(int j=0; j<wallList.length();j++){
JSONObject jsonobjectwall= (JSONObject) wallList.get(j);
double x1 = Integer.parseInt(jsonobjectwall.optString("x1")) / 100.0;
double y1 = Integer.parseInt(jsonobjectwall.optString("y1")) / 100.0;
double x2 = Integer.parseInt(jsonobjectwall.optString("x2")) / 100.0;
double y2 = Integer.parseInt(jsonobjectwall.optString("y2")) / 100.0;
Rect r = new Rect((int) (width*x1), (int) (height*y1), (int) (width*x2), (int) (height*y2));
listaRects.add(r);
}
}
}
text1=(TextView)findViewById(R.id.timer);
new CountDownTimer(16069000, 1000) { // adjust the milli seconds here
public void onTick(long millisUntilFinished) {
text1.setText("" + String.format(FORMAT,
TimeUnit.MILLISECONDS.toHours(millisUntilFinished),
TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished) - TimeUnit.HOURS.toMinutes(
TimeUnit.MILLISECONDS.toHours(millisUntilFinished)),
TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) - TimeUnit.MINUTES.toSeconds(
TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished))));
}
public void onFinish() {
text1.setText("done!");
}
}.start();
}
@Override
synchronized protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
ball.dibujaFigura(canvas);
Paint pincel = new Paint();
pincel.setColor(Color.argb(255, 164, 199, 57));
pincel.setStrokeWidth(5);
pincel.setStyle(Paint.Style.FILL);
for (Rect rec: listaRects) {
canvas.drawRect(rec, pincel);
}
}
public class Ball {
private Drawable drawable;
private int width, height;
private View view;
private int x, y;
public Ball(View view, Drawable drawable,int x, int y, int w, int h) {
this.view = view;
this.drawable = drawable;
this.width = w;
this.height = h;
this.x = x;
this.y = y;
}
public void dibujaFigura(Canvas canvas){
canvas.save();
drawable.setBounds(x - width/2, y - height/2, x + width/2, y + height/2);
drawable.draw(canvas);
canvas.restore();
}
}
}
This is the textview that i want the timer to go on
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/timer"
android:text="Timer"
android:layout_gravity="right|top" />