How can I restrict my GoogleTV app to display in a specific resolution: i.e. 720P, 1080p, etc? For some reason my app is stuck at displaying at a resolution around 960x540 even though my GoogleTV and monitor can handle 1080p.
I'm not sure if it's just my GoogleTV that is displaying only in 960x540 or if other GoogleTVs are also seeing the same thing. In any case, I want to make sure that my app can only be viewed in the resolutions: 960x540 or 1280x720
Each display on a Google TV is different. (With the exception of built in TV's like the LG) There is a step when the Google TV is just turned on where you establish the resolution of the TV.
Most current Google TV (ARM based) are 1080p. Scaling down to 720 is accomplished by your TV.
All that said, 960x540 are android Device Pixels for either 720p or 1080p.
So, to summarize, you can't / shouldn't do what your asking.
I figured it out. I had to set the initial scale of the webview, and that allows me to view the WebView in 720p even though the screen resolution is 1080p.
This is the code I used:
boolean _bReloaded = false;
boolean _bLoaded = false;
int _nWebScale = 100;
DisplayMetrics displaymetrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int nScreenHeight = displaymetrics.heightPixels;
if(nScreenHeight >= 1000){
_nWebScale = (int) Math.round((nScreenHeight/720.0) * 100.0);
_bReloaded = false;
mWebView.setVisibility(View.INVISIBLE);
}
mWebView.setInitialScale(_nWebScale);
But I wasn't done there.
At this point, the webView is displayed in the proper resolution; however, there is a noticeable resizing of the webview window when the webView loads. This is why in the above code I hide the webview. Another problem is that in my particular case, my HTML wasn't listening to a window resize event and so it didn't readjust its UI after the webview was noticeably seen changing size. To fix this I could change my HTML and have it react to a JavaScript window resize event, or I could do what I ultimately went with - reloading the webview after it loads with the incorrect sized UI. With this solution I didn't have to react to a window resize event:
mWebView.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, int progress) {
if (progress == 100) {
if(_nWebScale != 100 && (mWebView.getVisibility() != View.VISIBLE) && !_bReloaded){
_bReloaded = true;
mWebView.reload();
} else {
_bLoaded = true;
displayLoadingSpinner(false);
mWebView.setVisibility(View.VISIBLE);
}
} else if (mProgressBar.getVisibility() != View.VISIBLE) {
displayLoadingSpinner(true);
_bLoaded = false;
}
}
});
Another piece of info that isn't directly related to the original question, but may be useful is the following. Within my code, I had to resize and reposition a VideoView based on parameters that were sent from the webview. But because the webview may be in a different resolution than the actual display resolution, I had to adjust the parameters to make them in terms of the screen resolution.
For example:
//this parameter is equal to the width of the webview screen: 720
nHeightFromWebView;
//This is the x position of where the VideoView should be placed.
nXFromWebView;
float nScale = (float)_nWebScale/100;
int nAdjustedHeight = (int) Math.round(((float)nHeightFromWebView * nScale));
//The adjusted height computes to 1080 - the actual resolution of the screen
int nNewX = (int)Math.round((float)nXFromWebView * nScale);
Related
My Android application embeds a webview, the webview is written in Angular10. The webview displays a list of items using infinite scroll. A chunk of the data is displayed and when IntersectionObserver is triggered a new chunk of data is displayed.
It works fine on some of my devices (for example Google Pixel 4, Samsung S10e) but on some device (for example Sony Xperia XZ, Samsung TabS2) only the first chunk is displayed, the IntersectionObserver is not triggered and other chunks are not displayed.
The Android application computes the available space for the webview, if I slightly change the available space (for example by substracting 5 pixels) then the IntersectionObserver is triggered. This does not work for all devices.
The place available on the screen for the webview is computed as follow:
private fun computeWebViewHeight() {
val displaymetrics = DisplayMetrics()
activity.windowManager.defaultDisplay.getMetrics(displaymetrics)
val deviceHeight = displaymetrics.heightPixels
webView.viewTreeObserver.addOnGlobalLayoutListener(object : OnGlobalLayoutListener {
override fun onGlobalLayout() {
webView.viewTreeObserver.removeOnGlobalLayoutListener(this)
val actionBar = activity.findViewById<RelativeLayout>(R.id.action_bar)
webView.layoutParams = LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
deviceHeight - actionBar.height - statusBarHeight // - 5
)
}
})
}
I first thought that the available space computed was erroneous but if I compare with the effective height of the webview then both measurement matches, that is the height of the webview corresponds to the available space.
Have you already experienced such behaviour ? Do you have any idea where the problem comes from ?
As I understand that currently UHD video content is streamed on 4k TV mostly using HEVC codec.
I want to understand how can apps which have UHD image content can display their image content in native 4K?
What I am exactly looking for is rendering 4k(3840*2060) jpeg images. My display supports 4k rendering and the SOC can even output 4k. I am looking for modifications in framework, so that all apps which have 4k images can render them on my device without downscaling.
Actually I am trying to come up with API set which others can use. But my main confusion is : for jpeg image i create a 4k surface, but their are other surfaces as well (buttons etc). They are rendered by surface flinger which renders at 1280*720.
Now what is the best way to compose my 4k surface with these other surfaces? Where should I upscale these surfaces and where to compose all of them?
An important thing to keep clear is what kind of development you have in mind. If you simply wish to put a video stream showing inside your App, you should take the user interface for the main activity that will simply consist of an instance of the VideoView class. The VideoView class has a wide range of methods that may be called in order to manage the playback of video.
Configure the VideoView with the path of the video to be played and then start the playback. Then select the VideoPlayerActivity.java file and modify the OnCreate() method as outlined in the following listing:
package com.example.videoplayer;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.VideoView;
public class VideoPlayerActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_player);
final VideoView videoView =
(VideoView) findViewById(R.id.videoView1);
videoView.setVideoPath(
"http://www.ebookfrenzy.com/android_book/movie.mp4");
videoView.start();
}
.
.
.
}
Essentially what you have is the Android SDK for the App user interface, which means that you can use different choices to actually render the video streaming underneath the UI layer.
Migrating your already existing App from a tablet or mobile to a smart TV is also something that can be achieve quite smoothly. Some few things will have to be adjusted - e.g. touch screen usually for smart TV may not be an option.
Instead you should consider onkeyDown as a more reliable method to input interaction for your App:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_MEDIA_PLAY:{
if (!mPlaying) {
startSlideShow();
}
mPlaying = true;
break;
}
case KeyEvent.KEYCODE_MEDIA_PAUSE:{
mPlaying = false;
showStatusToast(R.string.slideshow_paused);
}
}
return super.onKeyDown(keyCode, event);
}
As part of Android Smart Google TV API, you can also make necessary adjustment for larger screen resolutions:
// Get the source image's dimensions
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; // this does not download the actual image, just downloads headers.
BitmapFactory.decodeFile(IMAGE_FILE_URL, options);
int srcWidth = options.outWidth; // actual width of the image.
int srcHeight = options.outHeight; // actual height of the image.
// Only scale if the source is big enough. This code is just trying to fit a image into a certain width.
if(desiredWidth > srcWidth)
desiredWidth = srcWidth;
// Calculate the correct inSampleSize/scale value. This helps reduce memory use. It should be a power of 2.
int inSampleSize = 1;
while(srcWidth / 2 > desiredWidth){
srcWidth /= 2;
srcHeight /= 2;
inSampleSize *= 2;
}
float desiredScale = (float) desiredWidth / srcWidth;
// Decode with inSampleSize
options.inJustDecodeBounds = false; // now download the actual image.
options.inDither = false;
options.inSampleSize = inSampleSize;
options.inScaled = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888; // ensures the image stays as a 32-bit ARGB_8888 image.
// This preserves image quality.
Bitmap sampledSrcBitmap = BitmapFactory.decodeFile(IMAGE_FILE_URL, options);
// Resize
Matrix matrix = new Matrix();
matrix.postScale(desiredScale, desiredScale);
Bitmap scaledBitmap = Bitmap.createBitmap(sampledSrcBitmap, 0, 0,
sampledSrcBitmap.getWidth(), sampledSrcBitmap.getHeight(), matrix, true);
sampledSrcBitmap = null;
// Save
FileOutputStream out = new FileOutputStream(LOCAL_PATH_TO_STORE_IMAGE);
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
scaledBitmap = null;
You can also easily convert your LCD TV into a smart TV and start playing and testing how your App for google TV would behave. For that you only need to put your hands in the adaptor kit.
In fact, Lenovo is releasing a 28-inch 4K monitor (the ThinkVision 28) that also runs Android, allowing you to run all of the usual media streaming apps, and Kogan is doing the same.
Hacking a little bit further in playing with gadgets, you can even huck up your mobile with MHL HDMI on a TV or use it as a computer.
So, Android working with MHL 3.0 does 4K video output is a reality that good developers can already make their Apps with the necessary resolution and input adjustment accordingly to the device in use.
If your main concern is to put performance and optimize the video streaming, you may consider following options:
NDK: You decide to take some library or implement your own program that actually is made in C++ to optimize the video streaming.
RenderScript: it uses C99 syntax with new APIs that are ultimately compiled to native code. While this syntax is well known, there's a learning curve to using this system because the APIs are not.
OpenCL: is meant for graphics acceleration and provides many tools for 3D rendering and video stream high performance.
In fact the code in OpenCL resembles C/C++:
for (int yy=-filterWidth; yy<=filterWidth; ++yy)
{
for (int xx=-filterWidth; xx<=filterWidth; ++xx)
{
int thisIndex = (y + yy) * width + (x + xx);
float4 currentPixel = oneover255 *convert_float4(srcBuffer[thisIndex]);
float domainDistance = fast_distance((float)(xx), (float)(yy));
float domainWeight = exp(-0.5f * pow((domainDistance/sigmaDomain),2.0f));
float rangeDistance = fast_distance(currentPixel.xyz, centerPixel.xyz);
float rangeWeight = exp(-0.5f * pow((rangeDistance/sigmaRange),2.0f));
float totalWeight = domainWeight * rangeWeight ;
normalizeCoeff += totalWeight;
sum4 += totalWeight * currentPixel;
}
}
In terms of ARM microprocessors capabilities, it is worth to mention Sigma Designs SMP8756 ARM for Android Set-top-boxes, meant to address full High Efficiency Video Coding (HEVC) capabilities.
Bilinear Filtering
To resize your image/video, what you need is to apply bilinear filtering. Bilinear Interpolation is the process of using each of the intermediate fields in an interlaced video frame to generate a full size target image. Either all the odd or all the even lines on the field are used. Interpolations are then performed between the lines and between adjoining pixels to generate an entire non-interlaced frame for the progressive scan output.
To implement have your image adjusted properly for the sizes you need, there are plenty of good algorithms that can be used for that purpose, such as some of the OpenCL features for image scaling, and likewise for native C++ other options are also available.
I have worked so hard on an app that displays perfectly on my Galaxy Note 3. However, it does not display right on iPhone and also one other Droid I tested on. My issue is with addChild() and then resizing it to fit the screen. For some reason when I add the Background (addBG(); The screen size works but if I load addChild to the BG, this works great on my Note 3 but not on the iPhone or another android device.
My issue is with the screenX, screenY var I created. They seem to be different for devices. Or it is a "rendering order issue" I am not sure. Would be so greatful for the help to fix this issue so it looks great on each phone. I have read some tuts on this subject but they are confusing. I think my code is close, I hope, and maybe it just needs a tweak. !
Here is a shot of the about screen on an IPhone. See the white does not fit the whole screen.
and Here is a shot from my Droid Note 3.
Declared Vars in a package:
This is not my full code, of course but only that which I believe is relevant.
public var screenX:int;
public var screenY:int;
public function Main()
{
if (stage)
{
setStage();
addBG();
}
}
public function setStage()
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
if (flash.system.Capabilities.screenResolutionX > stage.stageWidth)
{
screenX = stage.stageWidth;
screenY = stage.stageHeight;
}
else
{
screenX = flash.system.Capabilities.screenResolutionX;
screenY = flash.system.Capabilities.screenResolutionY;
}
}
This works: addBG();
public function addBG()
{
theBG = new BG();
addChild(theBG);
theBG.width = screenX;
theBG.height = screenY;
}
This does not: addAbout();
public function addAbout()
{
About = new viewAbout();
About.width = screenX;
About.height = screenY;
theBG.addChild(About);
TweenMax.fromTo(About,1, {alpha:0}, {alpha:1, ease:Expo.easeOut} );
}
UPDATE: And yet another more complex load is also called from a button and having the same issue. I hope you see the logic of what I am trying to do. First set the BG to the device then load and resize content to fit proportionally into the BG I loaded. The reason being, the BG will be distorted to different proportions and that's ok, but the content can not. So here is the example that loads content into the BG and then content into that container.
public function addRosaryApp()
{
Rosary = new viewRosaryApp();
Rosary.width = screenX;
Rosary.height = screenY;
theBG.addChild(Rosary);
TweenMax.fromTo(Rosary,1, {alpha:0}, {alpha:1, ease:Expo.easeOut} );
contentRosary = new contentRosaryApp();
theBG.addChild(contentRosary);
contentRosary.width = screenX;
contentRosary.scaleY = contentRosary.scaleX;
contentRosary.x = screenX/2 - contentRosary.width/2;
contentRosary.y = menuBanner.height;
}
Have you tried adding the child to stage first, and then setting the size? That's the only difference I can see between addBG and addAbout
About = new viewAbout();
theBG.addChild(About); // do this first
About.width = screenX; // then set width
About.height = screenY; // and height
I think your problem may have to do with either of several things.
My findings so far from my own devices (an Ipad Air, an iphone 4S, an LG G2 and an Acer Iconia A500) is that the only device size that's being reported correctly at all times is the stage.fullScreenWidth and the stage.fullScreenHeight
1st, Android reports Capabilities.screenResolutionX as the LONG side of your Android device.
IOS devices however report the SHORT side of your device to Capabilities.screenResolutionX.
2nd, stage.stageWidth and stage.stageHeight seem to report the wrong size on both Android and IOS.
And in fact if you check these before and after setting stage.scaleMode and stage.align then the values will differ completly (although Android will show it almost correctly).
My suggestion is that you set a base size (width and height) for your app and then compare it with the actual stage.fullScreenWidth and stage.fullScreenHeight reported by the device. That way you can get some nice scaleratios to use to scale your displayobjects. That's what I'm currently on my apps and it scales just fine :-)
I would like to get the size of touch screen. For the reason, when I tested this code in the emulator the minimum values of X is 0(Y too, when pressing the 'corner' of the screen). But when I tested the code on a real devices, X shows displays 2000. So I want to read the absolute values of the screen. I think I need to get the 'minimun, maximum' values of screen. how can I read this value ?
main()
{
int fileno = open("/dev/input/event0",O_RDONLY),num_bytes;
char ev[50];
num_bytes=read(fileno,&ev,sizeof(struct input_event));
if(num_bytes<=0)
{
perror("Cannot access");
exit(FAILURE);
}
printf("%d\n",fileno);
printf("\nNumber of bytes read is %d\n string is%s\n",num_bytes,ev);
close(fileno);
}
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
This will tell you the real size of your screen in pixels, but you'll still need to account for density as well as action bar or title bar in figuring your actuall workable area.
Is there any way to either remove the recent apps button in android 3.0 (I have a xoom) or clear the list? Is their any way to find device is, Mobile or Tab using java code.
Bcoz it breaks my policy app and allows people to switch device administrator if default Settings in that list. i am displaying my own launcher with out settings application.
So is their any way to disable Recent app button or to clear app thumbnail.
Please help me with any code sample or doc.Thanks in advance.
You've asked multiple questions. Here, I'm trying to answer your second question;
Is their any way to find device is, Mobile or Tab using java code.
You can use the screen size to determine whether your code is running on a tablet or mobile phone, see the code below;
public boolean isTablet() {
try {
// Compute screen size
DisplayMetrics dm = context.getResources().getDisplayMetrics();
float screenWidth = dm.widthPixels / dm.xdpi;
float screenHeight = dm.heightPixels / dm.ydpi;
double size = Math.sqrt(Math.pow(screenWidth, 2) + Math.pow(screenHeight, 2));
// Tablet devices should have a screen size greater than 6 inches
return size >= 6;
} catch(Throwable t) {
Log.error(TAG_LOG, "Failed to compute screen size", t);
return false;
}
}
Source: http://groups.google.com/group/android-developers/browse_thread/thread/d6323d81f226f93f