UiAutomator Detect Tablet vs Phone - android-uiautomator

Is there a way using Android's uiautomator to detect whether the device being tested upon is a phone or a tablet?
Thanks in advance.

I have figured it out. You can get the width and height of the device using the function calls getUiDevice().getDisplayWidth() and getUiDevice().getDisplayHeight(). You can use ADB to get the pixel density: getprop ro.sf.lcd_density. Then using the formula px = dp * (dpi / 160) you can generate the formula dp = px / (dpi / 160). Lastly, screen sizes according to Android are specified as follows: small - 426dp x 320dp, normal - 470dp x 320dp, large - 640dp x 480dp, and xlarge - 960dp x 720dp where large and xlarge screen sizes are tablets :). Enjoy!
public boolean isTablet() throws Exception {
double widthpx = getUiDevice().getDisplayWidth();
double heightpx = getUiDevice().getDisplayHeight();
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("getprop ro.sf.lcd_density");
InputStream inputStream = process.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
double dpi = Double.parseDouble(bufferedReader.readLine());
double widthdp = widthpx / (dpi / 160);
double heightdp = heightpx / (dpi / 160);
return (widthdp >= 640 && heightdp >= 480);
}

Related

How to bounce Kinematic Body 3d (godot) whenever it collides with a gridmap, static body or another kinematic body?

I have a kinematic body which moves with a virtual joystick. What I want is that my kinematic body should bounce off (like the ball in air hockey does when it hits the walls or the striker). I have my gridmap in a group called as "walls" . Here is my code for the player :
extends KinematicBody
var acceleration = 10
var topspeed = 40
onready var joystick = get_parent().get_node("Joystick/Joystick_button")
var vel = Vector3()
var speed = 10
var target_dir = Vector2(0, 0)
var a
var b
func _ready():
pass
func _physics_process(delta):
#var target_dir = Vector2(0, 0)
target_dir = -joystick.get_value()
if joystick.ongoing_drag != -1:
a = -joystick.get_value()
if joystick.ongoing_drag == -1 and joystick.i != 0:
target_dir = a
vel.x = lerp(vel.x, target_dir.x * speed , acceleration * delta)
vel.z = lerp(vel.z, target_dir.y * speed , acceleration * delta)
#vel = move_and_slide(vel, Vector3(0, 1, 0))
var collision = move_and_collide(vel * delta)
if collision:
vel = vel.bounce(collision.normal)
Edit : The vel.bounce() used at last does not satisfy the requirements as it returns a very low bounce but I want it to bounce zig zag between the walls until I change the direction with my joystick. Or putting in other words , I want the movement of my Kinematic body to be exactly like the ball's movement in Flaming core Game (click the link to see its gameplay) like how the ball bounces after colliding with the walls or the enemy.
Try chagne these line:
vel.x = lerp(vel.x, target_dir.x * speed , acceleration * delta)
vel.z = lerp(vel.z, target_dir.y * speed , acceleration * delta)
to these:
vel.x += target_dir.x * acceleration * delta
vel.x = min(vel.x, topspeed)
vel.z += target_dir.y * acceleration * delta
vel.z = min(vel.z, topspeed)
And adjust the acceleration if needed.

Itext 7 - Vertical watermark using text

I have been trying to add a watermark in a pdf using Itext 7. The watermark needs to be at the left side of each page and should be vertical. Something like shown in the following image:
Instead of being in centre, it should be at the left side of the page.
I tried the following code, but any angle I try it does not work for me -
File mergedDoc = new File(mergedFileName + ".pdf");
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(mergedDoc));
Document document = new Document(pdfDoc);
PdfFont font = PdfFontFactory.createFont(FontProgramFactory.createFont(FontConstants.HELVETICA));
Paragraph verticalWatermark = new Paragraph("My vertical watermark").setFont(font).setFontSize(30);
for (int i = 1 + pdfDoc.getNumberOfPages(); i <= k; i++) {
PdfPage page = pdfDoc.getPage(i);
page.setIgnorePageRotationForContent(false);
over = new PdfCanvas(pdfDoc.getPage(i));
over.saveState();
over.setExtGState(gs1);
document.showTextAligned(verticalWatermark, 30f, 25f, i, TextAlignment.LEFT, VerticalAlignment.BOTTOM, 90);
over.restoreState();
pdfDoc.close();
document.close();
}
Any help would be appreciated.
Your code is wrong in many places.
You combine low-level operations such saveState()/restoreState() on a PdfCanvas in combination with the high-level Document class' showTextAligned() method.
You start counting at 1 + pdfDoc.getNumberOfPages() which is weird. Your code sample is not a SSCCE. No one but you can run it because no one but you knows what variables such as k and gs1 are about. Not providing a SSCCE is often interpreted as "I am asking a question, but I'm not interested in getting an answer."
You are defining a value in degrees where a value in radians is expected, see the API docs: showTextAligned(Paragraph p, float x, float y, int pageNumber, TextAlignment textAlign, VerticalAlignment vertAlign, float radAngle)
I have taken the iText 7 Jump-Start Tutorial, and I have added a vertical watermark to the left of the page:
This was the code I used:
PdfReader reader = new PdfReader(src);
PdfWriter writer = new PdfWriter(dest);
PdfDocument pdf = new PdfDocument(reader, writer);
Document document = new Document(pdf);
Paragraph p = new Paragraph("My vertical watermark");
for (int i = 1; i <= pdf.getNumberOfPages(); i++) {
document.showTextAligned(
p, 36, 72, i, TextAlignment.LEFT, VerticalAlignment.BOTTOM,
(float)Math.PI / 2);
}
document.close();
As you can see: there's no need for a PdfCanvas and it's Math.PI / 2 radians instead of 90 degrees.

How can i get device tilt in xamarin forms?

I´d like to get the tilt of the device, so i can use this to mesure the tilt os some surface, laying down the device over the surface.
Right now i am using Device Motion Plugin for xamarin forms from here https://github.com/rdelrosario/xamarin-plugins
and the code below:
CrossDeviceMotion.Current.Start(MotionSensorType.Accelerometer);
CrossDeviceMotion.Current.SensorValueChanged += (s, a) =>
{
switch (a.SensorType)
{
case MotionSensorType.Accelerometer:
{
Debug.WriteLine("A: {0},{1},{2}", ((MotionVector)a.Value).X, ((MotionVector)a.Value).Y,
((MotionVector)a.Value).Z);
Exposicao.Inclinacao = ((MotionVector)a.Value).Z;
break;
}
case MotionSensorType.Compass:
{
// Debug.WriteLine("H: {0}", a.Value);
Exposicao.Bussola = (double)a.Value.Value;
break;
}
}
};
The compass part is ok, the accelerometer part is working but there are some but´s.
If i am not wrong, i get the tilt in Z axis, so z.Value.Value.
This value is diferent for android and ios, lets focus in android.
z values are from 10 when device is laying down on flat surface, to 0 if device is stand up, lets focus only in just one quadrant.
I am doing something wrong to achieve what i explained?
How can i convert those values to a Angle between 0 and 90? It seems not linear, so the 5 does not seem 45 degrees.
Thanks
I'd probably roll out my own platform implementation for the feature you're looking for. The DeviceMotion library looks a bit simple for your purposes, as can be seen from the answer below. I'm pretty sure you can use it as a good starting point but it needs to be extended a little.
Android
On Android, you should use the Rotation Vector Sensor which uses a Kalman filter (with accelerometer, magnetometer and gyroscope) to get accurate measurements of the device's rotation:
The rotation vector represents the orientation of the device as a combination of an angle and an axis, in which the device has rotated through an angle θ around an axis (x, y, or z).
Image from the official Android documentation
iOS:
For iOS, you have to do a bit more work yourself. The key is to make use of CMAttitude, which describes the attitude of the device relative to an initial attitude. I found a snippet I've saved to my collection from an unknown source (can't credit the original author) here:
public void CalculateLeanAngle ()
{
motionManager = new CMMotionManager ();
motionManager.DeviceMotionUpdateInterval = 0.02;
if (motionManager.DeviceMotionAvailable) {
motionManager.StartDeviceMotionUpdates(CMAttitudeReferenceFrame.XArbitraryZVertical, NSOperationQueue.CurrentQueue, (data, error) => {
CMQuaternion quat = motionManager.DeviceMotion.Attitude.Quaternion;
double x = quat.x;
double y = quat.y;
double w = quat.w;
double z = quat.z;
double degrees = 0.0;
//Roll
double roll = Math.Atan2 (2 * y * w - 2 * x * z, 1 - 2 * y * y - 2 * z * z);
degrees = Math.Round (-applyKalmanFiltering (roll) * 180.0 / Constants.M_PI);
});
}
public double applyKalmanFiltering (double yaw)
{
if (motionLastYaw == 0)
motionLastYaw = yaw;
float q = 0.1f; // process noise
float r = 0.1f; // sensor noise
float p = 0.1f; // estimated error
float k = 0.5f; // kalman filter gain
double x = motionLastYaw;
p = p + q;
k = p / (p + r);
x = x + k * (yaw - x);
p = (1 - k) * p;
motionLastYaw = x;
return motionLastYaw;
}
Image from the official Xamarin documentation
I'll try to look for the original source when I have more time but I'm pretty sure this will work out of the box for your purposes.

Fast algorithm for image distortion

I am working on a tool which distorts images, the purpose of the distortion is to project images to a sphere screen. The desired output is as the following image.
The code I use is as follow - for every Point(x, y) in the destination area, I calculate the corresponding pixel (sourceX, sourceY) in the original image to retrieve from.
But this approach is awkwardly slow, in my test, processing the sunset.jpg (800*600) requires more than 1500ms, if I remove the Mathematical/Trigonometrical calculations, calling cvGet2D and cvSet2D alone require more than 1200ms.
Is there a better way to do this? I am using Emgu CV (a .NET wrapper library for OpenCV) but examples in other language is also OK.
private static void DistortSingleImage()
{
System.Diagnostics.Stopwatch stopWatch = System.Diagnostics.Stopwatch.StartNew();
using (Image<Bgr, Byte> origImage = new Image<Bgr, Byte>("sunset.jpg"))
{
int frameH = origImage.Height;
using (Image<Bgr, Byte> distortImage = new Image<Bgr, Byte>(2 * frameH, 2 * frameH))
{
MCvScalar pixel;
for (int x = 0; x < 2 * frameH; x++)
{
for (int y = 0; y < 2 * frameH; y++)
{
if (x == frameH && y == frameH) continue;
int x1 = x - frameH;
int y1 = y - frameH;
if (x1 * x1 + y1 * y1 < frameH * frameH)
{
double radius = Math.Sqrt(x1 * x1 + y1 * y1);
double theta = Math.Acos(x1 / radius);
int sourceX = (int)(theta * (origImage.Width - 1) / Math.PI);
int sourceY = (int)radius;
pixel = CvInvoke.cvGet2D(origImage.Ptr, sourceY, sourceX);
CvInvoke.cvSet2D(distortImage, y, x, pixel);
}
}
}
distortImage.Save("Distort.jpg");
}
Console.WriteLine(stopWatch.ElapsedMilliseconds);
}
}
From my personal experience, I was doing some stereoscopic vision stuff, the best way to talk to openCV is through own wrapper, you could put your method in c++ and call it from c#, that would give you 1 call to native, faster code, and because under the hood Emgu's keeping OpenCV data, it's also possible to create an image with emgu, process it natively and enjoy processed image in c# again.
The get/set methods looks like Gdi's GetPixel / SetPixel ones, and, according to documentation they are "slow but safe way".
For staying with Emgu only, documentation tells that if you want to iterate over pixels, you should access .Data property:
The safe (slow) way
Suppose you are working on an Image. You can obtain the pixel on the y-th row and x-th column by calling
Bgr color = img[y, x];
Setting the pixel on the y-th row and x-th column is also simple
img[y,x] = color;
The fast way
The Image pixels values are stored in the Data property, a 3D array. Use this property if you need to iterate through the pixel values of the image.

math/algorithm Fit image to screen retain aspect ratio

I need help with math / algorithm to take an image of known size and fit to one of two screen dimensions:
720 x 480 or 1280 x 1024.
The image dimensions are coming from an XML file, however those dimensions are the web dimensions, I also get a selection of images from the XML that may be of higher and lower resolution than the web dimensions.
What I want is to use the aspect ration of the web dimensions to display the higher resolution image, if available, on an HD (1280x720) screen, or, if the user is on an SD screen (720x480) display the image on that screen.
Other things that would be useful for this, but lower priority, would be, if I know the resolution of the image is smaller in both dimensions than an SD screen (in this case, all I know is the web dimension, and the horizontal dimension of the image file), to display it as actual size on that screen.
Generic as can be:
Image data: (wi, hi) and define ri = wi / hi
Screen resolution: (ws, hs) and define rs = ws / hs
Scaled image dimensions:
rs > ri ? (wi * hs/hi, hs) : (ws, hi * ws/wi)
So for example:
20
|------------------|
10
|---------|
-------------------- --- ---
| | | | 7 |
| | | | | 10
|---------- | --- |
| | |
-------------------- ---
ws = 20
hs = 10
wi = 10
hi = 7
20/10 > 10/7 ==> (wi * hs/hi, hs) = (10 * 10/7, 10) = (100/7, 10) ~ (14.3, 10)
Which as you can see clearly scales to the screen size, because the height is that of the screen but clearly keeps aspect ratio since 14.3/10 ~ 10/7
UPDATE
Center the image as follows:
call (wnew, hnew) the new dimensions.
top = (hs - hnew)/2
left = (ws - wnew)/2
I understand the accepted answer and it works, but I've always found the following method to be simpler and succinct for "best fit":
// prep
let maxWidth = 190,
maxHeight = 150;
let imgWidth = img.width,
imgHeight = img.height;
// calc
let widthRatio = maxWidth / imgWidth,
heightRatio = maxHeight / imgHeight;
let bestRatio = Math.min(widthRatio, heightRatio);
// output
let newWidth = imgWidth * bestRatio,
newHeight = imgHeight * bestRatio;
... which of course can be distilled down to:
const maxWidth = 190, maxHeight = 150;
const bestRatio = Math.min(maxWidth / img.width, maxHeight / img.height);
img.width *= bestRatio;
img.height *= bestRatio;
Here it is in straightforward C.
You want to scale both coordinates by the returned scale factor.
/* For a rectangle inside a screen, get the scale factor that permits the rectangle
to be scaled without stretching or squashing. */
float
aspect_correct_scale_for_rect(const float screen[2], const float rect[2])
{
float screenAspect = screen[0] / screen[1];
float rectAspect = rect[0] / rect[1];
float scaleFactor;
if (screenAspect > rectAspect)
scaleFactor = screen[1] / rect[1];
else
scaleFactor = screen[0] / rect[0];
return scaleFactor;
}
Aspect ratio correction with letterboxing or fit-to-screen
I wrote up a method recently to handle this exact problem in iOS. I'm using the Eigen matrix library to do scaling, but the the principle (scaling factor) is the same without matrices.
Eigen::Matrix4x4f aspectRatioCorrection(bool fillScreen, const Eigen::Vector2f &screenSize, const Eigen::Vector2f &imageSize)
{
Eigen::Matrix4x4f scalingMatrix(Eigen::Matrix4x4f::Identity());
float screenWidth = screenSize.x();
float screenHeight = screenSize.y();
float screenAspectRatio = screenWidth / screenHeight;
float imageWidth = imageSize.x();
float imageHeight = imageSize.y();
float imageAspectRatio = imageWidth / imageHeight;
float scalingFactor;
if (fillScreen) {
if (screenAspectRatio > imageAspectRatio) {
scalingFactor = screenWidth / imageWidth;
} else {
scalingFactor = screenHeight / imageHeight;
}
} else {
if (screenAspectRatio > imageAspectRatio) {
scalingFactor = screenHeight / imageHeight;
} else {
scalingFactor = screenWidth / imageWidth;
}
}
scalingMatrix(0, 0) = scalingFactor;
scalingMatrix(1, 1) = scalingFactor;
return scalingMatrix;
}

Resources