Android: Updating int ever second - android

I am creating a text file with data related to my App's game.
I want to show the score at each second in the game.
How can I ensure that my int for seconds is updated, starting at zero
Example of output wanted:
Seconds Score
0 3
1 9
2 16
3 20
.....etc
Current output (seconds always 0):
Seconds Score
0 3
0 9
0 16
0 20
.....etc
Current code:
int seconds=0;
//creating header in the txt file Note: Blanked out as it is generating every second
writeToFileEEGPower(order("Seconds")+order("highAlpha")+order("lowAlpha")+order("highBeta")+order("LowBeta")+
order("lowGamma")+order("midGamma")+order("Delta")+order("Theta")+ "\n");
//creating the string to be written to file
String line = order(seconds+"")+order(eegPower.highAlpha+"")+order(eegPower.lowAlpha+"")+order(eegPower.highBeta+"")+
order(eegPower.lowBeta+"")+order(eegPower.midGamma+"")+order(eegPower.delta+"")+order(eegPower.theta+"")+ "\n";
//write the string to file
writeToFileEEGPower(line);
seconds++;

I think you should rather use a sqlite table for this. Greendao
is a good tool for managing those tables. You can save the information every second to a table. When the game is finished, you have a full list of the score for each second of the game.
In your code example the "second" variable is set to 0 each time before you write a new line. I think that is the problem.

Using TimerTask or Handler with postDelayed() method can do the trick.

You can use a handler to update your text file every second:
public class MyActivity extends Activity {
private android.os.Handler mHandler = new android.os.Handler();
private Runnable textFileLogger;
private int seconds = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
//Create header for text file
writeToFileEEGPower(order("Seconds") + order("highAlpha") + order("lowAlpha") + order("highBeta") + order("LowBeta") +
order("lowGamma") + order("midGamma") + order("Delta") + order("Theta") + "\n");
textFileLogger = new Runnable() {
#Override
public void run() {
seconds++;
String line = order(seconds + "") + order(eegPower.highAlpha + "") + order(eegPower.lowAlpha + "") + order(eegPower.highBeta + "") +
order(eegPower.lowBeta + "") + order(eegPower.midGamma + "") + order(eegPower.delta + "") + order(eegPower.theta + "") + "\n";
//write the string to file
writeToFileEEGPower(line);
//Repeats the logging after 1 second
mHandler.postDelayed(this, 1000);
}
};
//Starts the logging after 1 second
mHandler.postDelayed(textFileLogger, 1000);
}
#Override
protected void onDestroy() {
super.onDestroy();
//To stop the logging:
mHandler.removeCallbacks(textFileLogger);
}
}

Related

TimePicker's time does not get updated after setCurrentHour/Minute() correctly

I am extending a DialogPreference to get the following Dialog:
I want it to be able to pick two times: a starting time and an ending time (for whatever reason). For this the TimePicker should always show the time on the ToggleButton that is checked.
In order to let the user know which of both times he is currently changing, I use ToggleButtons and ensure by OnCheckedChangeListeners that exactly one is checked all the time. No problems so far. The same listeners are used to change the text on those ToggleButtons (by both, the setTextOn/setTextOff, methods).
See the following code I use in the extended DialogPreference:
/*
* Bind data to our content views
* */
#Override
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
// use 24h format
mTimePicker = (TimePicker) view.findViewById(R.id.timePicker);
mTimePicker.setIs24HourView(true);
mToggleButtonFrom = (ToggleButton) view.findViewById(R.id.toggleButtonDisplayOnFrom);
mToggleButtonUntil = (ToggleButton) view.findViewById(R.id.toggleButtonDisplayOnUntil);
// save the time of the timepicker internally for both buttons, if there are no saved values
if(fromHour == -1 && fromMin == -1) {
fromHour = mTimePicker.getCurrentHour();
fromMin = mTimePicker.getCurrentMinute();
}
if(untilMin == -1 && untilHour == -1){
untilHour = mTimePicker.getCurrentHour();
untilMin = mTimePicker.getCurrentMinute();
}
// set currently saved times
mToggleButtonFrom.setTextOn(String.format("%02d", fromHour) + ":" + String.format("%02d", fromMin));
mToggleButtonFrom.setTextOff(String.format("%02d", fromHour) + ":" + String.format("%02d", fromMin));
mToggleButtonUntil.setTextOn(String.format("%02d", untilHour) + ":" + String.format("%02d", untilMin));
mToggleButtonUntil.setTextOff(String.format("%02d", untilHour) + ":" + String.format("%02d", untilMin));
// update the button (not working without this)
mToggleButtonFrom.setChecked(mToggleButtonFrom.isChecked());
mToggleButtonUntil.setChecked(mToggleButtonUntil.isChecked());
// set togglebuttons to exclude each other
mToggleButtonFrom.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
// The toggle is enabled
if (mToggleButtonUntil.isChecked())
mToggleButtonUntil.setChecked(false);
} else {
// The toggle is disabled
if (!mToggleButtonUntil.isChecked())
mToggleButtonUntil.setChecked(true);
fromHour = getCurrentlyPickedHour2();
fromMin = getCurrentlyPickedMinute2();
String time = getStringTime(fromHour, fromMin);
mToggleButtonFrom.setTextOff(time);
mToggleButtonFrom.setTextOn(time);
setTimeToTimePickerSlim(false);
}
}
});
mToggleButtonUntil.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
// The toggle is enabled
if (mToggleButtonFrom.isChecked())
mToggleButtonFrom.setChecked(false);
} else {
// The toggle is disabled
if (!mToggleButtonFrom.isChecked())
mToggleButtonFrom.setChecked(true);
untilHour = getCurrentlyPickedHour2();
untilMin = getCurrentlyPickedMinute2();
String time = getStringTime(untilHour, untilMin);
mToggleButtonUntil.setTextOff(time);
mToggleButtonUntil.setTextOn(time);
setTimeToTimePickerSlim(true);
}
}
});
}
private void setTimeToTimePickerSlim(boolean from){
if(from){
mTimePicker.setCurrentHour(Integer.valueOf(fromHour));
mTimePicker.setCurrentMinute(Integer.valueOf(fromMin));
} else {
mTimePicker.setCurrentHour(Integer.valueOf(untilHour));
mTimePicker.setCurrentMinute(Integer.valueOf(untilMin));
}
}
private int fromHour = -1;
private int fromMin = -1;
private int untilHour = -1;
private int untilMin = -1;
private int getCurrentlyPickedHour2(){
return mTimePicker.getCurrentHour();
}
private int getCurrentlyPickedMinute2(){
return mTimePicker.getCurrentMinute();
}
private String getStringTime(int hour, int min){
return String.format("%02d", hour)+":"+String.format("%02d", min);
}
I have absolutly no clue, why the TimePicker is not updating to the shown (and set) time, when I choose a new time and then click on one of those ToggleButtons (same behaviour for both of them as far as I can tell).
But the most interesting part comes now: When I do this twice (choose a new time, toggle the buttons, choose another time, toggle again), the TimePicker starts toggling the shown time, too. Exactly what I want it to show!
I tried a lot of things, here are my 'best' guesses:
If I change the method setTimeToTimePickerSlim(boolean) to
private void setTimeToTimePickerSlim(boolean from){
if(from){
mTimePicker.setCurrentHour(3);
mTimePicker.setCurrentMinute(15);
} else {
mTimePicker.setCurrentHour(21);
mTimePicker.setCurrentMinute(45);
}
}
this works like intended (but is of cause a bit to static to be usefull ..). Unfortunately removing the Integer.valueOf() does not help, too.
I would be very happy for any hint (since I am trying to debug this for hours now).
Update: I logged the values by the following modification
private void setTimeToTimePickerSlim(boolean from){
Log.i("StrangeBugTest", "Before setting: from: " + fromHour + ":" + fromMin + " until: " + untilHour + ":" + untilMin + " (from=" + from + ")");
Log.i("StrangeBugTest", "Pickertime: " + mTimePicker.getCurrentHour() + ":" + mTimePicker.getCurrentMinute());
if(from){
mTimePicker.setCurrentHour(fromHour);
mTimePicker.setCurrentMinute(fromMin);
} else {
mTimePicker.setCurrentHour(untilHour);
mTimePicker.setCurrentMinute(untilMin);
}
Log.i("StrangeBugTest", "After setting: from: " + fromHour + ":" + fromMin + " until: " + untilHour + ":" + untilMin + " (from=" + from + ")");
Log.i("StrangeBugTest", "Pickertime: " + mTimePicker.getCurrentHour() + ":" + mTimePicker.getCurrentMinute());
}
When I start the app (and open the preferenceDialog) I get the following screen:
I than picked the hour 21 (because I am using 24h-format) and minute 45. After this i clicked the toggleButtonFrom (on the left). This gets me the following log (shortened):
10-20 19:43:11.575 Before setting: from: 21:45 until: 19:42 (from=false)
10-20 19:43:11.575 Pickertime: 21:45
10-20 19:43:11.575 After setting: from: 21:45 until: 19:42 (from=false)
10-20 19:43:11.575 Pickertime: 21:45
This is wrong, because the pickertime should be 19:42 after the setting. However, the gui is consistent to the picked time:
I than changed the Picker back to hour, chose hour 15 followed by minute 15 and clicked on ToggleButtonUntil (right one). This gives me the following log
10-20 19:44:26.178 Before setting: from: 21:45 until: 15:15 (from=true)
10-20 19:44:26.178 Pickertime: 15:15
10-20 19:44:26.188 After setting: from: 21:45 until: 15:15 (from=true)
10-20 19:44:26.188 Pickertime: 21:45
This is how it should work from the very beginning! The GUI shows:
From here on, everything is fine, both, times and buttons toggle as intended. But I do not see, why the first one does not work. I would be happy for every hint I can get.

Android get the selected audio file's duration from storage [duplicate]

How to get mp3 track duration without creating MediaPlayer instance? I just need to show mp3 song length in mp3 file list, so I think that I shouldn't create MediaPlayer object for each of tracks in the list
And another:
sometimes MediaPlayer returns wrong duration of the song ( I think its so because bitrate of those files is dinamic ). How can I get right duration of the song?
// load data file
MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
metaRetriever.setDataSource(filePath);
String out = "";
// get mp3 info
// convert duration to minute:seconds
String duration =
metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
Log.v("time", duration);
long dur = Long.parseLong(duration);
String seconds = String.valueOf((dur % 60000) / 1000);
Log.v("seconds", seconds);
String minutes = String.valueOf(dur / 60000);
out = minutes + ":" + seconds;
if (seconds.length() == 1) {
txtTime.setText("0" + minutes + ":0" + seconds);
}else {
txtTime.setText("0" + minutes + ":" + seconds);
}
Log.v("minutes", minutes);
// close object
metaRetriever.release();
You can use the MediaMetadataRetriever to get the duration of a song. Use the METADATA_KEY_DURATION in combination with the extractMetadata() funciton.
Here is the Kotlin version:
var metaRetriever:MediaMetadataRetriever = MediaMetadataRetriever()
metaRetriever.setDataSource(filePath)
var out:String = ""
var txtTime:String = ""
var duration:String = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
Log.d("DURATION VALUE", duration)
var dur:Long = duration.toLong()
var seconds:String = ((dur % 60000)/1000).toString()
Log.d("SECONDS VALUE", seconds)
var minutes:String = (dur / 60000).toString()
out = minutes + ":" + seconds
if (seconds.length == 1){
txtTime = "0" + minutes + ":0" + seconds
}
else {
txtTime = "0" + minutes + ":" + seconds
}
Log.d("MINUTES VALUE", minutes)
Log.d("FORMATTED TIME", txtTime)
metaRetriever.release()
If you want to support older Android versions, you can use a 3rd party library. For example http://www.jthink.net/jaudiotagger/ works fine, though it's relatively space consuming for an Android application (a little less than 1 MB).
True programmers would of course parse the duration from the binary file without using any libraries ;) I didn't have enough skill for this.
I found this more accurate getLength with FFmpeg
int soundLength = (int) new SoxController(context, new File(""), shell).getLength(soundPath);

How to insert a log in LogCat that when I click on it jumps to its line in code?

I want to insert a log in LogCat that when I click on it jumps to its line like some error logs that are generated by system.
Is it possible?
I found it:
public static void showLogCat(String tag, String msg) {
StackTraceElement[] stackTraceElement = Thread.currentThread()
.getStackTrace();
int currentIndex = -1;
for (int i = 0; i < stackTraceElement.length; i++) {
if (stackTraceElement[i].getMethodName().compareTo("showLogCat") == 0)
{
currentIndex = i + 1;
break;
}
}
String fullClassName = stackTraceElement[currentIndex].getClassName();
String className = fullClassName.substring(fullClassName
.lastIndexOf(".") + 1);
String methodName = stackTraceElement[currentIndex].getMethodName();
String lineNumber = String
.valueOf(stackTraceElement[currentIndex].getLineNumber());
Log.i(tag, msg);
Log.i(tag + " position", "at " + fullClassName + "." + methodName + "("
+ className + ".java:" + lineNumber + ")");
}
Its usage:
showLogCat("tag", "message");
The important thing is to insert "(X:Y)" in your log message, while X is your desired file name and Y is your desired line number in X. (I learned it from #breceivemail's answer). So try:
public static void log(final String tag, final String msg) {
final StackTraceElement stackTrace = new Exception().getStackTrace()[1];
String fileName = stackTrace.getFileName();
if (fileName == null) fileName=""; // It is necessary if you want to use proguard obfuscation.
final String info = stackTrace.getMethodName() + " (" + fileName + ":"
+ stackTrace.getLineNumber() + ")";
Log.LEVEL(tag, info + ": " + msg);
}
Note: The LEVEL is the log level and can be v, d, i, w, e or wtf.
Now you can use log(tag, msg) instead of Log.LEVEL(tag, msg).
Example:
MainActivity.java:
...
public class MainActivity extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
log("Test Tag", "Hello World!");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
...
The output:
12-30 14:24:45.343 ? I/Test Tag: onCreate (MainActivity.java:10): Hello World!
And MainActivity.java:10 automatically would be a link and you can click on it!
You can also assign following value to info variable if you want more verbose log:
final String info = stackTrace.getClassName() + "." + stackTrace.getMethodName() + " ("
+ fileName + ":" + stackTrace.getLineNumber() + ")\n";
So the output of above example would be:
12-30 14:33:07.360 ? I/Test Tag: com.example.myapp.MainActivity.onCreate (MainActivity.java:11)
Hello World!
Please use this Tree with Timber.
class MyLinkingTimberTree : Timber.DebugTree() {
override fun createStackElementTag(element: StackTraceElement): String? {
return makeClickableLineNumber(element)
}
private fun makeClickableLineNumber(
element: StackTraceElement
): String {
val className = element.fileName
val methodName = element.methodName
val lineNumber = element.lineNumber
val fileName = element.fileName
val stringBuilder = StringBuilder(className)
.append(".")
.append(methodName)
.append(" (")
.append(fileName)
.append(":")
.append(lineNumber)
.append(") ")
return stringBuilder.toString()
}
}
And then just instantiate it like this:
class MyApplication: Application() {
override fun onCreate() {
super.onCreate()
if(BuildConfig.DEBUG) {
Timber.plant(MyLinkingTimberTree())
}
}
}
Then just use Timber normally:
Timber.d("Currently Signed in:")
And this is the result. Nice, isn't it? I hope you enjoy using it as much as I enjoyed making it! ;)
Yes you can do it .. Follow the example as answered on SO - logging
To answer the question in a simple way:
respecter cette règle :
{FileName}.{ext}:{LigneNumber}
e.g. MainActivity.java:10
which gives a sample as below
Log.d(TAG, "onResume: MainActivity.java:10");
I hope this will help you
This isn't exactly an answer to the question, but perhaps it's a "close enough" workaround.
Highlight the log text
Press CTRL-SHIFT-F
Double-Click on the search result.
If the text is highlighted before you press CTRL-SHIFT-F, then you don't need to type or copy/paste it in.
If your searches tend to produce too many results, you can use live templates to make unique logcat entries:
Create a live template to insert the Class, Method, and Line-Number (at the time of writing). I use "logi." Yes, the line number will become less and less accurate as you continue to write, but it can still function as a way to make your log entries more "findable."

Get mp3 duration in android

How to get mp3 track duration without creating MediaPlayer instance? I just need to show mp3 song length in mp3 file list, so I think that I shouldn't create MediaPlayer object for each of tracks in the list
And another:
sometimes MediaPlayer returns wrong duration of the song ( I think its so because bitrate of those files is dinamic ). How can I get right duration of the song?
// load data file
MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
metaRetriever.setDataSource(filePath);
String out = "";
// get mp3 info
// convert duration to minute:seconds
String duration =
metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
Log.v("time", duration);
long dur = Long.parseLong(duration);
String seconds = String.valueOf((dur % 60000) / 1000);
Log.v("seconds", seconds);
String minutes = String.valueOf(dur / 60000);
out = minutes + ":" + seconds;
if (seconds.length() == 1) {
txtTime.setText("0" + minutes + ":0" + seconds);
}else {
txtTime.setText("0" + minutes + ":" + seconds);
}
Log.v("minutes", minutes);
// close object
metaRetriever.release();
You can use the MediaMetadataRetriever to get the duration of a song. Use the METADATA_KEY_DURATION in combination with the extractMetadata() funciton.
Here is the Kotlin version:
var metaRetriever:MediaMetadataRetriever = MediaMetadataRetriever()
metaRetriever.setDataSource(filePath)
var out:String = ""
var txtTime:String = ""
var duration:String = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)
Log.d("DURATION VALUE", duration)
var dur:Long = duration.toLong()
var seconds:String = ((dur % 60000)/1000).toString()
Log.d("SECONDS VALUE", seconds)
var minutes:String = (dur / 60000).toString()
out = minutes + ":" + seconds
if (seconds.length == 1){
txtTime = "0" + minutes + ":0" + seconds
}
else {
txtTime = "0" + minutes + ":" + seconds
}
Log.d("MINUTES VALUE", minutes)
Log.d("FORMATTED TIME", txtTime)
metaRetriever.release()
If you want to support older Android versions, you can use a 3rd party library. For example http://www.jthink.net/jaudiotagger/ works fine, though it's relatively space consuming for an Android application (a little less than 1 MB).
True programmers would of course parse the duration from the binary file without using any libraries ;) I didn't have enough skill for this.
I found this more accurate getLength with FFmpeg
int soundLength = (int) new SoxController(context, new File(""), shell).getLength(soundPath);

Asynctask taking ridiculous amount of time

My problem is that I had a program working before, without threading, and it took a long time to process info (16 seconds to get XML data and display it). Now I've gotten the whole threading and async thing down, but for some reason it is making my program SLOWER (in the emulator, device is not available right now), is there anything I've done that could have caused this, the UI thread is fine, but my async thread takes a minute and a half to execute. (when I had it in the UI thread used to take only 16 seconds, but froze the UI thread)
Here is the code for my thread, it sits inside of the main class:
private class TeamSearchTask extends AsyncTask<String,Void,String> {
CharSequence nfo;
String [] matches;
String [] data;
String teamNum;
ProgressDialog loading;
protected void onPreExecute()
{
//Show the 'loading' dialog
loading = new ProgressDialog(SapphireAlliance.this);
loading.setMessage("Loading, please wait...");
loading.show();
}
protected String doInBackground(String... teamNumber)
{
try
{
//Team information ------------------------------------------------------------------------------------
teamNum = teamNumber[0];
//Array of team data
data = APIconnection.getTeams(teamNum, "");
//Display basic team info
nfo = ("\nFormal Team Name:\n" + data[1] +
"\n\nLocation:\n" + data [3] + ", " + data[4] + ", " + data[5] +
"\n\nRookie Year:\n" + data[6] +
"\n\nRobot Name:\n" + data[7] +
"\n\nWebsite:\n" + data[8] + "\n\n\n\n\n\n\n\n\n");
//Make match archive --------------------------------------------------------------------------------------
String [] events = APIconnection.getEventIdsByYear(year1);
ArrayList<String> matches = new ArrayList<String>();
for (int i = 0; i<events.length; i++)
{
String [] add = APIconnection.getMatches2(teamNum, events[i] ,"","");
for(int j = 0; j<add.length; j++)
matches.add(add[j]);
}
String [] out = new String [matches.size()];
matches.toArray(out);
return "";
}
catch(Exception e)
{
return e.toString();
}
}
protected void onPostExecute(String result) {
if(result.equals(""))
{
info.setText(nfo);
matchArchive(matches);
//title
CharSequence ttl = "Team " + teamNum;
titlets.setText(ttl.toString());
loading.dismiss();
}
else
{
alert.setMessage(result);
alert.show();
}
}
}
Anything in there that could be causing this? :|
It may be that your thread priority may not be set very high. I remember the default is rather low. However, for what you're doing, it shouldn't be taking more than a couple seconds. I would think that the real problem lies in APIconnection going to the network and doing something that takes a long time. Particularly, that for loop that does the event fetching would be doing a lot of work if each call opens a new socket, assuming that this is for FIRST matches. :P
I am having the same issue, doing nothing more than a file copy with simple DES decryption... the whole thing ran in a few seconds on the UI thread, but when moved into an ASYNCTASK it is now taking MINUTES to accomplish. Unbelievable.

Categories

Resources