I have android TV app which will run for long time .And I have google map inside that but after 20-24 hours google map starts blinking. Following link contains video of issue.
https://www.dropbox.com/s/vp8pbqc5z4zopbz/20180611_095004.mp4?dl=0
Edit
I can't share the whole source code, but I am using two fragments. One fragment contains map and another contains a listview of images. I call a webservice every 10 seconds and update listview images and bound map with locations I get in response of web service.
if ( map!=null) {
if (activity.ambDetailList.size() > 0) {
int i;
double dist, currentLat = 0.0, currentLng = 0.0;
ambOnlineList.clear();
String ETA, SPEED;
Marker marker;
for (i = 0; i < activity.ambDetailList.size(); i++) {
ambulanceDetail = activity.ambDetailList.get(i);
dist = Math.sqrt(Math.pow(ambulanceDetail.getCurrentLat() - ambulanceDetail.getDestLat(), 2) + Math.pow(ambulanceDetail.getCurrentLng() - ambulanceDetail.getDestLng(), 2));
double minute = ((dist * 100) / (ambulanceDetail.getSpeed() * 60 / 1000));
double speed = ambulanceDetail.getSpeed() * 60 * 60 / 1000;
Log.i("Minute", "----->>>>" + minute);
if (speed >= 0.00 && speed <= 1.00) {
ETA = activity.getResources().getString(R.string.text_infinity);
SPEED = activity.getResources().getString(R.string.text_infinity);
} else if (minute > 60) {
double hour = minute / 60;
int roundHour = (int) (minute / 60);
int min = (int) ((hour - roundHour) * 60);
ETA = roundHour + " hour " + min + " min";
SPEED = (int) (ambulanceDetail.getSpeed() * 60 * 60 / 1000) + " km/h ";
} else {
ETA = (int) (minute) + " min ";
SPEED = (int) (ambulanceDetail.getSpeed() * 60 * 60 / 1000) + " km/h ";
}
ambulanceDetail.setEta(ETA);
ambulanceDetail.setDisplayETA(ETA);
ambulanceDetail.setDisplaySpeed(SPEED);
if (markerList.get(ambulanceDetail.getAmbulanceId()) == null) {
MarkerOptions markerOptions = createMarker(ambulanceDetail);
marker = map.addMarker(markerOptions);
markerList.put(ambulanceDetail.getAmbulanceId(), marker);
markerArrayList.add(marker);
detailMap.put(marker, ambulanceDetail);
} else {
marker = markerList.get(ambulanceDetail.getAmbulanceId());
if (marker.isVisible()) {
Location location = new Location("");
location.setLatitude(ambulanceDetail.getCurrentLat());
location.setLongitude(ambulanceDetail.getCurrentLng());
marker.setIcon(BitmapDescriptorFactory.fromBitmap(updateMarkerIcon(ambulanceDetail)));
marker.setPosition(new LatLng(ambulanceDetail.getCurrentLat(), ambulanceDetail.getCurrentLng()));
}
}
ArrayList<Integer> listId = new ArrayList<>();
for (int m = 0; m < activity.ambDetailList.size(); m++) {
listId.add(activity.ambDetailList.get(m).getAmbulanceId());
}
for (int k = 0; k < markerArrayList.size(); k++) {
Marker m = markerArrayList.get(k);
if (!listId.contains(detailMap.get(m).getAmbulanceId())) {
markerArrayList.remove(m);
markerList.remove(detailMap.get(m).getAmbulanceId());
detailMap.remove(m);
m.remove();
}
}
}
if (markerList.size() == 1 && activity.ambDetailList.size() == 1) {
map.moveCamera(CameraUpdateFactory.newLatLngZoom(markerList.get(activity.ambDetailList.get(0).getAmbulanceId()).getPosition(), 16));
} else {
boundLatLang();
}
if (isFirstCall) {
map.setBuildingsEnabled(true);
isFirstCall = false;
}
} else {
if (markerArrayList.size() > 0) {
for (int i = 0; i < markerArrayList.size(); i++) {
Marker marker = markerArrayList.get(i);
marker.remove();
}
markerList.clear();
markerArrayList.clear();
}
map.clear();
if (detailMap.size() > 0)
detailMap.clear();
}
}
Anyway, you can restart application (or if that didn't helps - reboot device) before map starts blinking, for example after 15 hours of work (or e.g. 500 calls of web service):
...
Intent restartIntent = getBaseContext().getPackageManager()
.getLaunchIntentForPackage( getBaseContext().getPackageName() );
restartIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(restartIntent);
...
Related
I have a fairly simple calculator with 2 tabs, the tabs appear to be working fine with the first tab calculating as it should, but the calculating for the second tab keeps throwing the catch error.
In the 2nd tab, I have 2 if statements, which checks to see which edittext field contains data. Depending on which contains data to what calculation it does.
Below is the code for when my button is pressed I have put together, it could probably be streamlined but just I'm an amature so go easy on me.
Any advice to get this working please?
calculate.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View view) {
if ( tabs.getCurrentTab() == 0) {
try {
if (d.getText().toString().trim().length() == 0) {
a1 = a.getText().toString();
double a2 = Double.parseDouble(a1);
b1 = b.getText().toString();
double b2 = Double.parseDouble(b1);
double sum = (a2 * b2) / 10000;
double total = Math.round((sum) * 10) / 10.0;
answer.setBackgroundColor(Color.parseColor("#d6ffffff"));
answer.setText(String.valueOf("Total Area Allocation = " + total + " ha"));
} else if (d.getText().toString().trim().length() >= 1) {
a1 = a.getText().toString();
double a2 = Double.parseDouble(a1);
b1 = b.getText().toString();
double b2 = Double.parseDouble(b1);
d1 = d.getText().toString();
double d2 = Double.parseDouble(d1);
double sum = (a2 * b2) / 10000;
double sum2 = (a2 * b2) / d2;
double total = Math.round((sum) * 10) / 10.0;
double total2 = Math.round((sum2) * 10) / 10.0;
answer.setBackgroundColor(Color.parseColor("#d6ffffff"));
answer.setText(String.valueOf("Total Area Allocation = " + total + " ha"));
answer2.setBackgroundColor(Color.parseColor("#d6ffffff"));
answer2.setText(String.valueOf("Set break " + total2 + " m"));
}
} catch (Exception e) {
answer.setBackgroundColor(Color.parseColor("#d6ffffff"));
answer.setText("Enter values in input fields");
}
}
if (tabs.getCurrentTab() == 1) {
try {
if (ff.getText().toString().trim().length() == 0) {
aa1 = aa.getText().toString();
double aa2 = Double.parseDouble(aa1);
bb1 = bb.getText().toString();
double bb2 = Double.parseDouble(bb1);
cc1 = cc.getText().toString();
double cc2 = Double.parseDouble(cc1);
dd1 = dd.getText().toString();
double dd2 = Double.parseDouble(dd1);
ee1 = ee.getText().toString();
double ee2 = Double.parseDouble(ee1);
if (ee.getText().toString().trim().length() == 0){
double sum = (aa2 * bb2)/(cc2 - dd2);
double total = Math.round((sum) * 10) / 10.0;
answer.setBackgroundColor(Color.parseColor("#d6ffffff"));
answer.setText(String.valueOf("Total Area Allocation = " + total + " ha"));
}
else if (cc.getText().toString().trim().length() == 0){
double sum = (aa2 * bb2)/ee2;
double total = Math.round((sum) * 10) / 10.0;
answer.setBackgroundColor(Color.parseColor("#d6ffffff"));
answer.setText(String.valueOf("Total Area Allocation = " + total + " ha"));
}
} else if (ff.getText().toString().trim().length() >= 1) {
aa1 = aa.getText().toString();
double aa2 = Double.parseDouble(aa1);
bb1 = bb.getText().toString();
double bb2 = Double.parseDouble(bb1);
cc1 = cc.getText().toString();
double cc2 = Double.parseDouble(cc1);
dd1 = dd.getText().toString();
double dd2 = Double.parseDouble(dd1);
ee1 = ee.getText().toString();
double ee2 = Double.parseDouble(ee1);
ff1 = ff.getText().toString();
double ff2 = Double.parseDouble(ff1);
if (ee.getText().toString().trim().length() == 0){
double sum = (aa2*bb2)/(cc2-dd2);
double sum2 = (sum * 10000) / ff2;
double total = Math.round((sum) * 10) / 10.0;
double total2 = Math.round((sum2) * 10) / 10.0;
answer.setBackgroundColor(Color.parseColor("#d6ffffff"));
answer.setText(String.valueOf("Total Area Allocation = " + total + " ha"));
answer2.setBackgroundColor(Color.parseColor("#d6ffffff"));
answer2.setText(String.valueOf("Set break " + total2 + " m"));
}
else if (cc.getText().toString().trim().length() == 0){
double sum = (aa2 * bb2)/ee2;
double sum2 = (sum * 10000) / ff2;
double total = Math.round((sum) * 10) / 10.0;
double total2 = Math.round((sum2) * 10) / 10.0;
answer.setBackgroundColor(Color.parseColor("#d6ffffff"));
answer.setText(String.valueOf("Total Area Allocation = " + total + " ha"));
answer2.setBackgroundColor(Color.parseColor("#d6ffffff"));
answer2.setText(String.valueOf("Set break " + total2 + " m"));
}
}
} catch (Exception e) {
answer.setBackgroundColor(Color.parseColor("#d6ffffff"));
answer.setText("Enter values in input fields 2");
}
}
}
});
While it's not strictly on topic of why you're running into the exceptions, might I make some suggestions to help improve your code and hopefully reduce problems down the road.
Try to use more helpful variable names, it's hard to know what aa and bb actually are. Try to explain what they actually contain. numOfCows or what have you.
Move your logic into smaller functions. This will help you understand at a glance what the code does, and what other code it calls.
For example, create functions for handling each tab's calculation, and move that logic into there.
calculate.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View view) {
if (tabs.getCurrentTab() == 0) {
calculateFirstTab();
} else if (tabs.getCurrentTab() == 1) {
calculateSecondTab();
}
}
});
And lastly, try to reduce duplication. You have a lot of code that does the same thing, but you can make it a lot cleaner by creating small functions to help.
For example, here I have created a function called setAnswer that lets me pass in a TextView, and some text. This will let you set the background color is one place, and update the text. Then, creating another function called setAnswers that lets you pass in the totals, you can now set both answers just like that.
private void setAnswers( double total1, double total2 ){
setAnswer(answer, "Total Area Allocation = " + total1 + " ha");
setAnswer(answer2, "Set break " + total2 + " m");
}
private void setAnswer( TextView view, String text ) {
view.setBackgroundColor(Color.parseColor("#d6ffffff"));
view.setText(text);
}
There are definitely a lot of other ways to improve, but just some suggestions that may help you out.
I'm using Unity3D and I created simple distance, speed and acceleration calculator using latitude and longitude of last position. I'm calculating last distance, speed and acceleration in each GPS update (approximately once per second). But sometimes (2-3 second interval) latitude and longitude values changes rapidly (in clear weather and no obstacles). That's why speed and acceleration values gets unreal results. For example, at stable 40 km/h speed, speed value becomes 60 km/h and returns to 40 km/h within 2-3 second. I'm here to ask how can I avoid this inaccurate and rapid GPS data changes?
I'm using Nexus 5 device
There is my code:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class Manager : MonoBehaviour
{
public Text longitude, latitude, lonAText, latAText, lonBText, latBText;
public Text result, overallResult, speedText, lastTimeText, timerText, accelerationText, speed0Text;
float lonA, lonB, latA, latB, overallDistance, lastDistance, timer, lastTime, speed, speed0, acceleration;
bool firstTime, allowTimer;
public AudioSource audio;
void Awake()
{
overallDistance = 0;
lastDistance = 0;
timer = 0;
lastTime = 0;
speed = 0;
speed0 = 0;
firstTime = true;
allowTimer = true;
}
IEnumerator Start()
{
// First, check if user has location service enabled
if (!Input.location.isEnabledByUser)
yield break;
// Start service before querying location
Input.location.Start(1, 1);
// Wait until service initializes
int maxWait = 20;
while (Input.location.status == LocationServiceStatus.Initializing && maxWait > 0)
{
yield return new WaitForSeconds(1);
maxWait--;
}
// Service didn't initialize in 20 seconds
if (maxWait < 1)
{
print("Timed out");
yield break;
}
// Connection has failed
if (Input.location.status == LocationServiceStatus.Failed)
{
print("Unable to determine device location");
yield break;
}
else
{
// Access granted and location value could be retrieved
print("Location: " + Input.location.lastData.latitude + " " + Input.location.lastData.longitude + " " + Input.location.lastData.altitude + " " + Input.location.lastData.horizontalAccuracy + " " + Input.location.lastData.timestamp);
longitude.text = Input.location.lastData.longitude.ToString();
latitude.text = Input.location.lastData.latitude.ToString();
lonA = Input.location.lastData.longitude;
latA = Input.location.lastData.latitude;
}
// Stop service if there is no need to query location updates continuously
//Input.location.Stop();
}
void Update()
{
longitude.text = Input.location.lastData.longitude.ToString();
latitude.text = Input.location.lastData.latitude.ToString();
timer += Time.deltaTime;
timerText.text = timer.ToString();
if (lonA != Input.location.lastData.longitude || latA != Input.location.lastData.latitude)
{
audio.Play();
CalculateDistances(lonA, latA, Input.location.lastData.longitude, Input.location.lastData.latitude); // last distance and overall distanceS
lonA = Input.location.lastData.longitude;
latA = Input.location.lastData.latitude;
lastTime = timer;
lastTimeText.text = lastTime.ToString();
timer = 0;
speed0 = speed;
speed0Text.text = speed0.ToString();
CalculateSpeed();
CalculateAcceleration();
}
}
public static float Radians(float x)
{
return x * Mathf.PI / 180;
}
public void CalculateDistances(float firstLon, float firstLat, float secondLon, float secondLat)
{
lonAText.text = firstLon.ToString();
latAText.text = firstLat.ToString();
lonBText.text = secondLon.ToString();
latBText.text = secondLat.ToString();
float dlon = Radians(secondLon - firstLon);
float dlat = Radians(secondLat - firstLat);
float distance = Mathf.Pow(Mathf.Sin(dlat / 2), 2) + Mathf.Cos(Radians(firstLat)) * Mathf.Cos(Radians(secondLat)) * Mathf.Pow(Mathf.Sin(dlon / 2), 2);
float c = 2 * Mathf.Atan2(Mathf.Sqrt(distance), Mathf.Sqrt(1 - distance));
lastDistance = 6371 * c * 1000;
result.text = lastDistance.ToString() + " meters";
overallDistance += lastDistance; // bu 1 anliq 6.000.000-dan boyuk qiymet ala biler
StartCoroutine(Overall());
}
IEnumerator Overall()
{
if (firstTime)
{
firstTime = false;
yield return new WaitForSeconds(2);
if (overallDistance > 6000000)
{
overallDistance = 0;
lastDistance = 0;
}
}
overallDistance += lastDistance;
overallResult.text = overallDistance.ToString() + " meters";
}
void CalculateSpeed()
{
speed = lastDistance / lastTime * 3.6f;
speedText.text = speed.ToString();
}
void CalculateAcceleration()
{
acceleration = (speed - speed0) / lastTime;
accelerationText.text = acceleration.ToString();
}
}
I want to convert from Gregorian to Hijri(Islamic) date and I use this class
the problem is islamic month's days is <29 , 30 , 29 , 30 else
but this class month's days is < 30, 29, 30, 29 else
any body can help fix this?
import java.util.Calendar;
/**
* Gregorian-Hijri Dates Converter
*
*
* This Code is used to convert Gregorian dates to Hijri Dates
*
*
*/
public class DateHigri {
static double gmod(double n,double m) {
return ((n % m) + m) % m;
}
static double[] kuwaiticalendar(boolean adjust) {
Calendar today = Calendar.getInstance();
int adj=0;
if(adjust){
adj=0;
}else{
adj=1;
}
if (adjust) {
int adjustmili = 1000 * 60 * 60 * 24 * adj;
long todaymili = today.getTimeInMillis() + adjustmili;
today.setTimeInMillis(todaymili);
}
double day = today.get(Calendar.DAY_OF_MONTH);
double month = today.get(Calendar.MONTH);
double year = today.get(Calendar.YEAR);
double m = month + 1;
double y = year;
if (m < 3) {
y -= 1;
m += 12;
}
double a = Math.floor(y / 100.);
double b = 2 - a + Math.floor(a / 4.);
if (y < 1583)
b = 0;
if (y == 1582) {
if (m > 10)
b = -10;
if (m == 10) {
b = 0;
if (day > 4)
b = -10;
}
}
double jd = Math.floor(365.25 * (y + 4716)) + Math.floor(30.6001 * (m + 1)) + day
+ b - 1524;
b = 0;
if (jd > 2299160) {
a = Math.floor((jd - 1867216.25) / 36524.25);
b = 1 + a - Math.floor(a / 4.);
}
double bb = jd + b + 1524;
double cc = Math.floor((bb - 122.1) / 365.25);
double dd = Math.floor(365.25 * cc);
double ee = Math.floor((bb - dd) / 30.6001);
day = (bb - dd) - Math.floor(30.6001 * ee);
month = ee - 1;
if (ee > 13) {
cc += 1;
month = ee - 13;
}
year = cc - 4716;
double wd = gmod(jd + 1, 7) + 1;
double iyear = 10631. / 30.;
double epochastro = 1948084;
double epochcivil = 1948085;
double shift1 = 8.01 / 60.;
double z = jd - epochastro;
double cyc = Math.floor(z / 10631.);
z = z - 10631 * cyc;
double j = Math.floor((z - shift1) / iyear);
double iy = 30 * cyc + j;
z = z - Math.floor(j * iyear + shift1);
double im = Math.floor((z + 28.5001) / 29.5);
if (im == 13)
im = 12;
double id = z - Math.floor(29.5001 * im - 29);
double[] myRes = new double[8];
myRes[0] = day; // calculated day (CE)
myRes[1] = month - 1; // calculated month (CE)
myRes[2] = year; // calculated year (CE)
myRes[3] = jd - 1; // julian day number
myRes[4] = wd - 1; // weekday number
myRes[5] = id; // islamic date
myRes[6] = im - 1; // islamic month
myRes[7] = iy; // islamic year
return myRes;
}
static String writeIslamicDate() {
String[] wdNames = {"Ahad", "Ithnin", "Thulatha", "Arbaa", "Khams",
"Jumuah", "Sabt"};
String[] iMonthNames = {"Muharram", "Safar", "Rabi'ul Awwal",
"Rabi'ul Akhir", "Jumadal Ula", "Jumadal Akhira", "Rajab",
"Sha'ban", "Ramadan", "Shawwal", "Dhul Qa'ada", "Dhul Hijja"};
// This Value is used to give the correct day +- 1 day
boolean dayTest=true;
double[] iDate = kuwaiticalendar(dayTest);
String outputIslamicDate = wdNames[(int) iDate[4]] + ", " + iDate[5] + " "
+ iMonthNames[(int) iDate[6]] + " " + iDate[7] + " AH";
return outputIslamicDate;
}
}
I have used the tutorial from Here
and successfully made a similar puzzle game (with custom layout and imaged tiles)
My problem now is to recognize when the user finishes the puzzle..
I am and android developer, but this cocos2d is very new to me.
I have downloaded the source code to check what the writer of the tutorial have done to find when the user has finished the puzzle, but his code for this part is not working, and I need to find a way to check after every move if the user has finished or not..
if it were android I would not have any problem with it..
here is the relevant code:
public void generateTiles(){
//We create a Node element to hold all our tiles
CCNode tilesNode = CCNode.node();
tilesNode.setTag(TILE_NODE_TAG);
addChild(tilesNode);
float scalefactor ; // a value we compute to help scale our tiles
int useableheight ;
int tileIndex = 0 ;
//We attempt to calculate the right size for the tiles given the screen size and
//space left after adding the status label at the top
int nextval ;
int[] tileNumbers = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};//{12,1,10,2,7,11,4,14,5,0,9,15,8,13,6,3}; //random but solvable sequence of numbers
//TILE_SQUARE_SIZE = (int) ((screenSize.height *generalscalefactor)/NUM_ROWS) ;
int useablewidth = (int) (screenSize.width - statusLabel.getContentSize().width*generalscalefactor ) ;
useableheight = (int) (screenSize.height - 40*generalscalefactor - statusLabel.getContentSize().height * 1.3f*generalscalefactor) ;
TILE_SQUARE_SIZE = (int) Math.min((useableheight/NUM_ROWS) , (useablewidth/NUM_COLUMNS)) ;
toppoint = (int) (useableheight - (TILE_SQUARE_SIZE / 2) + 30*generalscalefactor) ;
scalefactor = TILE_SQUARE_SIZE / 125.0f ;
topleft = (int) ((TILE_SQUARE_SIZE / 2) + 15*generalscalefactor) ;
for (int j = toppoint ; j > toppoint - (TILE_SQUARE_SIZE * NUM_ROWS); j-= TILE_SQUARE_SIZE){
for (int i = topleft ; i < (topleft - 5*generalscalefactor) + (TILE_SQUARE_SIZE * NUM_COLUMNS); i+= TILE_SQUARE_SIZE){
if (tileIndex >= (NUM_ROWS * NUM_COLUMNS)) {
break ;
}
nextval = tileNumbers[tileIndex ];
//Generate tile by it's number and it's subfolder
Tile tile = new Tile();
tile.setIndex(nextval);
tile.setSprite(CCSprite.sprite(subFolder+"/"+subFolder+"_tile_"+String.valueOf(nextval+1)+".jpg"));
tiles.add(tile);
//CCSprite tile = CCSprite.sprite(subFolder+"/"+subFolder+"_tile_"+String.valueOf(nextval+1)+".jpg");
CCNodeExt eachNode = new CCNodeExt();
eachNode.setContentSize(tile.getSprite().getContentSize());
//
//Layout Node based on calculated postion
eachNode.setPosition(i, j);
eachNode.setNodeText(nextval + "");
//Add Tile number
if(showNumbers == true)
{
CCBitmapFontAtlas tileNumber = CCBitmapFontAtlas.bitmapFontAtlas ("00", "bionic.fnt");
tileNumber.setScale(1.4f);
eachNode.setScale(scalefactor);
eachNode.addChild(tile.getSprite(),1,1);
tileNumber.setString(nextval + "");
eachNode.addChild(tileNumber,2 );
}
else
{
eachNode.setScale(scalefactor);
eachNode.addChild(tile.getSprite(),1,1);
}
if( nextval != 0){
tilesNode.addChild(eachNode,1,nextval);
}else {
emptyPosition = CGPoint.ccp(i, j);
}
//Add each Node to a HashMap to note its location
tileIndex++;
}
}
}
#Override
public boolean ccTouchesBegan(MotionEvent event)
{
//Get touch location cordinates
CGPoint location = CCDirector.sharedDirector().convertToGL(CGPoint.ccp(event.getX(), event.getY()));
CGRect spritePos ;
CCNode tilesNode = (CCNode) getChildByTag(TILE_NODE_TAG) ;
//ccMacros.CCLOG("Began", "Began : " + location.x + " : " );
//We loop through each of the tiles and get its cordinates
for (int i = 1 ; i < (NUM_ROWS * NUM_COLUMNS); i++){
CCNodeExt eachNode = (CCNodeExt) tilesNode.getChildByTag(i) ;
//Log.d(String.valueOf(eachNode), String.valueOf(tiles.get(i).getIndex()));
//we construct a rectangle covering the current tiles cordinates
spritePos = CGRect.make(
eachNode.getPosition().x - (eachNode.getContentSize().width*generalscalefactor/2.0f),
eachNode.getPosition().y - (eachNode.getContentSize().height*generalscalefactor/2.0f),
eachNode.getContentSize().width*generalscalefactor ,
eachNode.getContentSize().height*generalscalefactor );
//Check if the user's touch falls inside the current tiles cordinates
if(spritePos.contains(location.x, location.y)){
//ccMacros.CCLOG("Began Touched Node", "Began touched : " + eachNode.getNodeText());
slideCallback(eachNode); // if yes, we pass the tile for sliding.
}
}
return true ;
}
public void slideCallback(CCNodeExt thenode) {
CGPoint nodePosition = thenode.getPosition();
//Determine the position to slide the tile to .. ofcourse only if theres an empty space beside it
if((nodePosition.x - TILE_SQUARE_SIZE)== emptyPosition.x && nodePosition.y == emptyPosition.y){
slideTile("Left", thenode,true);
}else if((nodePosition.x + TILE_SQUARE_SIZE) == emptyPosition.x && nodePosition.y == emptyPosition.y){
slideTile("Right", thenode,true);
}else if((nodePosition.x)== emptyPosition.x && nodePosition.y == (emptyPosition.y + TILE_SQUARE_SIZE )){
slideTile("Down", thenode,true);
}else if((nodePosition.x )== emptyPosition.x && nodePosition.y == (emptyPosition.y - TILE_SQUARE_SIZE)){
slideTile("Up", thenode,true);
}else{
slideTile("Unmovable", thenode,false);
}
}
public void slideTile(String direction, CCNodeExt thenode, boolean move){
CCBitmapFontAtlas moveslabel = (CCBitmapFontAtlas) getChildByTag(MOVES_LABEL_TAG);
if(move && !gameover){
// Increment the moves label and animate the tile
moves ++ ;
moveslabel.setString("Moves : " + CCFormatter.format("%03d", moves ));
//Update statuslabel
statusLabel.setString("Tile : " + thenode.getNodeText() + " -> " + direction);
//Animate the tile to slide it
CGPoint nodePosition = thenode.getPosition();
//Log.d("current pos",String.valueOf(nodePosition));
CGPoint tempPosition = emptyPosition ;
//Log.d("go to pos",String.valueOf(tempPosition));
CCMoveTo movetile = CCMoveTo.action(0.4f, tempPosition);
CCSequence movetileSeq = CCSequence.actions(movetile, CCCallFuncN.action(this, "handleWin"));
thenode.runAction(movetileSeq);
emptyPosition = nodePosition ;
//Play a sound
appcontext = CCDirector.sharedDirector().getActivity();
SoundEngine.sharedEngine().playEffect(appcontext, R.raw.tileclick);
thenode.runAction(movetileSeq);
}else{
}
}
public void handleWin(Object sender){
if(checkCorrect()){
gameover = true ;
Log.d("Game "+String.valueOf(gameover), "VICTORY!");
SoundEngine.sharedEngine().playEffect(appcontext, R.raw.tileclick);
//WinCallback(sender);
}
}
//This method checks if the puzzle has been correctly solved.
public boolean checkCorrect(){
CCNode tileNode = (CCNode) getChildByTag(TILE_NODE_TAG);
int nodeindex = 1 ;
boolean result = false;
int rowindex = 0 ;
for (int j = toppoint ; j > toppoint - (TILE_SQUARE_SIZE * NUM_ROWS); j-= TILE_SQUARE_SIZE){
for (int i = topleft ; i < (topleft - 5*generalscalefactor) + (TILE_SQUARE_SIZE * NUM_COLUMNS); i+= TILE_SQUARE_SIZE){
Log.d(String.valueOf(tileNode.getChildByTag(nodeindex).getPosition().x), String.valueOf(tileNode.getChildByTag(nodeindex).getPosition().y));
Log.d(String.valueOf(i), String.valueOf(j));
if(tileNode.getChildByTag(nodeindex).getPosition().x == i && tileNode.getChildByTag(nodeindex).getPosition().y == j ){
//Log.d(String.valueOf(tileNode.getChildByTag(nodeindex).getPosition().x), String.valueOf(tileNode.getChildByTag(nodeindex).getPosition().y));
//Log.d(String.valueOf(i), String.valueOf(j));
result = true ;
Log.d("Game "+String.valueOf(result), "result");
}else{
//Log.d("Game "+String.valueOf(false), "result");
return false ;
}
nodeindex++ ;
//Log.d("nodeindex "+String.valueOf(nodeindex), "index total");
if(nodeindex == (NUM_ROWS * NUM_COLUMNS)){
Log.d("Game "+String.valueOf(result), "result");
return result ;
}
}
}
rowindex = 0 ;
Log.d("Game "+String.valueOf(result), "result");
return result ;
}
}
basically I just need the last method to be fixed for me, all of the other code is just for reference and understanding of the last needed part..
OK, since I have solved it, and I know it is kind of hard to get good examples and answers on this subject, I will share the solution here:
Add this line as global declaration:
//Array to hold the correct order of tiles so we can compare..
private ArrayList<Tile> tilesCompleted = new ArrayList<Tile>();
and change this method:
public void generateTiles(){
//We create a Node element to hold all our tiles
tilesNode.setTag(TILE_NODE_TAG);
addChild(tilesNode);
float scalefactor ; // a value we compute to help scale our tiles
int useableheight ;
int tileIndex = 0 ;
//We attempt to calculate the right size for the tiles given the screen size and
//space left after adding the status label at the top
int nextval ;
//{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};//
int[] tileNumbers = {12,1,10,2,7,11,4,14,5,0,9,15,8,13,6,3}; //random but solvable sequence of numbers
//TILE_SQUARE_SIZE = (int) ((screenSize.height *generalscalefactor)/NUM_ROWS) ;
int useablewidth = (int) (screenSize.width - statusLabel.getContentSize().width*generalscalefactor ) ;
useableheight = (int) (screenSize.height - 40*generalscalefactor - statusLabel.getContentSize().height * 1.3f*generalscalefactor) ;
TILE_SQUARE_SIZE = (int) Math.min((useableheight/NUM_ROWS) , (useablewidth/NUM_COLUMNS)) ;
toppoint = (int) (useableheight - (TILE_SQUARE_SIZE / 2) + 30*generalscalefactor) ;
scalefactor = TILE_SQUARE_SIZE / 125.0f ;
topleft = (int) ((TILE_SQUARE_SIZE / 2) + 15*generalscalefactor) ;
for (int j = toppoint ; j > toppoint - (TILE_SQUARE_SIZE * NUM_ROWS); j-= TILE_SQUARE_SIZE){
for (int i = topleft ; i < (topleft - 5*generalscalefactor) + (TILE_SQUARE_SIZE * NUM_COLUMNS); i+= TILE_SQUARE_SIZE){
if (tileIndex >= (NUM_ROWS * NUM_COLUMNS)) {
break ;
}
nextval = tileNumbers[tileIndex ];
//Generate tile by it's number and it's subfolder
Tile tile = new Tile();
tile.setIndex(nextval);
tile.setSprite(CCSprite.sprite(subFolder+"/"+subFolder+"_tile_"+String.valueOf(nextval+1)+".jpg"));
tiles.add(tile);
//This is the solution
if(tileIndex > 0)
{
tile.setPositionX(i);
tile.setPositionY(j);
tile.setIndex(tileIndex);
tilesCompleted.add(tile);
}
else
tilesCompleted.add(tile);
//CCSprite tile = CCSprite.sprite(subFolder+"/"+subFolder+"_tile_"+String.valueOf(nextval+1)+".jpg");
CCNodeExt eachNode = new CCNodeExt();
eachNode.setContentSize(tile.getSprite().getContentSize());
//
//Layout Node based on calculated postion
eachNode.setPosition(i, j);
eachNode.setNodeText(nextval + "");
//Add Tile number
if(showNumbers == true)
{
CCBitmapFontAtlas tileNumber = CCBitmapFontAtlas.bitmapFontAtlas ("00", "bionic.fnt");
tileNumber.setScale(1.4f);
eachNode.setScale(scalefactor);
eachNode.addChild(tile.getSprite(),1,1);
tileNumber.setString(nextval + "");
eachNode.addChild(tileNumber,2 );
}
else
{
eachNode.setScale(scalefactor);
eachNode.addChild(tile.getSprite(),1,1);
}
if( nextval != 0){
tilesNode.addChild(eachNode,1,nextval);
}else {
emptyPosition = CGPoint.ccp(i, j);
}
//Add each Node to a HashMap to note its location
tileIndex++;
}
}
}
And now change this:
//This method checks if the puzzle has been correctly solved.
public boolean checkCorrect(){
//CCNode tileNodes = (CCNode) getChildByTag(TILE_NODE_TAG);
int nodeindex = 0 ;
boolean result = false;
int rowindex = 0 ;
for (int j = toppoint ; j > toppoint - (TILE_SQUARE_SIZE * NUM_ROWS); j-= TILE_SQUARE_SIZE){
if(nodeindex > 0)
{
//Log.d("y", String.valueOf(tilesNode.getChildByTag(nodeindex).getPosition().y));
//Log.d("J", String.valueOf(tilesCompleted.get(nodeindex).getPositionY()));
}
for (int i = topleft ; i < (topleft - 5*generalscalefactor) + (TILE_SQUARE_SIZE * NUM_COLUMNS); i+= TILE_SQUARE_SIZE){
if(nodeindex > 0)
{
//Log.d("x", String.valueOf(tilesNode.getChildByTag(nodeindex).getPosition().x));
//Log.d("i", String.valueOf(tilesCompleted.get(nodeindex).getPositionX()));
}
if(nodeindex>0)
{
if(tilesNode.getChildByTag(nodeindex).getPosition().x == tilesCompleted.get(nodeindex).getPositionX()
&& tilesNode.getChildByTag(nodeindex).getPosition().y == tilesCompleted.get(nodeindex).getPositionY()){
//Log.d(String.valueOf(tileNode.getChildByTag(nodeindex).getPosition().x), String.valueOf(tileNode.getChildByTag(nodeindex).getPosition().y));
//Log.d(String.valueOf(i), String.valueOf(j));
result = true ;
Log.d("Game "+String.valueOf(result), "result");
}else{
//Log.d("Game "+String.valueOf(false), "result");
return false ;
}
}
nodeindex++ ;
//Log.d("nodeindex "+String.valueOf(nodeindex), "index total");
if(nodeindex == (NUM_ROWS * NUM_COLUMNS)){
Log.d("Game "+String.valueOf(result), "result");
return result ;
}
}
}
rowindex = 0 ;
Log.d("Game "+String.valueOf(result), "result");
return result ;
}
}
GOOD LUCK :)
I'm new in Android development. I'm looking for any method that applies pitch shifting to output sound (in real-time). But I couldn't find any point to start.
I've found this topic but I still don't know how can I apply this.
Any suggestions?
In general, the algorithm is called a phase vocoder -- searching for that on the Internets should get you started.
There are a few open source phase vocoders out there, you should be able to use those for reference too.
You can do phase vocoder in real-time -- the main component used is the FFT, so you'll need a fast FFT. The Android libraries can do this for you, see this documentation: http://developer.android.com/reference/android/media/audiofx/Visualizer.html
As it happens, I'm about to release an open source FFT for ARM that is faster than Apple's vDSP library (which was hitherto the fastest). I'll post back in a few days when I've uploaded it to github.com.
Good luck.
There is no built-in pitch shifting algorithm in the Android SDK. You have to code your own. Pitch shifting is a real hardcore DSP algorithm; good sounding algorithms are results of many months or rather years of development...
I personally do not know any Java implementation so I suggest you to adopt some of the free C++ PS algorithms, the best one - which I use in my audio applications, is SoundTouch:
http://www.surina.net/soundtouch/
I played with its code a little and it seems it would not be too much complicated to rewrite it in Java.
HOME URL: http://www.dspdimension.com
public class AudioPitch{
//region Private Static Memebers
private static int MAX_FRAME_LENGTH = 8192;
private static double M_PI = 3.14159265358979323846;
private static float[] gInFIFO = new float[MAX_FRAME_LENGTH];
private static float[] gOutFIFO = new float[MAX_FRAME_LENGTH];
private static float[] gFFTworksp = new float[2 * MAX_FRAME_LENGTH];
private static float[] gLastPhase = new float[MAX_FRAME_LENGTH / 2 + 1];
private static float[] gSumPhase = new float[MAX_FRAME_LENGTH / 2 + 1];
private static float[] gOutputAccum = new float[2 * MAX_FRAME_LENGTH];
private static float[] gAnaFreq = new float[MAX_FRAME_LENGTH];
private static float[] gAnaMagn = new float[MAX_FRAME_LENGTH];
private static float[] gSynFreq = new float[MAX_FRAME_LENGTH];
private static float[] gSynMagn = new float[MAX_FRAME_LENGTH];
private static long gRover;
//endregion
public static void PitchShift(float pitchShift, long numSampsToProcess, long fftFrameSize/*(long)2048*/, long osamp/*(long)10*/, float sampleRate, float[] indata)
{
double magn, phase, tmp, window, real, imag;
double freqPerBin, expct;
long i, k, qpd, index, inFifoLatency, stepSize, fftFrameSize2;
float[] outdata = indata;
/* set up some handy variables */
fftFrameSize2 = fftFrameSize / 2;
stepSize = fftFrameSize / osamp;
freqPerBin = sampleRate / (double)fftFrameSize;
expct = 2.0 * M_PI * (double)stepSize / (double)fftFrameSize;
inFifoLatency = fftFrameSize - stepSize;
if (gRover == 0) gRover = inFifoLatency;
/* main processing loop */
for (i = 0; i < numSampsToProcess; i++)
{
/* As long as we have not yet collected enough data just read in */
gInFIFO[(int) gRover] = indata[(int) i];
outdata[(int) i] = gOutFIFO[(int) (gRover - inFifoLatency)];
gRover++;
/* now we have enough data for processing */
if (gRover >= fftFrameSize)
{
gRover = inFifoLatency;
/* do windowing and re,im interleave */
for (k = 0; k < fftFrameSize; k++)
{
window = -.5 * Math.cos(2.0 * M_PI * (double)k / (double)fftFrameSize) + .5;
gFFTworksp[(int) (2 * k)] = (float)(gInFIFO[(int) k] * window);
gFFTworksp[(int) (2 * k + 1)] = 0.0F;
}
/* ***************** ANALYSIS ******************* */
/* do transform */
ShortTimeFourierTransform(gFFTworksp, fftFrameSize, -1);
/* this is the analysis step */
for (k = 0; k <= fftFrameSize2; k++)
{
/* de-interlace FFT buffer */
real = gFFTworksp[(int) (2 * k)];
imag = gFFTworksp[(int) (2 * k + 1)];
/* compute magnitude and phase */
magn = 2.0 * Math.sqrt(real * real + imag * imag);
phase = smbAtan2(imag, real);
/* compute phase difference */
tmp = phase - gLastPhase[(int) k];
gLastPhase[(int) k] = (float)phase;
/* subtract expected phase difference */
tmp -= (double)k * expct;
/* map delta phase into +/- Pi interval */
qpd = (long)(tmp / M_PI);
if (qpd >= 0) qpd += qpd & 1;
else qpd -= qpd & 1;
tmp -= M_PI * (double)qpd;
/* get deviation from bin frequency from the +/- Pi interval */
tmp = osamp * tmp / (2.0 * M_PI);
/* compute the k-th partials' true frequency */
tmp = (double)k * freqPerBin + tmp * freqPerBin;
/* store magnitude and true frequency in analysis arrays */
gAnaMagn[(int) k] = (float)magn;
gAnaFreq[(int) k] = (float)tmp;
}
/* ***************** PROCESSING ******************* */
/* this does the actual pitch shifting */
for (int zero = 0; zero < fftFrameSize; zero++)
{
gSynMagn[zero] = 0;
gSynFreq[zero] = 0;
}
for (k = 0; k <= fftFrameSize2; k++)
{
index = (long)(k * pitchShift);
if (index <= fftFrameSize2)
{
gSynMagn[(int) index] += gAnaMagn[(int) k];
gSynFreq[(int) index] = gAnaFreq[(int) k] * pitchShift;
}
}
/* ***************** SYNTHESIS ******************* */
/* this is the synthesis step */
for (k = 0; k <= fftFrameSize2; k++)
{
/* get magnitude and true frequency from synthesis arrays */
magn = gSynMagn[(int) k];
tmp = gSynFreq[(int) k];
/* subtract bin mid frequency */
tmp -= (double)k * freqPerBin;
/* get bin deviation from freq deviation */
tmp /= freqPerBin;
/* take osamp into account */
tmp = 2.0 * M_PI * tmp / osamp;
/* add the overlap phase advance back in */
tmp += (double)k * expct;
/* accumulate delta phase to get bin phase */
gSumPhase[(int) k] += (float)tmp;
phase = gSumPhase[(int) k];
/* get real and imag part and re-interleave */
gFFTworksp[(int) (2 * k)] = (float)(magn * Math.cos(phase));
gFFTworksp[(int) (2 * k + 1)] = (float)(magn * Math.sin(phase));
}
/* zero negative frequencies */
for (k = fftFrameSize + 2; k < 2 * fftFrameSize; k++) gFFTworksp[(int) k] = 0.0F;
/* do inverse transform */
ShortTimeFourierTransform(gFFTworksp, fftFrameSize, 1);
/* do windowing and add to output accumulator */
for (k = 0; k < fftFrameSize; k++)
{
window = -.5 * Math.cos(2.0 * M_PI * (double)k / (double)fftFrameSize) + .5;
gOutputAccum[(int) k] += (float)(2.0 * window * gFFTworksp[(int) (2 * k)] / (fftFrameSize2 * osamp));
}
for (k = 0; k < stepSize; k++) gOutFIFO[(int) k] = gOutputAccum[(int) k];
/* shift accumulator */
//memmove(gOutputAccum, gOutputAccum + stepSize, fftFrameSize * sizeof(float));
for (k = 0; k < fftFrameSize; k++)
{
gOutputAccum[(int) k] = gOutputAccum[(int) (k + stepSize)];
}
/* move input FIFO */
for (k = 0; k < inFifoLatency; k++) gInFIFO[(int) k] = gInFIFO[(int) (k + stepSize)];
}
}
}
//endregion
//region Private Static Methods
public static void ShortTimeFourierTransform(float[] fftBuffer, long fftFrameSize, long sign)
{
float wr, wi, arg, temp;
float tr, ti, ur, ui;
long i, bitm, j, le, le2, k;
for (i = 2; i < 2 * fftFrameSize - 2; i += 2)
{
for (bitm = 2, j = 0; bitm < 2 * fftFrameSize; bitm <<= 1)
{
if ((i & bitm) != 0) j++;
j <<= 1;
}
if (i < j)
{
temp = fftBuffer[(int) i];
fftBuffer[(int) i] = fftBuffer[(int) j];
fftBuffer[(int) j] = temp;
temp = fftBuffer[(int) (i + 1)];
fftBuffer[(int) (i + 1)] = fftBuffer[(int) (j + 1)];
fftBuffer[(int) (j + 1)] = temp;
}
}
long max = (long)(Math.log(fftFrameSize) / Math.log(2.0) + .5);
for (k = 0, le = 2; k < max; k++)
{
le <<= 1;
le2 = le >> 1;
ur = 1.0F;
ui = 0.0F;
arg = (float)M_PI / (le2 >> 1);
wr = (float)Math.cos(arg);
wi = (float)(sign * Math.sin(arg));
for (j = 0; j < le2; j += 2)
{
for (i = j; i < 2 * fftFrameSize; i += le)
{
tr = fftBuffer[(int) (i + le2)] * ur - fftBuffer[(int) (i + le2 + 1)] * ui;
ti = fftBuffer[(int) (i + le2)] * ui + fftBuffer[(int) (i + le2 + 1)] * ur;
fftBuffer[(int) (i + le2)] = fftBuffer[(int) i] - tr;
fftBuffer[(int) (i + le2 + 1)] = fftBuffer[(int) (i + 1)] - ti;
fftBuffer[(int) i] += tr;
fftBuffer[(int) (i + 1)] += ti;
}
tr = ur * wr - ui * wi;
ui = ur * wi + ui * wr;
ur = tr;
}
}
}
//endregion
private static double smbAtan2(double x, double y)
{
double signx;
if (x > 0.) signx = 1.;
else signx = -1.;
if (x == 0.) return 0.;
if (y == 0.) return signx * M_PI / 2.;
return Math.atan2(x, y);
}
}
this code working too but very consumption cpu usage.
pitchShift between 0.5 -2.0
call this class as below:
int maxValueOFShort = 32768;
short [] buffer = new short[800];
float[] inData = new float[buffer.length];
while (audiorackIsRun)
{
int m = recorder.read(buffer, 0, buffer.length);
for(int n=0; n<buffer.length;n++)
inData[n] = buffer[n]/(float)maxValueOFShort;
AudioPitch.PitchShift(1, buffer.length, 4096, 4, 44100, inData);
for(int n=0; n<buffer.length;n++)
buffer[n] = (short)(inData[n]*maxValueOFShort);
player.write(buffer, 0, buffer.length);
}