I am very close to finish my project that is related to count steps , distance covered and calculate velocity. I am using TYPE_COUNTER_STEP sensor to calculate the steps and using formulas to calculate distance i.e 0.415 for men and 0.413 for women to get foot length by multiplying with height So far every thing is working fine But i am suck to calculate the velocity. I do not know how to calculate, i mean i know s = vt but i need time to get the velocity/step. Anyone have any idea how to achieve that. This is the last part of my project. I have also look for it on the internet but i did not get working method to calculate the time. Someone suggest me to use timestamp but i used that but unfortunately i get infinity text instead of velocity
I cannot use GPS to calculate the velocity because GPS is not available all the time i.e inside tunnel or underground etc
Thanks
package com.lijianzhong13354146.coeur1;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.format.DateUtils;
import android.view.Display;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.TimeUnit;
public class AccurateStepCounter extends AppCompatActivity {
private long timestamp;
private TextView textViewStepCounter;
private TextView textViewStepDetector;
private Thread detectorTimeStampUpdaterThread;
private Handler handler;
Toolbar toolbar ;
private Button buttonStop ;
TextView stepValue ;
TextView distanceValue ;
TextView distanceTitle ;
int getCurrentStepValue ;
int actualStepTaken ;
SharedPreferences sharedPreferences ;
SharedPreferences.Editor editor ;
SharedPreferences sharedPreferencesFromSetting ;
SharedPreferences.Editor editorFromSetting ;
private boolean isRunning = true;
ArrayList<Step> arrayList ;
String gettingPersonHeight ;
double gettingPersonHeightInDoule ;
double step_length ;
SharedPreferences getSharedPreferencesHeight ;
SharedPreferences.Editor getEditoHeight ;
double timeInSecond ;
SharedPreferences sharedPreferencesGetGender ;
SharedPreferences.Editor editorGetGender;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_accurate_step_counter);
buttonStop = (Button) findViewById(R.id.buttonSTOP);
toolbar = (Toolbar) findViewById(R.id.toolbar);
stepValue = (TextView) findViewById(R.id.step_value);
distanceValue = (TextView) findViewById(R.id.distance_value);
arrayList = new ArrayList<>();
sharedPreferences = getSharedPreferences("saveInformation" , MODE_PRIVATE) ;
sharedPreferencesFromSetting = getSharedPreferences("EmailSave" , MODE_PRIVATE);
sharedPreferencesGetGender = getSharedPreferences("saveInformation" , MODE_PRIVATE);
getSharedPreferencesHeight = getSharedPreferences("Height" , MODE_PRIVATE);
distanceTitle = (TextView) findViewById(R.id.distance_title);
gettingPersonHeightInDoule = Double.parseDouble(
getSharedPreferencesHeight.getString("saveHeight" , "0"))/100;
if (sharedPreferencesGetGender.getString("GENDER" , null).equals("Male") ){
step_length = 0.415 * gettingPersonHeightInDoule ;
}else {
step_length = 0.413 * gettingPersonHeightInDoule ;
}
ToolbarConfig();
MediaPlayer mediaPlayer1 = MediaPlayer.create(this , R.raw.boom);
mediaPlayer1.start();
registerForSensorEvents();
onStopButtonClick();
// setupDetectorTimestampUpdaterThread();
}
#Override
public void onBackPressed() {
}
public void onStopButtonClick () {
buttonStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int actualSteps = getCurrentStepValue - arrayList.get(0);
editor = sharedPreferences.edit() ;
editor.putString("STEPS" , String.valueOf(actualSteps));
editor.commit() ;
startActivity(new Intent(AccurateStepCounter.this , FinalResultDisplay.class));
}
});
}
public void ToolbarConfig () {
toolbar.setTitle(getResources().getString(R.string.app_title));
toolbar.setSubtitle("Pedometer");
toolbar.setTitleTextColor(Color.WHITE);
toolbar.setSubtitleTextColor(Color.WHITE);
setSupportActionBar(toolbar);
}
public void registerForSensorEvents() {
SensorManager sManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
// Step Counter
sManager.registerListener(new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent event) {
Step step = new Step(event.values[0], System.currentTimeMillis());
arrayList.add(step);
getCurrentStepValue = (int) step.getStep();
stepValue.setText(getCurrentStepValue - arrayList.get(0) + "");
double distaneCovered = step_length * (getCurrentStepValue - arrayList.get(0));
// the elapsed time beetween 2 step will be:
if (arrayList.size() > 2) {
Step lastStep = arrayList.get(arrayList.size() - 1);
Step previousStep = arrayList.get(arrayList.size() - 2);
long msElapsedTime = lastStep.getTimestamp() - previousStep.getTimestamp();
timeInSecond = TimeUnit.MILLISECONDS.toSeconds(msElapsedTime);
}
double getVelocity = distaneCovered / timeInSecond ;
// distanceTitle shows the speed for now
distanceTitle.setText(getVelocity + " m/s");
distanceValue.setText("" + distaneCovered);
/* float steps = event.values[0];
arrayList.add((int)steps);
getCurrentStepValue = (int) steps ;
double distanceCovered = (step_length * (getCurrentStepValue - arrayList.get(0))) /1000;
stepValue.setText(getCurrentStepValue - arrayList.get(0) + "");
distanceValue.setText("" + String.format("%.2f" , distanceCovered));*/
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}, sManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER),
SensorManager.SENSOR_DELAY_FASTEST);
}
}
class Step {
private float step;
private long timestamp;
Step (float step , long timestamp) {
this.step = step;
this.timestamp = timestamp ;
}
public void setStep(float step) {
this.step = step;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public float getStep() {
return step;
}
public long getTimestamp() {
return timestamp;
}
// getters
// setters
}
You can calculate the elapsed time beetween 2 steps creating a Step class containing the timestamp as field. Then subtract the previous timestamp at the last!
public class Step {
private float step;
private long timestamp;
// constructor
// getters
// setters
}
#Override
public void onSensorChanged(SensorEvent event) {
Step step = new Step(event.values[0], System.currentTimeMillis());
arrayList.add(step);
getCurrentStepValue = (int) step.getStep();
stepValue.setText(getCurrentStepValue - arrayList.get(0) + "");
double distaneCovered = step_length * (getCurrentStepValue - arrayList.get(0));
// the elapsed time beetween 2 step will be:
if (arrayList.size() > 2) {
Step lastStep = arrayList.get(arrayList.size() - 1);
Step previousStep = arrayList.get(arrayList.size() - 2);
long msElapsedTime = lastStep.getTimestamp() - previousStep.getTimestamp();
}
distanceValue.setText("" + distaneCovered);
}
So you can do s=v/t
Related
I have put somehow together a code that records my sensor data from the phone and i want to save them as csv file in some directory (maybe DCIM) in the internal Storage on the phone, but i cannot find something similar, i am also new to Android Studio and java.
On the bottom you can see ,i found that code example with
"getExternalFilesDir(null).getAbsolutePath()" , how can i change that , that my file is saved on the phone in internal storage and tell him exactly where so i can find it later and use it further ?
package com.example.shakedemo;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.CompoundButton;
import android.widget.ProgressBar;
import android.widget.Switch;
import android.widget.TextView;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
TextView txt_currentAccel, txt_prevAccel, txt_acceleration, txt_temp;
ProgressBar prog_shakeMeter;
Switch switch1;
//define Sensor Variables
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private SensorManager mSensorManagerNew;
private Sensor mTemp;
private double accelerationCurrentValue;
private double accelerationPreviousValue;
private int SwitchFlag = 0;
final String TAG = "SensorLog";
FileWriter writer;
private SensorEventListener sensorEventListener = new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER && SwitchFlag == 1) {
float x = sensorEvent.values[0];
float y = sensorEvent.values[1];
float z = sensorEvent.values[2];
accelerationCurrentValue = Math.sqrt((x * x + y * y + z * z));
double changeInAcceleration = Math.abs(accelerationCurrentValue - accelerationPreviousValue);
accelerationPreviousValue = accelerationCurrentValue;
//update text views
txt_currentAccel.setText("Current =" + accelerationCurrentValue);
txt_prevAccel.setText(("Prev = " + accelerationPreviousValue));
txt_acceleration.setText("Acceleration change =" + changeInAcceleration);
prog_shakeMeter.setProgress((int) changeInAcceleration);
try {
writer.write(String.format("ACC; %f; %f; %f; %f; %f; %f\n", sensorEvent.values[0], sensorEvent.values[1], sensorEvent.values[2], 0.f, 0.f, 0.f));
}catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
};
private SensorEventListener sensorEventListenerNew = new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
float temp = sensorEvent.values[0];
txt_temp.setText("Temp = " + temp);
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txt_acceleration = findViewById(R.id.txt_accel);
txt_prevAccel = findViewById(R.id.txt_prevAccel);
txt_currentAccel = findViewById(R.id.txt_currentAccel);
txt_temp = findViewById(R.id.txt_temp);
prog_shakeMeter = findViewById(R.id.prog_shakeMeter);
switch1 = findViewById(R.id.switch1);
// Initialize Sensors
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManagerNew = (SensorManager) getSystemService(SENSOR_SERVICE);
mTemp = mSensorManagerNew.getDefaultSensor(Sensor.TYPE_LIGHT);
switch1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (b == true) {
Log.d(TAG, "Writing to " + getStorageDir());
try {
writer = new FileWriter(new File(getStorageDir(), "sensors_" + System.currentTimeMillis() + ".csv"));
} catch (
IOException e) {
e.printStackTrace();
}
SwitchFlag = 1;
} else {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
SwitchFlag = 0;
}
}
});
}
protected void onResume() {
super.onResume();
mSensorManager.registerListener(sensorEventListenerNew, mTemp, SensorManager.SENSOR_DELAY_NORMAL);
mSensorManager.registerListener(sensorEventListener, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(sensorEventListener);
mSensorManager.unregisterListener(sensorEventListenerNew);
}
private String getStorageDir() {
return this.getExternalFilesDir(null).getAbsolutePath();
}
}
My app is crashing. I am trying to build an accelerometer based app. Though build is successful, it is not running in the Pixel Emulator. Where have I gone wrong?
I have been trying to find the error but am unsuccessful. I am attaching the run error message, the screenshot of the manifest file and the main code.
This is the error message:
The main code follows
package com.example.androidaccelerometerexample;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.app.Activity;
import android.text.Html;
import android.view.Menu;
import android.widget.TextView;
import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Vibrator;
import android.widget.TextView;
class Main extends Activity implements SensorEventListener {
private float lastX, lastY, lastZ;
private SensorManager sensorManager;
private Sensor accelerometer;
private float deltaXMax = 0;
private float deltaYMax = 0;
private float deltaZMax = 0;
private float deltaX = 0;
private float deltaY = 0;
private float deltaZ = 0;
private float vibrateThreshold = 0;
private TextView currentX, currentY, currentZ, maxX, maxY, maxZ;
public Vibrator v;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initializeViews();
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) {
// success! we have an accelerometer
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
vibrateThreshold = accelerometer.getMaximumRange() / 2;
} else {
// fai! we dont have an accelerometer!
}
//initialize vibration
v = (Vibrator) this.getSystemService(Context.VIBRATOR_SERVICE);
}
public void initializeViews() {
currentX = (TextView) findViewById(R.id.currentX);
currentY = (TextView) findViewById(R.id.currentY);
currentZ = (TextView) findViewById(R.id.currentZ);
maxX = (TextView) findViewById(R.id.maxX);
maxY = (TextView) findViewById(R.id.maxY);
maxZ = (TextView) findViewById(R.id.maxZ);
}
protected void onResume() {
super.onResume();
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
#Override
public void onSensorChanged(#org.jetbrains.annotations.NotNull SensorEvent event) {
// clean current values
displayCleanValues();
// display the current x,y,z accelerometer values
displayCurrentValues();
// display the max x,y,z accelerometer values
displayMaxValues();
// get the change of the x,y,z values of the accelerometer
deltaX = Math.abs(lastX - event.values[0]);
deltaY = Math.abs(lastY - event.values[1]);
deltaZ = Math.abs(lastZ - event.values[2]);
// if the change is below 2, it is just plain noise
if (deltaX < 2)
deltaX = 0;
if (deltaY < 2)
deltaY = 0;
if ((deltaZ > vibrateThreshold) || (deltaY > vibrateThreshold) || (deltaX > vibrateThreshold)) {
v.vibrate(50);
}
}
public void displayCleanValues() {
currentX.setText("0.0");
currentY.setText("0.0");
currentZ.setText("0.0");
}
// display the current x,y,z accelerometer values
public void displayCurrentValues() {
currentX.setText(Float.toString(deltaX));
currentY.setText(Float.toString(deltaY));
currentZ.setText(Float.toString(deltaZ));
}
// display the max x,y,z accelerometer values
public void displayMaxValues() {
if (deltaX > deltaXMax) {
deltaXMax = deltaX;
maxX.setText(Float.toString(deltaXMax));
}
if (deltaY > deltaYMax) {
deltaYMax = deltaY;
maxY.setText(Float.toString(deltaYMax));
}
if (deltaZ > deltaZMax) {
deltaZMax = deltaZ;
maxZ.setText(Float.toString(deltaZMax));
}
}
}
Your activity class needs to be public and not package-private.
Change class Main to public class Main.
I am trying to get a notification to trigger when a long is below a certain number. However whenever sendNotification() is called it throws the above error.
I am new to android.
Below is the section of the code where the issue is.
I am not sure what is causing this error. I supect I made need to change the method to sendNotification(View view) but in that case what do I send as the view?
I can provide the full code if needed.
package com.mple.seriestracker;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;
import com.mple.seriestracker.activity.HomeScreenActivity;
import com.mple.seriestracker.api.episodate.entities.show.Episode;
import com.mple.seriestracker.util.NotificationGenerator;
import org.threeten.bp.Duration;
import org.threeten.bp.LocalDateTime;
import org.threeten.bp.OffsetDateTime;
import org.threeten.bp.ZoneId;
import org.threeten.bp.ZoneOffset;
import org.threeten.bp.ZonedDateTime;
import org.threeten.bp.format.DateTimeFormatter;
import java.util.Locale;
public class Countdown extends AppCompatActivity{
private int season;
private int episode;
private String name;
private ZonedDateTime airDate;
private Context context;
public Countdown(String name, int episode,int season,ZonedDateTime airDate, Context context){
this.airDate = airDate;
this.name = name;
this.episode = episode;
this.season = season;
this.context = context;
}
public Countdown(com.mple.seriestracker.api.episodate.entities.show.Countdown countdown){
this.airDate = parseToLocal(countdown.air_date);
this.name = countdown.name;
this.episode = countdown.episode;
this.season = countdown.season;
}
public void getSecondsTillAiring(){
Duration duration = Duration.between(LocalDateTime.now(),airDate);
long days = duration.toDays();
//No idea why this returns an absurd number, possibly something wrong with the time conversion
//So the simple fix is to convert the days into hours, subtract the total hours with the days.
//This returns the real value, and makes it accurate.
long hours = duration.toHours()-(days*24);
long minutes = (int) ((duration.getSeconds() % (60 * 60)) / 60);
long seconds = (int) (duration.getSeconds() % 60);
if(days > 0){
hours += days * 24;
}
if(hours > 0){
minutes += 60* hours;
}
if(minutes > 0){
seconds += 60 * minutes;
}
if (seconds < 432000){
sendNotification();
}
}
public void sendNotification()
{
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, "M_CH_ID");
//Create the intent that’ll fire when the user taps the notification//
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.androidauthority.com/"));
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
notificationBuilder.setContentIntent(pendingIntent);
NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel notificationChannel =
new NotificationChannel("M_CH_ID", "M_CH_ID", NotificationManager.IMPORTANCE_DEFAULT);
notificationChannel.setDescription("Test");
nm.createNotificationChannel(notificationChannel);
notificationBuilder.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_ALL)
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.ic_launcher)
.setTicker("Hearty365")
.setContentTitle("Default notification")
.setContentText("Random words")
.setContentInfo("Info");
nm.notify(1, notificationBuilder.build());
}
public String getCountdownFormat(){
getSecondsTillAiring();
Duration duration = Duration.between(LocalDateTime.now(),airDate);
long days = duration.toDays();
//No idea why this returns an absurd number, possibly something wrong with the time conversion
//So the simple fix is to convert the days into hours, subtract the total hours with the days.
//This returns the real value, and makes it accurate.
long hours = duration.toHours()-(days*24);
int minutes = (int) ((duration.getSeconds() % (60 * 60)) / 60);
int seconds = (int) (duration.getSeconds() % 60);
String timeString = "";
if(days > 0){
timeString+=formatDay(days);
}
if(hours > 0){
timeString+=formatHour(hours);
}
if(minutes > 0){
timeString+= formatMinutes(minutes);
}
if(seconds > 0){
timeString += formatSeconds(seconds);
}
return timeString;
}
public String getName() {
return name;
}
public int getEpisode() {
return episode;
}
public int getSeason() {
return season;
}
private String formatDay(long days){
return format(days,"day");
}
private String formatHour(long hours){
return format(hours,"hour");
}
private String formatMinutes(long minutes){
return format(minutes,"minute");
}
private String formatSeconds(long seconds){
return format(seconds,"second");
}
private String format(long x,String nonPlural){
//Checks whether or not a plural should be added
String string = nonPlural;
if(x > 1)
string+="s";
return String.format("%s %s ",x,string);
}
//All air dates are formatted in this format
static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH);
public static ZonedDateTime parseToLocal(String s){
if(s == null) return null;
return LocalDateTime.parse(s, DATE_TIME_FORMATTER)
.atOffset(ZoneOffset.UTC)
.atZoneSameInstant(ZoneId.systemDefault());
}
public static boolean isOlderEpisode(LocalDateTime airDate, LocalDateTime currEpDate){
return currEpDate.isBefore(airDate);
}
public static boolean isOlderEpisode(OffsetDateTime airDate, OffsetDateTime currEpDate){
return currEpDate.toLocalDate().isBefore(airDate.toLocalDate());
}
//Responsible for finding a certain episode
public Countdown getUpcomingAiringEp(Episode[] episodes, int episode, int season) {
if (episodes == null) {
return null;
}
//Loop in reverse, since the episodes are ordered from start to finish
//So looping from reverse will start with the newer shows first
for (int i = (episodes.length - 1); i >= 0; i--) {
Episode newEpisode = episodes[i];
if (newEpisode.air_date != null && newEpisode.season == season && newEpisode.episode == episode) {
return new Countdown(newEpisode.name,newEpisode.episode, newEpisode.season, parseToLocal(newEpisode.air_date),this);
}
if(newEpisode.season <= (newEpisode.season - 1)) {
break;
}
}
return null;
}
}
Full stack trace
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.mple.seriestracker, PID: 2348
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
at android.content.ContextWrapper.getPackageName(ContextWrapper.java:145)
at android.app.PendingIntent.getActivity(PendingIntent.java:344)
at android.app.PendingIntent.getActivity(PendingIntent.java:311)
at com.mple.seriestracker.Countdown.sendNotification(Countdown.java:76)
at com.mple.seriestracker.Countdown.getSecondsTillAiring(Countdown.java:65)
at com.mple.seriestracker.Countdown.getCountdownFormat(Countdown.java:100)
at com.mple.seriestracker.fragments.CountdownFragment$RecyclerViewAdapter$1.run(CountdownFragment.java:95)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
And the main class
package com.mple.seriestracker.activity;
import android.Manifest;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;
import androidx.core.content.ContextCompat;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.tabs.TabLayout;
import com.jakewharton.threetenabp.AndroidThreeTen;
import com.mple.seriestracker.R;
import com.mple.seriestracker.ShowInfo;
import com.mple.seriestracker.ShowTracker;
import com.mple.seriestracker.TvShow;
import com.mple.seriestracker.api.episodate.Episodate;
import com.mple.seriestracker.api.episodate.entities.show.TvShowResult;
import com.mple.seriestracker.database.EpisodeTrackDatabase;
import com.mple.seriestracker.fragments.CountdownFragment;
import com.mple.seriestracker.fragments.SectionsPagerAdapter;
import com.mple.seriestracker.fragments.MyShowsFragment;
import com.mple.seriestracker.util.NotificationGenerator;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Response;
public class HomeScreenActivity extends AppCompatActivity {
static final int NEW_SHOW_REQUEST_CODE = 1;
static final int FILE_PERMISSION_RREQUEST_CODE = 1;
static final int NEW_SHOW_REQUEST_RESULT_CODE = 1;
Context context = this;
SectionsPagerAdapter mSectionsPagerAdapter;
ViewPager mViewPager;
TabLayout mTabs;
boolean started = false;
//TODO allow more than 3 shows to display on countdown page
//TODO sort the countdown tab based on time
//TODO notify the user when a show is airing
//TODO re-obtain the next countdown (if any new episodes) otherwise remove the countdown from the tab
//TODO add delete button to delete shows (holding on image already has checkboxes implemented)
//All done after that
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EpisodeTrackDatabase.setInstance(new EpisodeTrackDatabase(getApplicationContext()));
//Sets all date time stuff to correct sync
AndroidThreeTen.init(this);
//Initialize fragments
mSectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
mViewPager = findViewById(R.id.view_pager);
setupViewPager(mViewPager);
mTabs = findViewById(R.id.tabs);
mTabs.setupWithViewPager(mViewPager);
//Initialize floating menu button
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startSearchIntent();
}
});
}
#Override
protected void onStart() {
super.onStart();
//On start is called when the search intent is destroyed
//This prevents it from being used more than once.
//As it's intended for loading settings only (after all UI elements are initialized)
if(started) return;
loadSettings();
started = true;
}
//Responsible for setting up the fragments for each tab
private void setupViewPager(ViewPager viewPager){
mSectionsPagerAdapter.addFragment(new MyShowsFragment(),"My Shows");
mSectionsPagerAdapter.addFragment(new CountdownFragment(),"Countdowns");
viewPager.setAdapter(mSectionsPagerAdapter);
}
private void loadSettings(){
//Loads settings from database
new LoadShowsTask().execute();
}
//Adds a show to the "my shows" tab
public void addShow(ShowInfo showInfo){
new TvShowTask().execute(showInfo); //Background task to get info from the api
EpisodeTrackDatabase.INSTANCE.addShow(showInfo.name,showInfo.imagePath,showInfo.id); //Add the show to the database
((MyShowsFragment)mSectionsPagerAdapter.getItem(0)).addShow(showInfo); //Adds it to the fragment, fragment will then automatically update it
}
public void addCountdown(long showID){
if(ShowTracker.INSTANCE.calenderCache.contains(showID))return;
((CountdownFragment)mSectionsPagerAdapter.getItem(1)).addCountdown(showID);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == NEW_SHOW_REQUEST_CODE && resultCode == NEW_SHOW_REQUEST_RESULT_CODE) {
//Create a new show, add it to the list and populate it
ShowInfo showInfo = new ShowInfo(); //Creates a new object
showInfo.id = data.getLongExtra("showID",0);
showInfo.imagePath = data.getStringExtra("showImage");
showInfo.name = data.getStringExtra("showName");
ShowTracker.INSTANCE.addedShowsCache.add(showInfo.id);
addShow(showInfo);
}
}
class LoadShowsTask extends AsyncTask<String,Void,String>{
#Override
protected String doInBackground(String... strings) {
ShowInfo[] showData = EpisodeTrackDatabase.INSTANCE.getAllShows();
runOnUiThread(() ->{
new TvShowTask().execute(showData);
for (ShowInfo show : showData) {
runOnUiThread(() ->addShow(show));
}
});
return null;
}
}
class TvShowTask extends AsyncTask<ShowInfo,Void, List<TvShowResult>> {
//Responsible for obtaining info about each show
//Automatically prompts on each show add/app initialization
#Override
protected List<TvShowResult> doInBackground(ShowInfo ... shows) {
List<TvShowResult> tvShowResults = new ArrayList<>();
for (ShowInfo show: shows) {
try {
Response<com.mple.seriestracker.api.episodate.entities.show.TvShow> response = Episodate.INSTANCE
.show()
.textQuery(show.id + "")
.execute();
if(response.isSuccessful()){
tvShowResults.add(response.body().tvShow);
}
} catch (IOException e) {}
}
return tvShowResults;
}
#Override
protected void onPostExecute(List<TvShowResult> result) {
for (TvShowResult tvShowResult : result) {
TvShow tvShow = new TvShow(tvShowResult);
ShowTracker.INSTANCE.addTvShow(tvShow);
if(tvShow.getCountdown() != null){
addCountdown(tvShow.getId());
}
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode){
case FILE_PERMISSION_RREQUEST_CODE:
if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
//Todo Finish this, if we will be implementing saving
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
break;
}
}
//Prevents the app opening multiple search intents, if spammed
void startSearchIntent(){
if(!ShowSearchActivity.destroyed) return;
Intent intent = new Intent(getApplicationContext(),ShowSearchActivity.class);
startActivityForResult(intent,NEW_SHOW_REQUEST_CODE);
}
//Will be used for writing saved data, later on to keep track of what shows are saved
boolean hasFilePermissions(){
return (Build.VERSION.SDK_INT > 22 && ContextCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED);
}
void askForPermission(){
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE}, FILE_PERMISSION_RREQUEST_CODE);
}
}
Iam wondering if at this point it is just easiier to link to github as there are more classes than just these 2.
You must supply the proper Context from you Activity class.
First in your YOUR_ACTIVITY.java declare this
Context context = this;
then add context parameters in your countdown method
private int season;
private int episode;
private String name;
private ZonedDateTime airDate;
private Context context;
public Countdown(String name, int episode,int season,ZonedDateTime airDate, Context context){
this.airDate = airDate;
this.name = name;
this.episode = episode;
this.season = season;
this.context = context;
}
Just add the context when calling the Countdown method.
new Countdown(name, episode, season, context).getSecondsTillAiring();
then supply the context to NotificationManager like this.
NotificationManager nm = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Just remove "extends AppCompatActivity" might work for you, because apparently your class does not inherit anything from AppCompatActivity.
EDIT:
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
You may consider moving this part of the code to your Activity class,
or passing activity reference to the method and call it like:
NotificationManager nm = (NotificationManager) activity.getSystemService(Context.NOTIFICATION_SERVICE);
I need your help to find an error in my "test" android application.
Until I create the second function "setProgessBar" the app runs without error, but now the error occur everytime. To comment the function call out has no effect.
Here is the code:
package my.timer;
import android.os.CountDownTimer;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
public class Timer1 extends AppCompatActivity {
private int arrayPosition = 0;
private long timeValue = 0;
private boolean indicator = false;
private double progress;
private final String[] actions = {"Phase1" , "Phase2" , "Phase3" , "Phase4"};
private final ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_timer1);
final Button startButton = (Button) findViewById(R.id.startButton);
final TextView text1 = (TextView) findViewById(R.id.textView3);
final TextView text2 = (TextView) findViewById(R.id.actionParameter);
startButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
text2.setText(actions[arrayPosition]);
text1.setText("" + timeValue + "");
new CountDownTimer(240000, 100) {
public void onTick(long millisUntilFinished) {
timeValue = (millisUntilFinished / 1000) % 4;
text1.setText("" + timeValue + "");
if (timeValue == 3 && indicator){
if (arrayPosition < 3){
arrayPosition++;
} else {
arrayPosition = 0;
}
indicator = false;
setProgressBar(arrayPosition);
text2.setText(actions[arrayPosition]);
}
if (timeValue == 1){
indicator = true;
}
}
public void onFinish() {
text1.setText("Geschafft :)");
}
}.start();
}
});
}
private void setProgressBar(int progressStatus) {
switch (progressStatus){
case 0:
progress = progress + 0.25;
break;
case 2:
progress = progress - 0.25;
break;
}
progressBar.setProgress((int)progress);
}
}
Many thanks in advance
Tim
Im really new to Android programming(started yesterday) and im currently working on an App that should give me the time between first time clicking a button and second time clicking the button.
It works fine when i stay in the Activity. But if i change the activity while the time is "running" and then reenter the main activity it gives me a strange timestamp.
How the timestamp works:
I have a button for Start/Stop
On clicking start it calls a Method where i get the current system time in milliseconds and saves it to a variable.
On clicking stop it does the same and subtracts endTime-startTime. Thats how i get the total time.
(Works fine)
But when changing activity(I got a button where it changes to an activity where i can add a customer) and reentering main and stopping the timer, it adds the totalTime up to something i cant relate to.. currently my stop time is at 45 minutes.
Maybe i do something wrong on saving my values?
I'll just post my code. Maybe someone can help me and give me a hint. Thanks and sorry for my bad english!
Class "Timerecording"
package com.example.cmsolutions.zeiterfassung;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;
import android.view.View;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
public class ZeitErfassen extends AppCompatActivity {
public static LinkedList<Kunde> kunden = new LinkedList();
boolean running = false;
long startTime,endTime,totalTime;
public Date date = new Date();
private SharedPreferences app_preferences;
private SharedPreferences.Editor editor;
private static final int PREFERENCE_MODE_PRIVAT=0;
private TextView displayTime;
public Button startEndButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_zeit_erfassen);
//Einstellungen laden
app_preferences = getPreferences(PREFERENCE_MODE_PRIVAT);
displayTime = (TextView)findViewById(R.id.zeit_bei_Kunde);
startTime= app_preferences.getLong("startTime", 0);
endTime = app_preferences.getLong("endTime", 0);
running = app_preferences.getBoolean("running", false);
totalTime = app_preferences.getLong("totalTime", 0);
displayTime.setText((CharSequence) app_preferences.getString("zeitAnzeige", "Zeit bei Kunde"));
startEndButton = (Button)findViewById(R.id.start_Timer);
startEndButton.setText((CharSequence)app_preferences.getString("timerButton","Start Timer"));
editor = app_preferences.edit();
editor.commit();
createDropDown();
}
public void startTimer(View view) {
if(running == false) {
startTime = getTime();
displayTime.setText("Zeitstoppung läuft");
editor.putString("zeitAnzeige",(String)displayTime.getText());
running = true;
editor.putBoolean("running",true);
editor.putLong("startTimer", startTime);
startEndButton.setText("End Timer");
editor.putString("timerButton", (String)startEndButton.getText());
editor.commit();
} else {
endTime = getTime();
editor.putLong("endTime",endTime);
totalTime = endTime - startTime;
editor.putLong("totalTime",totalTime);
int hours = (int) ((totalTime / (1000*60*60)) % 24);
int minutes = (int) ((totalTime / (1000*60)) % 60);
int seconds = (int) (totalTime / 1000) % 60;
displayTime.setText(String.valueOf(hours)+ ":"+String.valueOf(minutes)+":"+ String.valueOf(seconds));
startEndButton.setText("Start Timer");
editor.putString("timerButton",(String)startEndButton.getText());
editor.commit();
running = false;
}
}
public void neuerKunde(View view) {
Intent intent = new Intent(this, AddKunde.class);
startActivity(intent);
}
public long getTime() {
long millis = System.currentTimeMillis();
return millis;
}
public void createDropDown() {
if(kunden.size() > 0) {
Spinner spinner = (Spinner) findViewById(R.id.chooseCustomer);
ArrayList<String> names = new ArrayList<>();
for(Kunde k:kunden) {
names.add(k.getName());
}
// Create an ArrayAdapter using the string array and a default spinner layout
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, names);
// Specify the layout to use when the list of choices appears
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// Apply the adapter to the spinner
spinner.setAdapter(adapter);
}
}
}
Class"AddCusomter"
package com.example.cmsolutions.zeiterfassung;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.EditText;
import java.util.LinkedList;
public class AddKunde extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_kunde2);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
public void addKunde(View view) throws Exception {
try {
EditText strings = (EditText) findViewById(R.id.customerName);
String name = strings.getText().toString();
strings = (EditText) findViewById(R.id.addressField);
String address = strings.getText().toString();
Kunde customer = new Kunde(name,address);
ZeitErfassen.kunden.add(customer);
} catch (Exception e) {
throw new Exception("Fehler in addKunde!");
}
startActivity(new Intent(this,ZeitErfassen.class));
}
}
I just realised, maybe its because at the end of method addKunde() I start the MainActivity again?
PS: I think that I could also improve my Coding Style. If you have any Tips regarding better coding(methods to other class,....), im also greatuful! Thanks!
Instead of start activity you can finish activity.
//startActivity(new Intent(this,ZeitErfassen.class));
finish();
Check the shared pref is XML is storing values using ddms.
Open shared prefs only when you need
//OnCreate
app_preferences = getApplicationContext().getSharedPreferences("MyPref", MODE_PRIVATE);
Editor editor = pref.edit();
public void startTimer(View view) {
SharedPreferences.Editor editor = = app_preferences.edit();
if(running == false) {
startTime = getTime(); displayTime.setText("Zeitstoppung läuft");
editor.putString("zeitAnzeige",(String)displayTime.getText());
running = true;
editor.putBoolean("running",true); editor.putLong("startTimer", startTime);
startEndButton.setText("End Timer");
editor.putString("timerButton", (String)startEndButton.getText());
editor.commit();
} else {
endTime = getTime();
editor.putLong("endTime",endTime); totalTime = endTime - startTime;
editor.putLong("totalTime",totalTime);
int hours = (int) ((totalTime / (1000*60*60)) % 24); int minutes = (int) ((totalTime / (1000*60)) % 60);
int seconds = (int) (totalTime / 1000) % 60;
displayTime.setText(String.valueOf(hours)+ ":"+String.valueOf(minutes)+":"+ String.valueOf(seconds));
startEndButton.setText("Start Timer"); editor.putString("timerButton",(String)startEndButton.getText());
editor.commit();
running = false;
}
}