Issue with WifiManager.calculateSignalLevel(RSSI, 5) - android

I am trying to use the Wifimanager to calculate the Signal Level of the access points found during a scan.
I am using the following method:
WifiManager.calculateSignalLevel(int, int)
But it appears to always return the same int no matter what the RSSI level is.
Here is my code:
public int calculateQoS(int aRSSI){
signalLevel = WifiManager.calculateSignalLevel(RSSI, 5);
return signalLevel;
}
public void testCalculateQoS(){
Log.d("signal", "signal = : "
+ connMonitor.calculateQoS(-44)
+ " " + connMonitor.calculateQoS(-80)
+ " " + connMonitor.calculateQoS(-120)
+ " " + connMonitor.calculateQoS(-20));
}
The logging outputs 1 for all the test cases for calculateQoS(int).
Am I missing something simple here? Why is the SignalLevel always 1?

It seems that calculateSignalLevel is implemented this way:
public static int calculateSignalLevel(int rssi, int numLevels) {
if (rssi <= MIN_RSSI) {
return 0;
} else if (rssi >= MAX_RSSI) {
return numLevels - 1;
} else {
int partitionSize = (MAX_RSSI - MIN_RSSI) / (numLevels - 1);
return (rssi - MIN_RSSI) / partitionSize;
}
}
Maybe this code snippet can explain your problem. Also note:
http://code.google.com/p/android/issues/detail?id=2555

thanks to this question I could prevent problem on lower API versions then the one I'm targetting. So I made this so you can use it on any platform version.
public int getWifiSignalStrength(Context context){
int MIN_RSSI = -100;
int MAX_RSSI = -55;
int levels = 101;
WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiInfo info = wifi.getConnectionInfo();
int rssi = info.getRssi();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH){
return WifiManager.calculateSignalLevel(info.getRssi(), levels);
} else {
// this is the code since 4.0.1
if (rssi <= MIN_RSSI) {
return 0;
} else if (rssi >= MAX_RSSI) {
return levels - 1;
} else {
float inputRange = (MAX_RSSI - MIN_RSSI);
float outputRange = (levels - 1);
return (int)((float)(rssi - MIN_RSSI) * outputRange / inputRange);
}
}
}//end method

This issue is only in android 2.3,
you can replace it with latest code of WiFiManger of an android 4.2
Here is the code:
public int calculateSignalLevel(int rssi, int numLevels) {
if(rssi <= MIN_RSSI) {
return 0;
} else if(rssi >= MAX_RSSI) {
return numLevels - 1;
} else {
float inputRange = (MAX_RSSI - MIN_RSSI);
float outputRange = (numLevels - 1);
if(inputRange != 0)
return (int) ((float) (rssi - MIN_RSSI) * outputRange / inputRange);
}
return 0;
}

Related

Android SurfaceView onTouchEvent not getting called

I'm developing a game using SurfaceView which listens to touch events. The onTouchEvent method in SurfaceView works fine for many of the devices, but in some devices, sometimes it doesn't get called (Moto X Style is the one) and my app also stops responding.
I guess that this might be due to the overloading of main thread due to which onTouchEvent is starving.
Could some Android experts over here give me some tips to reduce the load on main thread if it's getting overloaded, or there might be some other reason which may cause this
The code is quite complex but still I'm posting some if you want to go through it
GameLoopThread
public class GameLoopThread extends Thread{
private GameView view;
// desired fps
private final static int MAX_FPS = 120;
// maximum number of frames to be skipped
private final static int MAX_FRAME_SKIPS = 5;
// the frame period
private final static int FRAME_PERIOD = 1000 / MAX_FPS;
private boolean running = false;
public GameLoopThread(GameView view){
this.view = view;
}
public void setRunning(boolean running){
this.running = running;
}
public boolean isRunning() {
return running;
}
#Override
public void run() {
Canvas canvas;
long beginTime; // the time when the cycle begun
long timeDiff; // the time it took for the cycle to execute
int sleepTime; // ms to sleep (<0 if we're behind)
int framesSkipped; // number of frames being skipped
while (running) {
canvas = null;
// try locking the canvas for exclusive pixel editing
// in the surface
try {
canvas = view.getHolder().lockCanvas();
synchronized (view.getHolder()) {
beginTime = System.nanoTime();
framesSkipped = 0; // resetting the frames skipped
// update game state
// render state to the screen
// draws the canvas on the panel
this.view.draw(canvas);
// calculate how long did the cycle take
timeDiff = System.nanoTime() - beginTime;
// calculate sleep time
sleepTime = (int)(FRAME_PERIOD - timeDiff/1000000);
if (sleepTime > 0) {
// if sleepTime > 0 we're OK
try {
// send the thread to sleep for a short period
// very useful for battery saving
Thread.sleep(sleepTime);
} catch (InterruptedException e) {}
}
while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
// update without rendering
// add frame period to check if in next frame
sleepTime += FRAME_PERIOD;
framesSkipped++;
}
}
}
finally {
// in case of an exception the surface is not left in
// an inconsistent state
view.getHolder().unlockCanvasAndPost(canvas);
} // end finally
}
}
}
GameView
public class GameView extends SurfaceView {
ArrayList<Bitmap> circles = new ArrayList<>();
int color;
public static boolean isGameOver;
public GameLoopThread gameLoopThread;
Circle circle; // Code for Circle class is provided below
public static int score = 0;
public static int stars = 0;
final Handler handler = new Handler();
int remainingTime;
boolean oneTimeFlag;
Bitmap replay;
Bitmap home;
Bitmap star;
int highScore;
boolean isLeaving;
public GameView(Context context, ArrayList<Bitmap> circles, int color) {
super(context);
this.circles = circles;
this.color = color;
oneTimeFlag = true;
gameLoopThread = new GameLoopThread(GameView.this);
getHolder().addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
if (!gameLoopThread.isRunning()) {
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
gameLoopThread.setRunning(false);
gameLoopThread = new GameLoopThread(GameView.this);
}
});
initializeCircles();
if(!gameLoopThread.isRunning()) {
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
}
public void initializeCircles() {
ArrayList<String> numbers = new ArrayList<>();
for(int i=0;i<10;i++)
numbers.add(i+"");
Random random = new Random();
int position = random.nextInt(4);
numbers.remove(color + "");
int p1 = position;
int r1 = Integer.valueOf(numbers.get(random.nextInt(9)));
numbers.remove(r1+"");
int r2 = Integer.valueOf(numbers.get(random.nextInt(8)));
numbers.remove(r2 + "");
int r3 = Integer.valueOf(numbers.get(random.nextInt(7)));
ArrayList<Bitmap> bitmaps = new ArrayList<>();
if(position == 0) {
bitmaps.add(circles.get(color));
bitmaps.add(circles.get(r1));
bitmaps.add(circles.get(r2));
bitmaps.add(circles.get(r3));
}
else if(position == 1) {
bitmaps.add(circles.get(r1));
bitmaps.add(circles.get(color));
bitmaps.add(circles.get(r2));
bitmaps.add(circles.get(r3));
}
else if(position == 2) {
bitmaps.add(circles.get(r1));
bitmaps.add(circles.get(r2));
bitmaps.add(circles.get(color));
bitmaps.add(circles.get(r3));
}
else {
bitmaps.add(circles.get(r1));
bitmaps.add(circles.get(r2));
bitmaps.add(circles.get(r3));
bitmaps.add(circles.get(color));
}
numbers = new ArrayList<>();
for(int i=0;i<10;i++)
numbers.add(i+"");
position = random.nextInt(4);
numbers.remove(color + "");
r1 = Integer.valueOf(numbers.get(random.nextInt(9)));
numbers.remove(r1 + "");
r2 = Integer.valueOf(numbers.get(random.nextInt(8)));
numbers.remove(r2 + "");
r3 = Integer.valueOf(numbers.get(random.nextInt(7)));
if(position == 0) {
bitmaps.add(circles.get(color));
bitmaps.add(circles.get(r1));
bitmaps.add(circles.get(r2));
bitmaps.add(circles.get(r3));
}
else if(position == 1) {
bitmaps.add(circles.get(r1));
bitmaps.add(circles.get(color));
bitmaps.add(circles.get(r2));
bitmaps.add(circles.get(r3));
}
else if(position == 2) {
bitmaps.add(circles.get(r1));
bitmaps.add(circles.get(r2));
bitmaps.add(circles.get(color));
bitmaps.add(circles.get(r3));
}
else {
bitmaps.add(circles.get(r1));
bitmaps.add(circles.get(r2));
bitmaps.add(circles.get(r3));
bitmaps.add(circles.get(color));
}
circle = new Circle(this, bitmaps, circles, p1, position, color, getContext());
}
#Override
public void draw(Canvas canvas) {
if(canvas != null) {
super.draw(canvas);
canvas.drawColor(Color.WHITE);
if(!isGameOver && timer != null)
stopTimerTask();
try {
circle.draw(canvas);
} catch (GameOverException e) {
isGameOver = true;
if(isLeaving)
gameOver(canvas);
else if(GameActivity.counter > 0) {
gameOver(canvas);
GameActivity.counter++;
} else {
if (oneTimeFlag) {
int size1 = 200 * GameActivity.SCREEN_HEIGHT / 1280;
int size2 = 125 * GameActivity.SCREEN_HEIGHT / 1280;
float ratio = (float) GameActivity.SCREEN_HEIGHT / 1280;
replay = GameActivity.decodeSampledBitmapFromResource(getResources(), R.drawable.replay, size1, size1);
home = GameActivity.decodeSampledBitmapFromResource(getResources(), R.drawable.home, size2, size2);
continueButton = GameActivity.decodeSampledBitmapFromResource(getContext().getResources(), R.drawable.button, (int) (540 * ratio), (int) (100 * ratio));
star = GameActivity.decodeSampledBitmapFromResource(getContext().getResources(), R.drawable.star1, (int) (220 * ratio), (int) (220 * ratio));
int w = (int) ((float) GameActivity.SCREEN_WIDTH * 0.9);
oneTimeFlag = false;
}
if (askPurchaseScreen == 2) {
gameOver(canvas);
} else {
canvas.drawColor(Circle.endColor);
}
}
}
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
circle.onTouch(x, y);
return true;
}
}
Circle
public class Circle {
int x;
int y1;
int y2;
public static float speedY1 = 12.5f*(float)GameActivity.SCREEN_HEIGHT/1280;
public static float speedY2 = 12.5f*(float)GameActivity.SCREEN_HEIGHT/1280;
ArrayList<Bitmap> bitmaps;
GameView gameView;
int p1; // Position of required circle in slot 1
int p2; // Position of required circle in slot 2
int color;
int tempColor;
int width;
Context context;
// Centers of required circle
float centerX1;
float centerX2;
float centerY1;
float centerY2;
ArrayList<Bitmap> circles = new ArrayList<>();
boolean touchedFirst;
boolean touchedSecond;
int count1 = 1; // Slot 1 circle radius animation
int count2 = 1; // Slot 2 circle radius animation
float tempSpeedY1;
float tempSpeedY2;
boolean stopY1;
boolean stopY2;
int barCounter = 1;
int loopCount = 0;
int endGameCount = 0; // Count to move circle upwards
double limit;
float endRadiusSpeed;
int endSlot; // Where you died
int endRadiusCount = 0; // Count to increase circle radius
int barEndCounter = 1;
final Handler handler = new Handler();
boolean exception;
public static int endColor;
public Circle(GameView gameView, ArrayList<Bitmap> bitmaps, ArrayList<Bitmap> circles, int p1, int p2, int color, Context context) {
this.gameView = gameView;
this.bitmaps = bitmaps;
this.circles = circles;
this.p1 = p1;
this.p2 = p2;
this.color = color;
this.context = context;
width = GameActivity.SCREEN_WIDTH / 4 - 10;
x = 10;
y1 = 0;
y2 = -(GameActivity.SCREEN_HEIGHT + width) / 2;
centerX1 = x + p1 * (10 + width) + width / 2;
centerY1 = y1 + width / 2;
centerX2 = x + p2 * (10 + width) + width / 2;
centerY2 = y2 + width / 2;
}
public void update() throws GameOverException {
y1+= speedY1;
y2+= speedY2;
centerY1+= speedY1;
centerY2+= speedY2;
float ratio = (float)GameActivity.SCREEN_HEIGHT/1280;
limit = width/(20*ratio);
if(y1 >= gameView.getHeight()) {
loopCount++;
if(touchedFirst)
touchedFirst = false;
else {
speedY1 = speedY2 = -(12.5f * ratio);
endColor = bitmaps.get(p1).getPixel(width/2, width/2);
endGameCount += 1;
endSlot = 1;
}
if(endGameCount == 0) {
if (stopY1) {
tempSpeedY1 = speedY1;
speedY1 = 0;
ArrayList<Integer> numbers = new ArrayList<>();
for (int i = 0; i < 10; i++) {
if (i != color)
numbers.add(i);
}
tempColor = numbers.get(new Random().nextInt(9));
}
y1 = -(gameView.getWidth() / 4 - 10);
count1 = 1;
setBitmaps(1);
}
}
else if(y2 >= gameView.getHeight()) {
loopCount++;
if(touchedSecond)
touchedSecond = false;
else {
speedY1 = speedY2 = -(12.5f * ratio);
endColor = bitmaps.get(p2 + 4
).getPixel(width/2, width/2);
endGameCount += 1;
endSlot = 2;
}
if(endGameCount == 0) {
if (stopY2) {
tempSpeedY2 = speedY2;
speedY2 = 0;
}
y2 = -(gameView.getWidth() / 4 - 10);
count2 = 1;
setBitmaps(2);
}
}
}
public void setBitmaps(int slot) {
ArrayList<String> numbers = new ArrayList<>();
for(int i=0;i<10;i++)
numbers.add(i+"");
Random random = new Random();
int position = random.nextInt(4);
numbers.remove(color + "");
int r1 = Integer.valueOf(numbers.get(random.nextInt(9)));
numbers.remove(r1+"");
int r2 = Integer.valueOf(numbers.get(random.nextInt(8)));
numbers.remove(r2 + "");
int r3 = Integer.valueOf(numbers.get(random.nextInt(7)));
if(position == 0) {
bitmaps.set((slot - 1)*4, circles.get(color));
bitmaps.set((slot - 1)*4 + 1, circles.get(r1));
bitmaps.set((slot - 1)*4 + 2, circles.get(r2));
bitmaps.set((slot - 1)*4 + 3, circles.get(r3));
}
else if(position == 1) {
bitmaps.set((slot - 1)*4, circles.get(r1));
bitmaps.set((slot - 1)*4 + 1, circles.get(color));
bitmaps.set((slot - 1)*4 + 2, circles.get(r2));
bitmaps.set((slot - 1)*4 + 3, circles.get(r3));
}
else if(position == 2) {
bitmaps.set((slot - 1)*4, circles.get(r1));
bitmaps.set((slot - 1)*4 + 1, circles.get(r2));
bitmaps.set((slot - 1)*4 + 2, circles.get(color));
bitmaps.set((slot - 1)*4 + 3, circles.get(r3));
} else {
bitmaps.set((slot - 1)*4,circles.get(r1));
bitmaps.set((slot - 1)*4 + 1,circles.get(r2));
bitmaps.set((slot - 1)*4 + 2,circles.get(r3));
bitmaps.set((slot - 1)*4 + 3,circles.get(color));
}
if(slot == 1) {
p1 = position;
centerX1 = x+position*(10 + width) + width/2;
centerY1 = y1 + width/2;
}
else if(slot == 2) {
p2 = position;
centerX2 = x+position*(10 + width) + width/2;
centerY2 = y2 + width/2;
}
}
public void onTouch(float X, float Y) {
int radius = (gameView.getWidth() / 4 - 10) / 2;
if(endGameCount == 0) {
if ((X >= centerX1 - radius) && (X <= centerX1 + radius) && (Y >= centerY1 - radius) && (Y <= centerY1 + radius)) {
GameView.score++;
touchedFirst = true;
centerX1 = centerY1 = -1;
if(p1 == (timerCount - 1) && timer != null && starSlot == 1) {
GameView.stars++;
starCollected = true;
timerCount = 0;
stopTimerTask(0);
}
} else if ((X >= centerX2 - radius) && (X <= centerX2 + radius) && (Y >= centerY2 - radius) && (Y <= centerY2 + radius)) {
GameView.score++;
touchedSecond = true;
centerX2 = centerY2 = -1;
if(p2 == (timerCount - 1) && timer != null && starSlot == 2) {
GameView.stars++;
starCollected = true;
timerCount = 0;
stopTimerTask(0);
}
} else {
endSlot = 0;
if ((Y >= centerY1 - radius) && (Y <= centerY1 + radius)) {
endSlot = 1;
if (X >= 10 && X <= 10 + 2 * radius) {
p1 = 0;
centerX1 = 10 + radius;
} else if (X >= 20 + 2 * radius && X <= 20 + 4 * radius) {
p1 = 1;
centerX1 = 20 + 3 * radius;
} else if (X >= 30 + 4 * radius && X <= 30 + 6 * radius) {
p1 = 2;
centerX1 = 30 + 5 * radius;
} else if (X >= 40 + 6 * radius && X <= 40 + 8 * radius) {
p1 = 3;
centerX1 = 40 + 2 * radius;
} else
endSlot = 0;
} else if ((Y >= centerY2 - radius) && (Y <= centerY2 + radius)) {
endSlot = 2;
if (X >= 10 && X <= 10 + 2 * radius) {
p2 = 0;
centerX2 = 10 + radius;
} else if (X >= 20 + 2 * radius && X <= 20 + 4 * radius) {
p2 = 1;
centerX2 = 20 + 3 * radius;
} else if (X >= 30 + 4 * radius && X <= 30 + 6 * radius) {
p2 = 2;
centerX2 = 30 + 5 * radius;
} else if (X >= 40 + 6 * radius && X <= 40 + 8 * radius) {
p2 = 3;
centerX2 = 40 + 2 * radius;
} else
endSlot = 0;
}
if (endSlot != 0) {
speedY1 = speedY2 = 0;
limit = endGameCount = 6;
if (endSlot == 1) {
endColor= bitmaps.get(p1).getPixel(width/2, width/2);
} else {
endColor = bitmaps.get(p2 + 4).getPixel(width/2, width/2);
}
}
}
if (GameView.score % 5 == 0 && GameView.score <= 110 && barCounter == 1) {
float ratio = (float)GameActivity.SCREEN_HEIGHT/1280;
speedY1 += ratio*0.5;
speedY2 += ratio*0.5;
}
if (GameView.score > 0 && GameView.score % 15 == 14) {
if(isOddScore)
stopY1 = true;
else
stopY2 = true;
}
if (GameView.score > 0 && GameView.score % 15 == 0 && barCounter == 1) {
if(isOddScore)
stopY2 = true;
else
stopY1 = true;
}
if (GameView.score % 15 == 1)
barCounter = 1;
}
}
public void draw(Canvas canvas) throws GameOverException {
GameView.isGameOver = false;
if(exception)
throw new GameOverException(color);
update();
for(int i=0;i<bitmaps.size();i++) {
if(i<4) {
Rect rect = new Rect(x+i*(10 + width),y1,(x+width)*(i+1),y1+width);
if(endGameCount == Math.ceil(limit) && endSlot == 1) {
if(i == p1) {
endRadiusCount += 1;
if (endRadiusCount > 23) {
star.recycle();
loopCount = loopCount%starInterval;
Cryptography.saveFile((loopCount + "").getBytes(), context, "interval");
endGameCount = 0;
exception = true;
throw new GameOverException(color);
}
rect = new Rect(x + i * (10 + width) - endRadiusCount*(int)Math.ceil(endRadiusSpeed), y1 - endRadiusCount*(int)Math.ceil(endRadiusSpeed), (x + width) * (i + 1) + endRadiusCount*(int)Math.ceil(endRadiusSpeed), y1 + width + endRadiusCount*(int)Math.ceil(endRadiusSpeed));
canvas.drawBitmap(bitmaps.get(i), null, rect, null);
}
}
// TOUCH ANIMATION : DIMINISH CIRCLE
else if(i==p1 && touchedFirst) {
rect = new Rect(x + i * (10 + width) + 3*count1 + ((int)speedY1-15), y1 + 3*count1 + ((int)speedY1-15), (x + width) * (i + 1) - 3*count1 - ((int)speedY1-15), y1 + width - 3*count1 - ((int)speedY1-15));
canvas.drawBitmap(bitmaps.get(i), null, rect, null);
count1++;
}
else if(endSlot != 2) {
canvas.drawBitmap(bitmaps.get(i), null, rect, null);
if(timerCount > 0 && starSlot == 1) {
int size = width * 30 / 50;
int difference = (width - size) / 2;
Rect starRect = new Rect(x + (timerCount - 1) * (10 + width) + difference, y1 + difference, (x + width) * (timerCount) - difference, y1 + width - difference);
canvas.drawBitmap(star, null, starRect, null);
}
}
}
if(i >= 4) {
Rect rect = new Rect(x + (i % 4) * (10 + width), y2, (x + width) * ((i % 4) + 1), y2 + width);
if(endGameCount == Math.ceil(limit) && endSlot == 2) {
if((i%4)==p2) {
endRadiusCount += 1;
if (endRadiusCount > 23) {
star.recycle();
loopCount = loopCount%starInterval;
Cryptography.saveFile((loopCount + "").getBytes(), context, "interval");
endGameCount = 0;
exception = true;
throw new GameOverException(color);
}
rect = new Rect(x + (i % 4) * (10 + width) - endRadiusCount*(int)Math.ceil(endRadiusSpeed), y2 - endRadiusCount*(int)Math.ceil(endRadiusSpeed), (x + width) * ((i % 4) + 1) + endRadiusCount*(int)Math.ceil(endRadiusSpeed), y2 + width + endRadiusCount*(int)Math.ceil(endRadiusSpeed));
canvas.drawBitmap(bitmaps.get(i), null, rect, null);
}
}
else if((i%4)==p2 && touchedSecond) {
rect = new Rect(x + (i % 4) * (10 + width) + 3*count2 + ((int)speedY1-15), y2 + 3*count2 + ((int)speedY1-15), (x + width) * ((i % 4) + 1) - 3*count2 - ((int)speedY1-15), y2 + width - 3*count2 - ((int)speedY1-15));
canvas.drawBitmap(bitmaps.get(i), null, rect, null);
count2++;
}
else if(endSlot != 1) {
canvas.drawBitmap(bitmaps.get(i), null, rect, null);
if(timerCount > 0 && starSlot == 2) {
int size = width * 30 / 50;
int difference = (width - size) / 2;
Rect starRect = new Rect(x + (timerCount - 1) * (10 + width) + difference, y2 + difference, (x + width) * (timerCount) - difference, y2 + width - difference);
canvas.drawBitmap(star, null, starRect, null);
}
}
}
}
Rect src = new Rect(circles.get(color).getWidth()/2 - 10,circles.get(color).getHeight()/2 - 10,circles.get(color).getWidth()/2 + 10,circles.get(color).getHeight()/2 + 10);
Rect dst;
Paint paint = new Paint();
paint.setColor(Color.WHITE);
paint.setTextAlign(Paint.Align.RIGHT);
paint.setTypeface(Typeface.SANS_SERIF);
paint.setTextSize(72 * ratio);
canvas.drawText(GameView.score + " ", GameActivity.SCREEN_WIDTH, width / 2, paint);
dst = new Rect(5,5, (int) (120 * ratio - 5), (int) (120 * ratio - 5));
canvas.drawBitmap(star,null,dst,null);
paint.setTextAlign(Paint.Align.LEFT);
canvas.drawText("" + GameView.stars, 120 * ratio, width/2, paint);
}
}
Don't override draw(). That's used to render the View, not the Surface, and you generally shouldn't override that method even if you're creating a custom View:
When implementing a view, implement onDraw(android.graphics.Canvas) instead of overriding this method.
SurfaceViews have two parts, the Surface and the View. The View part is handled like any other View, but is generally just a transparent "hole" in the layout. The Surface is a separate layer that, by default, sits behind the View layer. Whatever you draw on the Surface "shows through" the transparent hole.
By overriding draw() you're drawing on the View whenever the View UI is invalidated. You're also calling draw() from the render thread, so you're drawing on the Surface, but with default Z-ordering you can't see that because the View contents are fully opaque. You will reduce your impact on the UI thread by not drawing everything in two different layers.
Unless you're deliberately drawing on the View, it's best to avoid subclassing SurfaceView entirely, and just use it as a member.
Because your draw code is synchronized, the two draw passes will not execute concurrently. That means your View layer draw call will block waiting for the Surface layer rendering to complete. Canvas rendering on a Surface is not hardware-accelerated, so if you're touching a lot of pixels it can get slow, and the UI thread will have to wait for it to run. That wouldn't be so bad, but you're holding on to the mutex while you're sleeping, which means the only opportunity for the main UI thread to run comes during the brief instant when the loop wraps around. The thread scheduler does not guarantee fairness, so it's entirely possible to starve the main UI thread this way.
If you change #override draw() to myDraw() things should get better. You should probably move your sleep call out of the synchronized block just on general principles, or work to eliminate it entirely. You might also want to consider using a custom View instead of SurfaceView.
On an unrelated note, you should probably avoid doing this every update:
Random random = new Random();
for the reasons noted here.
Successfully solved the issue. Can't imagine that the solution would be this much simple as compared to the problem that I was considering that complex. Just reduced the frame rate from 120 to 90 and guess what, it worked like charm!
Due to a high frame rate, the SurfaceView was busy doing all the drawing and onTouchEvent() method had to starve

Step Counting Algorithm

I am Currently working on pedometer Application for intel device with LSM9DS0 sensor. My requirement is to develop a pedometer with the application code intel published in the Native Application Guide
This code is available in the section 6.1.4 of below shared pdf
http://download.intel.com/support/edison/sb/edison_nag_331192003.pdf
As a matter of fact I found some similar code but android version
public StepDetector() {
int h = 480; // TODO: remove this constant
mYOffset = h * 0.5f;
mScale[0] = - (h * 0.5f * (1.0f / (SensorManager.STANDARD_GRAVITY * 2)));
mScale[1] = - (h * 0.5f * (1.0f / (SensorManager.MAGNETIC_FIELD_EARTH_MAX)));
}
public void setSensitivity(float sensitivity) {
mLimit = sensitivity; // 1.97 2.96 4.44 6.66 10.00 15.00 22.50 33.75 50.62
}
public void addStepListener(StepListener sl) {
mStepListeners.add(sl);
}
//public void onSensorChanged(int sensor, float[] values) {
public void onSensorChanged(SensorEvent event) {
Sensor sensor = event.sensor;
synchronized (this) {
if (sensor.getType() == Sensor.TYPE_ORIENTATION) {
}
else {
int j = (sensor.getType() == Sensor.TYPE_ACCELEROMETER) ? 1 : 0;
if (j == 1) {
float vSum = 0;
for (int i=0 ; i<3 ; i++) {
final float v = mYOffset + event.values[i] * mScale[j];
vSum += v;
}
int k = 0;
float v = vSum / 3;
float direction = (v > mLastValues[k] ? 1 : (v < mLastValues[k] ? -1 : 0));
if (direction == - mLastDirections[k]) {
// Direction changed
int extType = (direction > 0 ? 0 : 1); // minumum or maximum?
mLastExtremes[extType][k] = mLastValues[k];
float diff = Math.abs(mLastExtremes[extType][k] - mLastExtremes[1 - extType][k]);
if (diff > mLimit) {
boolean isAlmostAsLargeAsPrevious = diff > (mLastDiff[k]*2/3);
boolean isPreviousLargeEnough = mLastDiff[k] > (diff/3);
boolean isNotContra = (mLastMatch != 1 - extType);
if (isAlmostAsLargeAsPrevious && isPreviousLargeEnough && isNotContra) {
Log.i(TAG, "step");
for (StepListener stepListener : mStepListeners) {
stepListener.onStep();
}
mLastMatch = extType;
}
else {
mLastMatch = -1;
}
}
mLastDiff[k] = diff;
}
mLastDirections[k] = direction;
mLastValues[k] = v;
}
}
}
}
Complete android source code available in Github
https://github.com/bagilevi/android-pedometer
My problem is that I am not able to make perfect design document using these codes. I need clarifications on
How does Scale values are calculated?
its look like a random constant from nowhere is used here
int h = 480; // TODO: remove this constant
mScale[0] = - (h * 0.5f * (1.0f / (SensorManager.STANDARD_GRAVITY * 2)));
mScale[1] = - (h * 0.5f * (1.0f / (SensorManager.MAGNETIC_FIELD_EARTH_MAX)));
How does these mLimit value calculated?
if (diff > mLimit)
Intel code saying
v = vSum / 2300;
ButAndroid code saying
v = vSum / 3;
The Calculation of vector Sum is similar in both the codes. Which equation actually followed here?
Please some one help me to get these things straight
I found out that the mechanism is just trial and run algorithm
These constant values may subject to change based on the environment, device, device packing, sensitivity of the accelerometer etc.

Prime Factorization in Android

I am developing a small Prime Number application for Android devices and am nearly done, however I would like some help with optimizing my factorization class.
I am still having one or two problems with some large numbers(Even Numbers) being factored within a reasonable amount of time. I won't be able to use the sieve of Eratosthenes for this particular project I think as I can only sieve up to 10 million without the app crashing on my physical device (Samsung Galaxy S4 Mini). So my work around algorithm is below. I am not sure if I can maybe make the Pollard Rho algorithm that I implemented any better.
Once I have established that the number being tested isn't prime or isn't a prime square, I quickly do trial division up to 10 000, after that if the number still isn't factored completely I use the Pollard Rho method to reduce it the rest of the way.
I want to be able to factor numbers in the range of 2 > 2^64.
This is an example of a number taking roughly 15 seconds 256332652145852
It's factorization is [2, 2, 1671053, 38348971].
Any help would be gladly appreciated.
try {
long num = Long.valueOf(input);
if(num == 1) {
return "1" + " = " + input;
} else if(num < 1) {
return "Cannot factor a number less than 1";
} else if(PrimeNumbers.isPrime(num) == true) {
return result = num + " is a Prime Number.";
} else if(isSquare(num) == true && PrimeNumbers.isPrime((long) Math.sqrt(num)) == true) {
return result = (int) Math.sqrt(num) + "<sup><small>" + 2 + "</small></sup>" + " = " + input;
} else {
factors(num, pFactors);
return result = exponentialForm(pFactors, num) + " = " + input;
}
} catch(NumberFormatException e) {
return result = "Unfortunately the number entered is too large";
}
}
public static void factors(long n, ArrayList<Long> arr) {
long number = trialDiv(n, arr);
if(number > 1) {
while(true) {
long divisor = pollard(number, 1);
if(PrimeNumbers.isPrime(divisor) == true) {
number /= divisor;
arr.add(divisor);
if(PrimeNumbers.isPrime(number) == true) {
arr.add(number);
break;
}
}
}
}
}
private static long trialDiv(long n, ArrayList<Long> arr) {
while(n % 2 == 0) {
n /= 2;
arr.add((long) 2);
}
for(long i = 3; i < 10000; i += 2) {
if(PrimeNumbers.isPrime(i) == true) {
while(n % i == 0) {
arr.add(i);
n /= i;
}
}
}
if(PrimeNumbers.isPrime(n) == true) {
arr.add(n);
return 1;
}
return n;
}
public static long pollard(long n, long c) {
long x = 2;
long y = 2;
long d = 1;
while (d == 1) {
x = g(x, n, c);
y = g(g(y, n, c), n, c);
d = gcd(Math.abs(y - x), n);
}
if (d == n) {
return pollard(n, c + 1);
} else {
return d;
}
}
static long g(long x, long n, long c) {
long g = (((x * x) + c) % n);
return g;
}
static long gcd(long a, long b) {
if (b == 0) {
return a;
} else {
return gcd(b, a % b);
}
}
Your pollard function is okay but not great. You are using Pollard's original algorithm, but it would be better to use Brent's variant. But that's probably not the source of your slow performance.
Your trial division function is slow. Checking each possible divisor for primality is very expensive, and not necessary. It doesn't matter if you divide by a composite; the division will always fail, but you don't waste the time checking primality. A better approach is wheel factorization.

Simulating multi-touch events (one finger linear swipe)

I am doing an edit to a driver file that uses Multi-Touch protocol.
My goal is to bind a swipe gesture from (x1,y1) to (x2,y2) that follows a line.
To do this i execute this function inside the key pressure detection function:
static void do_swipe(struct kp *kp, long xstart, long ystart, long xend, long yend,
int id) {
printk("SWIPE! X1 %d Y1 %d X2 %d Y2 %d ID %d \n",xstart,ystart,xend,yend,id);
int sx, sy;
int dx = abs(xend - xstart);
int dy = abs(yend - ystart);
if (xstart < xend)
sx = 1;
else
sx = -1;
if (ystart < yend)
sy = 1;
else
sy = -1;
int err = dx - dy;
long tempx = xstart;
long tempy = ystart;
while (1) {
key_report(kp, tempx, tempy, id);
//Touch is now detected with input_sync
input_sync(kp->input);
if(tempx == xend && tempy == yend) break;
int e2 = 2 * err;
if (e2 > (-1)*dy) {
err = err - dy;
tempx = tempx + sx;
} else if (e2 < dx) {
err = err + dx;
tempy = tempy + sy;
}
}
printk("END! X %d Y %d \n",tempx, tempy);
}
This function is an edited Bresenham's line algorhitm that instead of drawing a line calls key_report to simulate a touch at the given coordinates.
static void key_report(struct kp *kp, long x, long y, int id) {
if (x == 0 && y == 0) {
//printk("---------- zero point --------------\n");
;
} else {
input_report_key(kp->input, BTN_TOUCH, 1);
input_report_abs(kp->input, ABS_MT_TRACKING_ID, id);
input_report_abs(kp->input, ABS_MT_TOUCH_MAJOR, 20);
input_report_abs(kp->input, ABS_MT_WIDTH_MAJOR, 20);
input_report_abs(kp->input, ABS_MT_POSITION_X, x);
input_report_abs(kp->input, ABS_MT_POSITION_Y, y);
input_mt_sync(kp->input);
}
release = 1;
}
Where kp-> input is so defined
struct input_dev *input;
Edit: I updated the code and I'm also attaching the generic code of a key pressure, because I'd like the driver to perform a swipe only once for each key pressure, to avoid swipe looping.
static void kp_work(struct kp *kp) {
int i, code, value;
kp_search_key(kp);
if (key_param[0] == 3) {
if (kp->key_valid[4] == 1) {
value = kp->key_value[4];
kp->flagchan4 = 0;
if (value >= 0 && value <= (9 + 40)) {
if (key_param[99] == 1 ) {
do_swipe(kp, key_param[25], key_param[26], key_param[97],
key_param[98], 12);
} else
key_report(kp, key_param[25], key_param[26], 12);
} else if (value >= 392 - 40 && value <= (392 + 40)) {
if (key_param[102] == 1) {
do_swipe(kp, key_param[23], key_param[24], key_param[100],
key_param[101], 12);
} else
key_report(kp, key_param[23], key_param[24], 12);
}
kp->flagchan4 = 0;
} else {
kp->flagchan4 = 1;
}
}
input_sync(kp->input);
}
Maybe i could set a check on kp->flagchan4...
Edit: Setting a check on flagchan4 did the trick.

Android motion detection

I want to detect motion with Android sensors. For example I hold only bottom of phone and move top of phone to up. I think I need sampling algorithms. I can write a simple application to record data of sensors . For comparing real time data and recorded data ,Is there any libary ? I have suspicious about performace problems if I would make it. Is there a different path for detetion movements ?
These links will help you to start..
http://developer.android.com/guide/topics/sensors/sensors_motion.html
http://code.google.com/p/android-motion-detection/
http://www.helloandroid.com/tutorials/android-image-processing-detecting-motions
http://code.google.com/p/android-motion-detection/ is a good example.
I modified the isDifferent method in RgbMotionDetection class to detect the motion in the center part (25%) of the camera view.
protected static boolean isDifferent(int[] first, int width, int height) {
if (first==null) throw new NullPointerException();
if (mPrevious==null) return false;
if (first.length != mPrevious.length) return true;
if (mPreviousWidth != width || mPreviousHeight != height) return true;
int totDifferentPixels = 0;
int size = height * width;
int startHeight = height / 4;
int endHeight = 3 * (height / 4);
int startWidth = width / 4;
int endWidth = 3 * (width / 4);
int offSet = width / 4;
Log.d("params", "start height " + startHeight + "end height " + endHeight + "start width " + startWidth + "end width " + endWidth);
Boolean offSetApplied;
for (int i = startHeight, ij=0; i < endHeight; i++) {
{
offSetApplied = false;
for (int j = startWidth; j < endWidth; j++, ij++) {
if (!offSetApplied){
offSetApplied = true;
ij = startHeight * width + offSet;
}
int pix = (0xff & ((int)first[ij]));
int otherPix = (0xff & ((int)mPrevious[ij]));
//Catch any pixels that are out of range
if (pix < 0) pix = 0;
if (pix > 255) pix = 255;
if (otherPix < 0) otherPix = 0;
if (otherPix > 255) otherPix = 255;
if (Math.abs(pix - otherPix) >= mPixelThreshold) {
totDifferentPixels++;
//Paint different pixel red
//first[ij] = Color.RED;
}
}
}
}
if (totDifferentPixels <= 0) totDifferentPixels = 1;
//boolean different = totDifferentPixels > mThreshold;
int percent = 100/(size/totDifferentPixels);
//float percent = (float) totDifferentPixels / (float) size;
boolean different = percent > SENSITIVITY;
String output = "Number of different pixels: " + totDifferentPixels + "> " + percent + "%";
if (different) {
Log.e(TAG, output);
} else {
Log.d(TAG, output);
}
return different;
}

Categories

Resources