The COVID-19 outbreak has thrown personal health into the spotlight. To help tackle the pandemic, HUAWEI Contact Shield tracks contact records between people.
This article explains how the risk value used to determine a person's risk of catching COVID-19 is calculated.
For details about how Contact Shield tracks contact records, please refer to the development guide.
Due to version updates, Contact Shield provides two logic sets (TotalRiskValue and ContactWindowScore) for you to calculate the risk value. Let's learn about TotalRiskValue and ContactWindowScore respectively.
TotalRiskValue
Contact Shield calculates the total risk value based on the following formula:
TotalRiskValue = attenuationRiskValue * daysAfterContactedRiskValue * durationRiskValue * initialRiskLevelRiskValue
attenuationRiskValue: contact distance with a diagnosed user. The closer the distance is, the higher the risk value is. The value ranges from 0 to 8.
daysAfterContactedRiskValue: number of days between the last contact time and the current time. The closer the value is to the current time, the higher the risk value is. The value ranges from 0 to 8.
durationRiskValue: risk value corresponding to the contact duration. The longer the contact duration is, the higher the risk value is. The value ranges from 0 to 8.
initialRiskLevelRiskValue: initial risk level of the current periodic key, which is determined when the diagnosed user uploads the periodic key. The value ranges from 0 to 8.
TotalRiskValue is obtained by multiplying these four variables. For details about how to calculate these four variables, please refer to the following code:
The putSharekeyFiles API is called before the diagnosis result is obtained (getContactSketch and getContactDetail). This API contains an input parameter DiagnosisConfiguration, which determines the four variables mentioned above.
Java:
public void putKeys () {
........
// Set the diagnosis configuration.
DiagnosisConfiguration config = new DiagnosisConfiguration.Builder()
.setAttenuationDurationThresholds(100, 200)
.setAttenuationRiskValues(0, 0, 0, 0, 1, 2, 3, 4)
.setDaysAfterContactedRiskValues(0, 0, 0, 0, 1, 2, 3, 4)
.setDurationRiskValues(0, 0, 0, 0, 1, 2, 3, 4)
.setInitialRiskLevelRiskValues(0, 0, 0, 0, 1, 2, 3, 4)
.setMinimumRiskValueThreshold(2)
.build();
PendingIntent pendingIntent = PendingIntent.getService(this, 0,
new Intent(this, BackgroundContackCheckingIntentService.class),
PendingIntent.FLAG_UPDATE_CURRENT);
// Start diagnosis.
mEngine.putSharedKeyFiles(pendingIntent, putList, config, token)
.addOnSuccessListener(aVoid -> {
Log.d(TAG, "putSharedKeyFiles succeeded.");
})
.addOnFailureListener(e -> {
Log.d(TAG, "putSharedKeyFiles failed, cause: " + e.getMessage());
});
}
We can learn about the four variables and their value setting logic in DiagnosisConfiguration based on the API reference. We can see that, the four variables are set as arrays in the DiagnosisConfiguration class.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Although the arrays here are size-mutable arrays (int...), their lengths are actually fixed. The following examples give a clearer insight into the four variables.
The description of arrays in the setAttenuationRiskValues method in the API reference is as follows:
Contact Shield roughly defines the contact distance between two people based on the attenuation of the Bluetooth signal.
For example, setAttenuationRiskValues(0, 0, 0, 0, 1, 2, 3, 4) indicates the following:
If the attenuation is greater than 73 dBm, the value of attenuationRiskValues is 0.
If the attenuation is greater than 63 dBm and less than or equal to 73 dBm, the value of attenuationRiskValues is 0.
If the attenuation is greater than 51 dBm and less than or equal to 63 dBm, the value of attenuationRiskValues is 0.
If the attenuation is greater than 33 dBm and less than or equal to 51 dBm, the value of attenuationRiskValues is 0.
If the attenuation is greater than 27 dBm and less than or equal to 33 dBm, the value of attenuationRiskValues is 1.
If the attenuation is greater than 15 dBm and less than or equal to 27 dBm, the value of attenuationRiskValues is 2.
If the attenuation is greater than 10 dBm and less than or equal to 15 dBm, the value of attenuationRiskValues is 3.
If the attenuation is less than or equal to 10 dBm, the value of attenuationRiskValues is 4.
The configurations of daysAfterContactedRiskValues, durationRiskValues and initialRiskLevelRiskValues are similar.
setDaysAfterContactedRiskValues(0, 0, 0, 0, 1, 2, 3, 4) indicates the following:
If the number of days elapsed since the last contact between a person and a diagnosed user is greater than or equal to 14, the value of daysAfterContactedRiskValues is 0.
If the number of days elapsed since the last contact between a person and a diagnosed user is greater than or equal to 12 and less than 14, the value of daysAfterContactedRiskValues is 0.
If the number of days elapsed since the last contact between a person and a diagnosed user is greater than or equal to 10 and less than 12, the value of daysAfterContactedRiskValues is 0.
If the number of days elapsed since the last contact between a person and a diagnosed user is greater than or equal to 8 and less than 10, the value of daysAfterContactedRiskValues is 0.
If the number of days elapsed since the last contact between a person and a diagnosed user is greater than or equal to 6 and less than 8, the value of daysAfterContactedRiskValues is 1.
If the number of days elapsed since the last contact between a person and a diagnosed user is greater than or equal to 4 and less than 6, the value of daysAfterContactedRiskValues is 2.
If the number of days elapsed since the last contact between a person and a diagnosed user is greater than or equal to 2 and less than 4, the value of daysAfterContactedRiskValues is 3.
If the number of days elapsed since the last contact between a person and a diagnosed user is greater than or equal to 0 and less than 2, the value of daysAfterContactedRiskValues is 4.
setDurationRiskValues(0, 0, 0, 0, 1, 2, 3, 4) indicates the following:
If there is no contact between a person and a diagnosed user, the value of durationRiskValues is 0.
If the contact duration between a person and a diagnosed user is less than or equal to 5 minutes, the value of durationRiskValues is 0.
If the contact duration between a person and a diagnosed user is greater than 5 and less than or equal to 10 minutes, the value of durationRiskValues is 0.
If the contact duration between a person and a diagnosed user is greater than 10 and less than or equal to 15 minutes, the value of durationRiskValues is 0.
If the contact duration between a person and a diagnosed user is greater than 15 and less than or equal to 20 minutes, the value of durationRiskValues is 1.
If the contact duration between a person and a diagnosed user is greater than 20 and less than or equal to 25 minutes, the value of durationRiskValues is 2.
If the contact duration between a person and a diagnosed user is greater than 25 and less than or equal to 30 minutes, the value of durationRiskValues is 3.
If the contact duration between a person and a diagnosed user is greater than 30 minutes, the value of durationRiskValues is 4.
setInitialRiskLevelRiskValues(0, 0, 0, 0, 1, 2, 3, 4) indicates the following:
If a user has had contacted with a diagnosed user who has the lowest risk level, the value of initialRiskLevelRiskValues is 0.
If a user has had contacted with a diagnosed user who has the low risk level, the value of initialRiskLevelRiskValues is 0.
If a user has had contacted with a diagnosed user who has the low-medium risk level, the value of initialRiskLevelRiskValues is 0.
If a user has had contacted with a diagnosed user who has the medium risk level, the value of initialRiskLevelRiskValues is 0.
If a user has had contacted with a diagnosed user who has the medium-high risk level, the value of initialRiskLevelRiskValues is 1.
If a user has had contacted with a diagnosed user who has the high risk level, the value of initialRiskLevelRiskValues is 2.
If a user has had contacted with a diagnosed user who has the extremely high risk level, the value of initialRiskLevelRiskValues is 3.
If a user has had contacted with a diagnosed user who has the highest risk level, the value of initialRiskLevelRiskValues is 4.
Note: You can manually set the risk level after obtaining the shared key of the diagnosed user. For details, please refer to setInitialRiskLevel.
The above is the value setting logic of attenuationRiskValue, daysAfterContactedRiskValue, durationRiskValue, and initialRiskLevelRiskValue. You can view these four variables in the ContactDetail class that is returned by calling the getContactDetail API after diagnosis.
And that’s everything for calculating TotalRiskValue.
This example will help illustrate the logic:
On March 10, 2020, A and B had a meal together (the Bluetooth attenuation was about 10–15), for around 40 minutes. After the meal, they both returned to their homes and never saw each other again.
On March 15, 2020, B was diagnosed with COVID-19 and labeled as medium-high risk. Following this, healthcare workers immediately instructed B to upload his shared key onto Contact Shield. If the diagnosis configuration code of the app used by the hospital is as follows:
DiagnosisConfiguration config = new DiagnosisConfiguration.Builder() .setAttenuationRiskValues(0, 0, 0, 0, 1, 2, 3, 4) .setDaysAfterContactedRiskValues(0, 0, 0, 0, 1, 2, 3, 4) .setDurationRiskValues(0, 0, 0, 0, 1, 2, 3, 4) .setInitialRiskLevelRiskValues(0, 0, 0, 0, 1, 2, 3, 4) …… .build();
what is the value of TotalRiskValue for A?
This is calculated as follows:
According to the description, the Bluetooth attenuation ranges from 10 to 15. Therefore, the value of attenuationRiskValue is 3 based on the diagnosis configuration setAttenuationRiskValues(0, 0, 0, 0, 1, 2, 3, 4).
The contact duration between the two is 40 minutes, meaning the value of durationRiskValue is 4 based on the diagnosis configuration setDurationRiskValues(0, 0, 0, 0, 1, 2, 3, 4).
Five days have elapsed since A and B contact. As a result, the value of daysAfterContactedRiskValue is 2 based on the diagnosis configuration setDaysAfterContactedRiskValues(0, 0, 0, 0, 1, 2, 3, 4).
B is diagnosed as a COVID-19 patient with medium-high risk, and therefore the value of initialRiskLevelRiskValue is 1 based on the diagnosis configuration setInitialRiskLevelRiskValues(0, 0, 0, 0, 1, 2, 3, 4).
As a result, TotalRiskValue = attenuationRiskValue * daysAfterContactedRiskValue * durationRiskValue * initialRiskLevelRiskValue = 3 x 2 x 4 x 1 = 24.
If the above assumption remains unchanged, while the diagnosis configuration code is changed to the following:
Java:
DiagnosisConfiguration config = new DiagnosisConfiguration.Builder()
.setAttenuationRiskValues(1, 2, 3, 4, 5, 6, 7, 8)
.setDaysAfterContactedRiskValues(1, 2, 3, 4, 5, 6, 7, 8)
.setDurationRiskValues(1, 2, 3, 4, 5, 6, 7, 8)
.setInitialRiskLevelRiskValues(1, 2, 3, 4, 5, 6, 7, 8)
……
.build();
TotalRiskValue of A will change to 1680 (7 x 6 x 8 x 5 = 1680). The calculation details are not described here.
ContactWindowScore
Contact Shield calculates the risk value of each contact window based on the following formula:
ContactWindowScore = reportTypeScore * contagiousnessScore * attenuationDurationScore
reportTypeScore: risk value corresponding to the report type of the shared key. For details about its configuration, please refer to setWeightOfReportType().
contagiousnessScore: risk value corresponding to the contagiousness of the diagnosed user. For details about its configuration, please refer to setWeightOfContagiousness(). Contagiousness is related to the number of days between the current day and the first symptom of the virus. For details, please refer to setDaysSinceCreationToContagiousness().
attenuationDurationScore: Bluetooth scanning data contained in the contact window, and risk value calculated based on the contact distance and time. For details about the configuration, please refer to setThresholdsOfAttenuationInDb().
At the code level, ContactWindowScore and TotalRiskValue are configured at different time points.
Specifically, TotalRiskValue is configured before you call the putSharekeyFiles API, while ContactWindowScore is configured when you call the getDailySketch API after the putSharekeyFiles API is successfully called. The sample code is as follows:
Java:
public void getDailySketches() {
DailySketchConfiguration configuration = new DailySketchConfiguration.Builder()
.setWeightOfReportType(0, 0)
.setWeightOfReportType(1, 1.0)
.setWeightOfReportType(2, 1.1)
.setWeightOfReportType(3, 1.2)
.setWeightOfReportType(4, 1.3)
.setWeightOfReportType(5, 1.4)
.setWeightOfContagiousness(0, 0)
.setWeightOfContagiousness(1, 2.1)
.setWeightOfContagiousness(2, 2.2)
.setThresholdsOfAttenuationInDb(Arrays.asList(50, 150, 200), Arrays.asList(2.5, 2.0, 1.0, 0.0))
.setThresholdOfDaysSinceHit(0)
.setMinWindowScore(0)
.build();
mEngine.getDailySketch(configuration)
.addOnSuccessListener(dailySketches -> {
Log.d(TAG, "getDailySketch succeeded.");
// Process diagnosis results.
………
})
.addOnFailureListener(e -> Log.d(TAG, "getDailySketch failed." + e.toString()));
}
Unlike DiagnosisConfiguration, which configures TotalRiskValue mainly in the form of array, DailySketchConfiguration configures ContactWindowScore in the form of chain expression.
Note: The above sample code can be called only after the putSharekeyFiles API is successfully called.
We can learn about the three variables (reportType, contagiousnessScore, and attenuationDurationScore) and how their values are set based on the API reference.
The value of reportTypeScore is related to the setWeightOfReportType API which is in the form of <key, value> and can be called repeatedly. key indicates the current report type, and value indicates the weight of each report type.
ReportType values displayed in the following figure are for reference only, and their values can be customized as required.
If setWeightOfReportType() is set as follows:
Java:
new DailySketchConfiguration.Builder()
.setWeightOfReportType(0, 0)
.setWeightOfReportType(1, 1.0)
.setWeightOfReportType(2, 1.1)
.setWeightOfReportType(3, 1.2)
.setWeightOfReportType(4, 1.3)
.setWeightOfReportType(5, 1.4)
it indicates:
If reportType is 0, the value of reportTypeScore is 0.
If reportType is 1, the value of reportTypeScore is 1.0.
If reportType is 2, the value of reportTypeScore is 1.1.
If reportType is 3, the value of reportTypeScore is 1.2.
If reportType is 4, the value of reportTypeScore is 1.3.
If reportType is 5, the value of reportTypeScore is 1.4.
The configurations of contagiousnessScore and attenuationDurationScore are similar.
The value of contagiousnessScore is related to the setWeightOfContagiousness API which is in the form of <key, value> and can be called repeatedly. key indicates the contagiousness of the current confirmed patient, and value indicates the weight of each contagiousness.
Contagiousness values displayed in the following figure are for reference only.
If setWeightOfContagiousness() is set as follows:
Java:
new DailySketchConfiguration.Builder()
.setWeightOfContagiousness(0, 0)
.setWeightOfContagiousness(1, 2.1)
.setWeightOfContagiousness(2, 2.2)
If the diagnosed user has no or uncertain contagiousness, Contagiousness is 0 and the value of contagiousnessScore is 0.
If the diagnosed user has standard contagiousness, Contagiousness is 1 and the value of contagiousnessScore is 2.1.
If the diagnosed user has high contagiousness, Contagiousness is 2 and the value of contagiousnessScore is 2.2.
The value of attenuationDurationScore is related to the setThresholdsOfAttenuationInDb API which has two input parameters: List<Integer> list and List<Double> list1. For details, please refer to the description in the API reference.
If setThresholdsOfAttenuationInDb() is set as follows:
Java:
setThresholdsOfAttenuationInDb(Arrays.asList(50, 150, 200), Arrays.asList(2.5, 2.0, 1.0, 0.0))
it indicates: If the Bluetooth signal strength is less than or equal to 50 dBm, the value of attenuationDurationScore is 2.5.
If the Bluetooth signal strength is greater than 50 dBm and less than or equal to 150 dBm, the value of attenuationDurationScore is 2.0.
If the Bluetooth signal strength is greater than 150 dBm and less than or equal to 200 dBm, the value of attenuationDurationScore is 1.0.
If the Bluetooth signal strength is greater than 200 dBm, the value of attenuationDurationScore is 0.
This part has shown the value setting logic of reportTypeScore, contagiousnessScore, and attenuationDurationScore.
Note: You can view these three variables in the ContactWindow class that is returned by calling the getContactWindow API after diagnosis.
And that’s everything for calculating ContactWindowScore.
This example will help illustrate the logic:
On March 10, 2020, A and B had a meal together (the Bluetooth attenuation was about 10–15), for around 40 minutes. After the meal, they both returned to their homes and never saw each other again.
On March 15, 2020, B was diagnosed with COVID-19 and labeled as high contagiousness. Following this, healthcare workers immediately instructed B to upload his shared key onto Contact Shield, and set his reportType to 1. If the diagnosis configuration code of the app used by the hospital is as follows:
Java:
DailySketchConfiguration configuration = new DailySketchConfiguration.Builder()
.setWeightOfReportType(0, 0)
.setWeightOfReportType(1, 1.0)
.setWeightOfReportType(2, 1.1)
.setWeightOfReportType(3, 1.2)
.setWeightOfReportType(4, 1.3)
.setWeightOfReportType(5, 1.4)
.setWeightOfContagiousness(0, 0)
.setWeightOfContagiousness(1, 2.1)
.setWeightOfContagiousness(2, 2.2)
.setThresholdsOfAttenuationInDb(Arrays.asList(50, 150, 200), Arrays.asList(2.5, 2.0, 1.0, 0.0))
.setThresholdOfDaysSinceHit(0)
.setMinWindowScore(0)
.build();
what is the value of TotalRiskValue for A?
This is calculated as follows:
The Bluetooth attenuation ranges from 10 to 15. Therefore, the value of attenuationDurationScore is 2.5 based on the diagnosis configuration setThresholdsOfAttenuationInDb(Arrays.asList(50, 150, 200), Arrays.asList(2.5, 2.0, 1.0, 0.0)).
B is confirmed as a diagnosed patient with high contagiousness, and subsequently the value of contagiousnessScore is 2.2 based on the diagnosis configuration setWeightOfContagiousness(2, 2.2).
Healthcare workers set the reportType for B to 1. Therefore, the value of reportTypeScore is 1.0 based on the diagnosis configuration setWeightOfReportType(1, 1.0).
As a result, ContactWindowScore = reportTypeScore * contagiousnessScore * attenuationDurationScore = 1.0 x 2.2 x 2.5 = 5.5.
If the above configuration remains unchanged while B is determined to have standard contagiousness, and his reportType is set to 3,
TotalRiskValue of A will change to 6.3 (1.2 x 2.1 x 2.5 = 6.3). The calculation details are not described here.
To learn more, please visit:
HUAWEI Developers official website
Development Guide
Reddit to join developer discussions
GitHub or Gitee to download the demo and sample code
Stack Overflow to solve integration problems
Follow our official account for the latest HMS Core-related news and updates.
Original Source
Related
Hi all, as you may or may not know from my recent posts, I've been trying my hand at kernel development. I have some questions though.
What are the limits to audio boost? I have mine boosted up to 2500 max & -500 min & everything runs fine & I get a HUGE boost over the normal boost of -1500 to 1100. Why aren't all kernels built like this? Obviously stupid values like 100,000 wont work, but why not ~2000-2500 on audioboost kernels? Why not 3000? What is the safe level? Just wondering what the reasoning behind the oddball 1100 max is on most kernels.
Next, most kernel devs know about the RGB666 (more color depth support) for the CDMA revisions in board-mahimahi-panel.c. I looked through the code, and other than the revision checker that decides whether to use the RGB666 or RGB565 init tables, there is only one line of code different between the two panels and thats in the init table itself:
Code:
static struct lcm_tbl samsung_oled_rgb565_init_table[] = {
{ 0x31, 0x08 },
{ 0x32, 0x14 },
{ 0x30, 0x2 },
{ 0x27, 0x1 },
{ 0x12, 0x8 },
{ 0x13, 0x8 },
{ 0x15, 0x0 },
[B][COLOR="Red"]{ 0x16, 0x02 },[/COLOR][/B]
{ 0x39, 0x24 },
{ 0x17, 0x22 },
{ 0x18, 0x33 },
{ 0x19, 0x3 },
{ 0x1A, 0x1 },
{ 0x22, 0xA4 },
{ 0x23, 0x0 },
{ 0x26, 0xA0 },
};
static struct lcm_tbl samsung_oled_rgb666_init_table[] = {
{ 0x31, 0x08 },
{ 0x32, 0x14 },
{ 0x30, 0x2 },
{ 0x27, 0x1 },
{ 0x12, 0x8 },
{ 0x13, 0x8 },
{ 0x15, 0x0 },
[COLOR="Red"][B]{ 0x16, 0x01 },[/B][/COLOR]
{ 0x39, 0x24 },
{ 0x17, 0x22 },
{ 0x18, 0x33 },
{ 0x19, 0x3 },
{ 0x1A, 0x1 },
{ 0x22, 0xA4 },
{ 0x23, 0x0 },
{ 0x26, 0xA0 },
};
That is the ONLY difference, even between the gamma level settings. Does that ONE line have that much of an effect as to increase color depth that much?
Anyway, I've removed the version check code and set it to always use the RGB666 init table. The kernel runs & boots fine, all the graphics run great still. I've done some admittedly very subjective tests with images that I KNOW on a stock kernel have severe banding in Gallery3D, and on my kernel, the banding is almost, if not entirely gone. It is a noticeable improvement, but without side-by-side tests that I simply can't do, it's not very scientific at all.
Can any experts weigh in? Sorry if it seems like a lot of questions, I'm just trying to figure this out so I can attempt to contribute something lol
where did you test the images? i thought the banding was due to the 16bit colour depth coded into the 3D gallery app
Somebody boost the ringtones volume please
There are certainly a solution if the ''incall volume'' has been already boosted
vegetaleb said:
Somebody boost the ringtones volume please
There are certainly a solution if the ''incall volume'' has been already boosted
Click to expand...
Click to collapse
+1 pls, it rings with ridiculously low volume
I have to agree with this.
In Call Volume NOOB
I recently upgraded from Cyanogen 5053 to 506, and I noticed that the bluetooth volume in call is super loud, so that i can't understand what's being said. Is there a way to reduce the incall volume through a nice GUI? or is there another way to lower the incall volume?
the range for qdsp6 audio are:
+1200 to -4000
after some testing, i determined +1100 to -1500 was a good trade-off between too loud and too soft, and that within which is adjustable via volume rocker.
pershoot said:
the range for qdsp6 audio are:
+1200 to -4000
after some testing, i determined +1100 to -1500 was a good trade-off between too loud and too soft, and that within which is adjustable via volume rocker.
Click to expand...
Click to collapse
Ahh OK thanks. Good 'ol placebo effect lol.
Also, i had known there were problems with Gallery3D being 16bit, but a stock nexus kernel only has support for RGB565 on GSM/UMTS devices, but CDMA revisions allow for RGB666. What effect does this have on us with only RGB565? Is hardcoding RGB666 values unsafe? What effect will it have since the color depth issue is just in Gallery3D?
Hmm, looking at the code where it sets the absolute min/max values, would it be possible to change the values here to allow higher highs? I.E:
Code:
int q6audio_set_stream_volume(struct audio_client *ac, int vol)
{
if (vol > 1200 || vol < -4000) {
pr_err("unsupported volume level %d\n", vol);
return -EINVAL;
}
mutex_lock(&audio_path_lock);
audio_stream_mute(ac, 0);
audio_stream_volume(ac, vol);
mutex_unlock(&audio_path_lock);
return 0;
}
changed to say:
Code:
int q6audio_set_stream_volume(struct audio_client *ac, int vol)
{
[B][COLOR="Red"]if (vol > 1500 || vol < -4000) {[/COLOR][/B]
pr_err("unsupported volume level %d\n", vol);
return -EINVAL;
}
mutex_lock(&audio_path_lock);
audio_stream_mute(ac, 0);
audio_stream_volume(ac, vol);
mutex_unlock(&audio_path_lock);
return 0;
}
Theoretically, you could probably change the volume limit levels to whatever you want. I know on the G1 you can carry on going until the speaker physically breaks, although it is done in a different way.
Meltus said:
Theoretically, you could probably change the volume limit levels to whatever you want. I know on the G1 you can carry on going until the speaker physically breaks, although it is done in a different way.
Click to expand...
Click to collapse
Interesting. How high do you think we can safely push the Nexus, or do you have no idea? Im kinda afraid to just experiment cuz I'm afraid to break my speaker,but if you have no idea I will try.
Geniusdog254 said:
Interesting. How high do you think we can safely push the Nexus, or do you have no idea? Im kinda afraid to just experiment cuz I'm afraid to break my speaker,but if you have no idea I will try.
Click to expand...
Click to collapse
I have absolutely no idea i'm afraid, i don't know how to increase the volume properly, but i'm trying to figure it out (no idea if i'll be successful).
I came close to breaking the main speaker on my G1 when i first starting experimenting with the values, but as long as you're careful you should be ok lol
Geniusdog254 said:
Ahh OK thanks. Good 'ol placebo effect lol.
Also, i had known there were problems with Gallery3D being 16bit, but a stock nexus kernel only has support for RGB565 on GSM/UMTS devices, but CDMA revisions allow for RGB666. What effect does this have on us with only RGB565? Is hardcoding RGB666 values unsafe? What effect will it have since the color depth issue is just in Gallery3D?
Click to expand...
Click to collapse
Regarding RGB565, a Google-employed Android project kernel hacker who on occasion visits this forum (swetland) confimed that the physical wiring to the AMOLED panel is only RGB565/16-bits. The one-bit change you mention is in the panel configuration data and probably tells the panel to expect data on those extra two input bits. They are probably the least significant bits, and tied low in hardware which is why you don't notice it not working. I doubt there is any chance of harm, but there is also zero chance of it improving the panel quality. The extra bits simply aren't connected.
(There are also some more changes for RGB666 in the mdp driver that you seemingly didn't notice... these are less likely to be safe as they control the extra bits coming out of the QSD8250. These pins might be used for something else and it's difficult to know if it's safe without both the QSD8250 programming manual (not public) and the PCB schematics. )
Hi, i've seen many people complaining about audio boost to get higher volume through the phone but very few looking at bluetooth headsets.
Audio boost makes the volume through these ones too high, in the end the quality is very bad, audio results overboosted and noisy.
Do you know if there is any way to separate built-in speaker and BT parameters?
ya how bout some you guys try a hearing aid
This thread is for those following the battery calibration thread that would like to help build tools to read and set some advanced battery values, and ultimately recalibrate in learning mode.
It takes its inspiration from this forum thread over at precentral :
http://forums.precentral.net/palm-pre/256967-find-out-how-good-bad-your-battery.html
See HOW-TO in post 3 below, or in-thread post from mtw4991, for instructions on using app to calibrate
reference material
battery manufacturer technical info
DS2784 data sheet - http://datasheets.maxim-ic.com/en/ds/DS2784.pdf
Storing Fuel Gauge Parameters in the DS2784 - http://pdfserv.maxim-ic.com/en/an/AN4043.pdf
Lithium-Ion Cell Fuel Gauging with Maxim Battery Monitor ICs - http://pdfserv.maxim-ic.com/en/an/AN131.pdf
code
cyanogenmod github repository / kanged HTC code - http://github.com/CyanogenMod/cm-kernel/blob/android-msm-2.6.34/drivers/power/ds2784_battery.c
HTC Desire - http://developer.htc.com/ (use HTC Desire kernel source code download)
edit 2010/11/17: source code for battery driver mods - http://github.com/thelogin/n1batcal/
edit 2010/12/15: source code for app -
app availability
available from the Android Marketplace
link: https://market.android.com/details?id=net.jonrichards.batterycalibrator.ui (thanks, McFroger3!)
reference info
thread at precentral which was the inspiration for this thread - http://forums.precentral.net/palm-pre/256967-find-out-how-good-bad-your-battery.html
spreadsheet of registers - https://spreadsheets.google.com/ccc...VNzdXpqWVdFejNGM1pLWmc&hl=en&authkey=CJ_ItagO
related apps
Dr. Battery on the Pre - http://discussion.treocentral.com/homebrew-apps/260947-dr-battery.html
specific code references
(with reference to the manufacturer battery info above)
1 - CONTROL REGISTER FORMAT - page 12 - UVEN—Undervoltage Enable
1 - CAPACITY ESTIMATION ALGORITHM - page 21 - Figure 3: Top-Level Algorithm Diagram
1 - page 24
from Active Empty Voltage (VAE) - includes Aging Capacity (AC) and Age Scalar (AS)
CAPACITY ESTIMATION OPERATION - Learn Function ("A continuous charge from empty to full results in a learn cycle." then "First, the active empty point must be detected."!!)
1 - page 25 - STATUS REGISTER FORMAT
(to be completed)
with thanks to RogerPodacter for his help in compiling this list
progress status and useable findings
status
we have made mods to the kernel code (based on 2.6.35.x) to
make any register writable
make the following registers readable: AGE, Vae (ACTIVE_EMPTY_VOLT), and Status Reg (STS)
allow read/write of these registers via virtual files
remove pseudo-extended battery charging
edit 2010/11/17: created a "dumpreg" file to show all registers and their current values
edit 2010/11/17:
work is being done on a GUI app with the following initial functionality:
show when learn mode is hit
save age when learn mode is complete
the following functionality may be in:
option to restore age when app launched
HOW-TO
mtw4991 said:
How to calibrate your battery using the Battery Calibrator App....
(original text: http://forum.xda-developers.com/showpost.php?p=9583271&postcount=340)
1. Use the battery calibrator app v.1.3.0 to do the following:
a. Open the app and go to menu>settings and check all boxes. Auto-on airplane mode is optional
b. set your age to 100 using the battery app under the Learn Prep tab and press Save
c. set your full40 to 1452mAh in the same tab if using the stock capacity OEM battery and press Save
NOTE: set your full40 to 1650mAh or higher if using an aftermarket battery and save
2. In the Learn Prep tab:
a. set your aEvolts to 3201 (type on each line: Register:0x 66 Value: a4 and press save)
b. set your stop charging current to <20mA (Register:0x 65 Value: 06 and press save)
c. if Capacity/mAh drops to near empty prior to 3201mV being reached, the app will automatically raise capacity by 200mAh so phone doesn't auto-shutdown prior to reaching 3201mV
3. Achieving Learn Mode with the app:
a. turn learn mode on in Learn Mode tab
NOTE: to hit learn mode you must keep your current mA above -200mA draw at the empty point! The app will automatically enable GPS polling to keep you above the required minimum current draw.
b. wait for mV to drop to 3201mV (the learn mode pop-up box will appear & learnf button will light up)
c. insert charger IMMEDIATELY! (You will see a pop-up message saying Learn Mode is active.)
d. turn off and close any open apps you have running, but leave Battery Calibrator open.
e. put phone into airplane mode so that you don’t get unexpected current draw near the full point.
f. set SetCPU profile to disable overclocking. (set min/max to the same value, ie. 998\998max)
g. charge for a full 4 hrs with stock battery and screen off, 5 hrs for larger capacity batterys.
NOTE: if you want to, you can actually use your phone until the charge reaches 80-90%, then use airplane mode and DO NOT touch the phone, peek, turn on the screen....DO NOTHING but walk away til time is up.
h. unplug and reboot, your new age should be set automatically. Learn is now complete and your phone should now charge to 100% and die at 0-1%. Also, some have reported having to manually power down/power up with the new app to have age reset by the application. If age isn’t change upon reboot, try power off/power on.
4. Learn Failure:
If your new age shows 94% upon rebooting, then learn mode failed and you need to do it again, paying close attention as charging nears 80% and above. This is where learn mode can be lost by rogue apps, auto-updates, calls, etc pulling the current down below the minimum prematurely.
Note1: As current gets close to <50-60mA don't touch the phone or you may artifically increase the current draw pulling it below 20mA and it will end the learn cycle prematurely. Airplane mode helps prevent that.
Note2: Learn mode cannot be achieve with the phone off. Leave the phone on until learn is complete and the battery status register shows 0x81. Done!
How to perform a Capacity Test for your battery. Credit goes to the infamous Temasek!
Prepare for another learn cycle
This time we will do what I call a capacity test.
Perform another learn cycle.
Once cycle completed do not reboot. Check your battery log using an app like OS Monitor. See your highest achieved capacity at 99-100% before it completed its charge. The capacity should drop below your full40. Read the log properly. The highest achieved capacity before it drop below your full40 will be your new full40 value.
With your new full40 value, perform yet another learn cycle.
Enjoy your new calibrated battery!
Click to expand...
Click to collapse
HOW-TO2:
http://forum.xda-developers.com/showpost.php?p=24599586&postcount=284 (as requested by St4hli)
Initial investigation and analysis
OK, so I'm going to try and use the following repositories in github and in this order:
AOSP > pershoot > CyanogenMod > others
as I'd like it as generic as possible and ideally integrate any patches at the highest level.
Not being an expert in github, you'll have to excuse any obvious noobness! I couldn't see any of the 2784 battery stuff in AOSP so I'm guessing the CM team used the Desire kernel source from developer.htc.com to integrate the files. Actual code here:
http://member.america.htc.com/download/RomCode/Source_and_Binaries/bravo_54b7033a.tar.gz
------
At:
http://github.com/CyanogenMod/cm-kernel/blob/android-msm-2.6.34/drivers/power/ds2784_battery.c
we see device info struct as:
Code:
char raw[DS2784_DATA_SIZE]; /* raw DS2784 data */
struct battery_status status;
struct power_supply bat;
struct workqueue_struct *monitor_wqueue;
struct work_struct monitor_work;
struct alarm alarm;
struct wake_lock work_wake_lock;
with battery_status struct as:
Code:
u8 percentage; /* battery percentage */
u8 charge_source;
u8 status_reg;
u8 battery_full; /* battery full (don't charge) */
i.e. not many properties.
However, from the corresponding include file at:
http://github.com/CyanogenMod/cm-kernel/blob/android-msm-2.6.34/drivers/power/w1_ds2784.h
there are lots of defined registers, including several AGE and FULL_40.
Our 2784 code has both read and write functions (w1_ds2784_read/write), which are used in function ds2784_battery_read_status.
** Objective 1**
title:
to read some additional values such as AGE and FULL_40 and output them.
suggested implementation:
add in some other properties corresponding to AGE and FULL_40 values, populate these in the read function, parse them in the parse_data function, then output them at line 325 of the ds2784_battery.c file. Yes there will be lots of repetition, but the code is easily and quick to modify.
ideal implementation:
write a new app that outputs these but also outputs the status_reg value too. We can then use this to determine if and when our batteries go into "learning" mode. More below.
code-level:
1) modify struct battery_status, adding:
Code:
u16 age;
u16 full_40;
etc, with any other interesting ones too. Might as well grab all of them and output so we can hand-pick the ones that are useful.
2) from line 244 in parse_data, add something like:
Code:
s->age = raw[DS2784_REG_AGE_SCALAR];
etc
may have to convert from hex.
*****************
THEN I opened the HTC ds2784_battery.c and was amazed at what I saw!
*****************
*their* battery_info struct contains:
Code:
u8 level; /* formula */
u8 level_last;
u32 full_bat; /* Full capacity of battery (mAh) */
u32 full_level; /* Full level for battery control */
u8 guage_status_reg;/* guage status*/
u32 acr;
u32 active_empty;
their ds2784_device_info struct:
Code:
int guage_status_reg; /* battery status register offset=01h*/
int full_mah; /* battery full mah */
long full_charge_count; /* Full charge counter */
int acr;
int active_empty;
int full_level; /* Full level for battery control */
OK nothing earthshattering so far, BUT their Calculate_Full_mAh function uses the FULL_40 stuff.
** Objective 2 **
title: write values to registers
implementation: to be discussed once we have the values from Objective 1 and we still need it (i.e. learning mode does not exist or work to recalibrate).
Wrap-up:
The HTC charging code (from line 854) uses the following logic:
Code:
percent < 95, batt full = false
if status_reg = full and current <= 80 and percent = 100
then *IF IT HAS BEEN ONE HOUR OR MORE ON FULL CHARGE*!!!
then stop charging
WOW.
Nice thread. I'll give you a hand with this. Do you still need help getting your kernel compiling set up?
dvgrhl said:
Nice thread. I'll give you a hand with this. Do you still need help getting your kernel compiling set up?
Click to expand...
Click to collapse
yeah - how best to do this? what about gtalk? <mylogin>@gmail.com if you are OK with that. Will be online in two mins
loginwithnoname, very nice summary and overview. the HTC driver is what most interests me. i guess there would be zero chance of using the HTC code and logic, since it seems they A) use the better values of full_capacity, etc rather than the nexus "conservative" estimation. and B) theirs looks a little more straight forward than the nexus one.
where did you find the HTC driver? i cant seem to find it.
nice work!
just in case you still interested, here is the AOSP source code that pershoot used. well he used his code, then he posted this link in the other thread and said this is his current source he's using.
EDIT: sorry i meant this link
EDIT2: geez, still was cm code. i'll find it real quick.
finally:
http://android.git.kernel.org/?p=ke...54cfa3b22c61dd50eae;hb=android-msm-2.6.35-wip
RogerPodacter said:
the HTC driver is what most interests me. i guess there would be zero chance of using the HTC code and logic, since it seems they A) use the better values of full_capacity, etc rather than the nexus "conservative" estimation. and B) theirs looks a little more straight forward than the nexus one.
Click to expand...
Click to collapse
I think their code is old-hat given what we've done in the other thread, apart from the fact they wait an hour before deeming the battery "fully charged". I don't think as techies/devs we need that though.
thelogin said:
I couldn't see any of the 2784 battery stuff in AOSP so I'm guessing the CM team used the Desire kernel source from developer.htc.com to integrate the files. Actual code here:
http://member.america.htc.com/downlo...4b7033a.tar.gz
where did you find the HTC driver? i cant seem to find it.
Click to expand...
Click to collapse
Click to expand...
Click to collapse
aw, come on Rog! that'll be http://developer.htc.com then click the download button for HTC Desire kernel source code
theloginwithnoname said:
I think their code is old-hat given what we've done in the other thread, apart from the fact they wait an hour before deeming the battery "fully charged". I don't think as techies/devs we need that though.
aw, come on Rog! that'll be http://developer.htc.com then click the download button for HTC Desire kernel source code
Click to expand...
Click to collapse
ha i found the HTC developer site, and grabbed the 74mb source kernel for the desire, but i'm at my work computer which i have no admin rights to do anything. how could i view that code? i was hoping for online repositories like github.
RogerPodacter said:
i'm at my work computer which i have no admin rights to do anything. how could i view that code? i was hoping for online repositories like github.
Click to expand...
Click to collapse
It's a .tar.gz so you need to unzip it then extract it. If you're on Windows, I'm told WinZip will unzip/extract it for you (I used 7-Zip); if you're on linux, tar -zxvf <file>.tar.gz will do it for you...
i wont clutter up this thread anymore, but winzip was the first thing i tried. its a strange winzip used here though, so its expected.
theloginwithnoname said:
** Objective 1**
title:
to read some additional values such as AGE and FULL_40 and output them.
suggested implementation:
add in some other properties corresponding to AGE and FULL_40 values, populate these in the read function, parse them in the parse_data function, then output them at line 325 of the ds2784_battery.c file. Yes there will be lots of repetition, but the code is easily and quick to modify.
ideal implementation:
write a new app that outputs these but also outputs the status_reg value too. We can then use this to determine if and when our batteries go into "learning" mode. More below.
Click to expand...
Click to collapse
rather than doing it at line 325, wouldnt it make more sense to modify lines 103-118:
PHP:
unsigned n;
mutex_lock(&battery_log_lock);
seq_printf(sf, "timestamp mV mA avg mA uAh dC %% src mode reg full\n");
for (n = battery_log_tail; n != battery_log_head; n = (n + 1) & BATTERY_LOG_MASK) {
struct battery_status *s = battery_log + n;
seq_printf(sf, "%9d %5d %6d %6d %8d %4d %3d %s %s 0x%02x %d\n",
s->timestamp, s->voltage_uV / 1000,
s->current_uA / 1000, s->current_avg_uA / 1000,
s->charge_uAh, s->temp_C,
s->percentage,
battery_source[s->charge_source],
battery_mode[s->charge_mode],
s->status_reg, s->battery_full);
}
mutex_unlock(&battery_log_lock);
return 0;
how easy would it be to just add on to this? i suck bad a code and talk out my arse, barely enough to see what's going on. i dont even know where to come up with
seq_printf(sf, "%9d %5d %6d %6d %8d %4d %3d %s %s 0x%02x %d\n",
which seems like where the actual data is coming from for each parameter being output. cant we just add our get_full40, scalar, etc onto that output string?
theloginwithnoname said:
code-level:
1) modify struct battery_status, adding:
Code:
u16 age;
u16 full_40;
etc, with any other interesting ones too. Might as well grab all of them and output so we can hand-pick the ones that are useful.
2) from line 244 in parse_data, add something like:
Code:
s->age = raw[DS2784_REG_AGE_SCALAR];
etc
may have to convert from hex.
Click to expand...
Click to collapse
I think the parse function is line 320, i dont see anything at line 244. so the parse and then pr_info is what is output when we see our dmesg log? for the simplest and quickest result, i think adding registers to the batt_log i posted up above would be the path of least resistence, no? (ignore if i make no sense, i'm noob with code).
then objective 2 would be writing back to the register...
this driver also talks about read/write the bits, which i dont know if we looked thru this one yet. its definitely part of all this i think.
cm-kernel / drivers / w1 / w1.h
http://github.com/CyanogenMod/cm-kernel/blob/android-msm-2.6.34/drivers/w1/w1.h
at least i hope it is relevant!
theloginwithnoname said:
yeah - how best to do this? what about gtalk? <mylogin>@gmail.com if you are OK with that. Will be online in two mins
Click to expand...
Click to collapse
Sorry man, I had a hell of a day at work and didn't even get on IM at all or check back on this thread. My IM is my name at gmail.com, so tomorrow I will make sure to be online if you want. I am PST. Have you tried following the guide here: http://wiki.cyanogenmod.com/index.p...m_source#Install_development_support_packages? I assume so. Where do you get stuck at?
Definitely looking forward to this
Something like the Desire one would be nice too,
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
I've been wanting to check the "health" of my battery like how they do on Thinkpads forever.
It shows values like "Design Capacity" & "Full Charge Capacity" to let you see how much your battery is worn. Sometimes I feel like my battery life issues is not with Cyanogen but with the actual battery itself (bought it 2 months used so i dunno how well the other person treated it, came in box and had all original stuff (sealed) tho no scratches!! ) I was thinking to buy another battery and see but might as well get a Seidio then if that's the case
So in that case, the main battery should be "1400 mAh" battery but maybe it's current charge capacity is only 1000mAh so that's why my talk/usage time is low.
Not sure this helps, but just to spark some thinking i grabbed this from page 25 of the spec sheet for the ds2784.
http://datasheets.maxim-ic.com/en/ds/DS2784.pdf
STATUS REGISTER FORMAT
The status register contains bits that report the device status. All bits are set internally. The CHGTF, AEF, SEF, and LEARNF bits are read only. The UVF and PORF bits can be cleared by writing a zero to the bit locations.
PHP:
ADDRESS 01h
BIT 7 - CHGTF
BIT 6 - AEF
BIT 5 - SEF
BIT 4 - LEARNF
BIT 3 - X
BIT 2 - UVF
BIT 1 - PORF
BIT 0 - X
CHGTF—Charge-Termination Flag. CHGTF is set to indicate that the voltage and average current register values have persisted above the VCHG and below the IMIN thresholds sufficiently long to detect a fully charged condition. CHGTF is cleared when RARC is less than 90%. CHGTF is read only.
AEF—Active-Empty Flag. AEF is set to indicate that the battery is at or below the active-empty point. AEF is set when the voltage register value is less than the VAE threshold. AEF is cleared when RARC is greater than 5%. AEF is read only.
Click to expand...
Click to collapse
good spot Rog - I might need to decompile all the tech info and add it as a technical analysis post here. Will be a few days before I can do this though.
I'll post these links here for completeness, it kinda wraps everything up with examples of everything. You really should read when you have a sec.
http://pdfserv.maxim-ic.com/en/an/AN3584.pdf
http://pdfserv.maxim-ic.com/en/an/AN131.pdf
http://pdfserv.maxim-ic.com/en/an/AN4043.pdf
http://pdfserv.maxim-ic.com/en/an/AN3463.pdf
been looking over the code, and i'm pretty sure for phase #1, step #1, to grab the info we need we'd have to add the following line 51, line 224-226, and line 325 and 331:
we need to define the additional variable:
PHP:
48 int current_avg_uA;
49 int charge_uAh;
51 int full40_uAh /*This variable added*/
We need to parse the additional data (MSB and LSB for full40):
PHP:
221 /* RAAC is in units of 1.6mAh */
222 s->charge_uAh = ((raw[DS2784_REG_RAAC_MSB] << 8) |
223 raw[DS2784_REG_RAAC_LSB]) * 1600;
224 /* full40 has same conversion units of 1.6mAh */
225 s->full40_uAh = ((raw[DS2784_REG_FULL_40_MSB] << 8) |
226 raw[DS2784_REG_FULL_40_LSB]) * 1600;
and finally, simplest way i see it is to just add it to the dmesg log (at least right now, later we can do whatever with it):
PHP:
ds2784_parse_data(di->raw, &di->status);
324
325 pr_info("batt: %3d%%, %d mV, %d mA (%d avg), %d.%d C, %d mAh, %d full40 mAh\n",
326 di->status.percentage,
327 di->status.voltage_uV / 1000, di->status.current_uA / 1000,
328 di->status.current_avg_uA / 1000,
329 di->status.temp_C / 10, di->status.temp_C % 10,
330 di->status.charge_uAh / 1000,
331 di->status.full40_uAh / 1000); /*added this output to dmesg log*/
332 return 0;
333 }
the only thing i am not sure on is the conversion units for full40, i cant find it yet. we could just not convert it at all and end up with a large raw value, but that would mess up the dmesg log readability. for above i just assumed it was the same conversion as charge capacity (very well could be the same).
next i'll attempt the same for age scalar.
besides, there is another way to find the full40 value, its the one that your dmesg log jumps to when you hit full charge, but you have to be at +40 C temperature (that's what full40 is, its the max our battery can hold at 40C since the higher the temp, the more capacity our battery can hold). in my case, my getfull40 is 1369 mAh.
should i post this in the battery thread and see if pershoot would compile a test kernel for me? i'd try this out.
EDIT: i'm almost positive this will work, so i'll see how to add in age scalar before posting it in the other thread for pershoot.
I'm a very new Java developer, having started learning it last month specifically for this project. I have fifteen years of development experience, but it has almost all been web related (html, JS, JQuery, ColdFusion, etc), so this is a major paradigm change that I'm having trouble wrapping my head around.
Anyway, I'm attempting to create a movie-based live wallpaper to sell on the app store. I have a 15 second mpg (or 450 png frames) derived from some rendered artwork I did, the bottom 35% of which has motion (the rest remains relatively static). I'd like code flexible enough to handle future animations as well, though, as I just rediscovered Vue and may do other videos where the entire frame has motion.
My initial attempts are detailed on my Stack Overflow question at: (link removed due to forum rules; findable with the title: How do you create a video live wallpaper).
That post, in short, boils down to having tried these different approaches:
Load frames into a bitmap array and display on canvas in loop; excellent FPS but hundreds of MB of memory use.
Load frames into byteArray as jpgs and decode during display; clocking in at only 10 FPS at 60% cpu usage on powerful hardware, but with good memory usage.
Load tiled sprite with all 450 frames in AndEngine as a texture and display; went oom while trying to allocate 200 MB of memory.
AndEngine again. Load tiled jpg with 10 frames into sprite, load next tiled jpg into a second sprite, every 400ms hide one sprite and display the second, then load the upcoming jpg into the hidden sprite; rinse, repeat. Attempting to decode in a makeshift buffer, essentially.
I feel like maybe method 4 has promise and am including the code I'm using below. However, every time the sprites are swapped out the screen freezes for as long as a second or two. I tried adding timers between every line of code to determine what's taking so much time, but they almost always come back with barely a millisecond or two taken, leaving me confused about where the freeze is occurring. But I don't understand AndEngine well yet (or even Java) so I may be doing something completely boneheaded.
I'd welcome any thoughts, whether a refinement on an existing method or a completely new idea. I've had a horrible time trying to find tutorials on doing this, and questions I find here and on SO generally don't offer much encouragement. I just want to get this thing finished so I can concentrate on the heart of this project: the art. Thanks!
As an aside, how much work would this be (ie: how much would it cost) for an experienced developer to create a template for me? I wouldn't mind paying a small amount for something I can keep using with future animations.
Code:
public void onCreateResources(
OnCreateResourcesCallback pOnCreateResourcesCallback)
throws Exception {
scene = new Scene();
initializePreferences();
// Water
waterTexture = new BitmapTextureAtlas(this.getTextureManager(), 1200, 950, TextureOptions.BILINEAR);
waterRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(waterTexture, this.getAssets(), "testten1.jpg", 0, 0, 2, 5);
waterTexture.load();
waterTexture2 = new BitmapTextureAtlas(this.getTextureManager(), 1200, 950, TextureOptions.BILINEAR);
waterRegion2 = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(waterTexture2, this.getAssets(), "testten2.jpg", 0, 0, 2, 5);
waterTexture2.load();
water = new AnimatedSprite(0, 0, waterRegion, this.getVertexBufferObjectManager());
water2 = new AnimatedSprite(0, 0, waterRegion2, this.getVertexBufferObjectManager());
scene.attachChild(water);
water.animate(40);
mHandler.postDelayed(mUpdateDisplay, 400);
}
private final Handler mHandler = new Handler();
private final Runnable mUpdateDisplay = new Runnable() {
[user=439709]@override[/user]
public void run() {
changeWater();
}
};
public void changeWater() {
mHandler.removeCallbacks(mUpdateDisplay);
mHandler.postDelayed(mUpdateDisplay, 400);
if (curWaterTexture == 1) {
Log.w("General", "Changed texture to 2 with resource: " + curWaterResource);
curWaterTexture = 2;
scene.attachChild(water2);
water2.animate(40);
scene.detachChild(water);
curWaterResource = curWaterResource + 1;
if (curWaterResource > 4) curWaterResource = 1;
String resourceName = "testten" + curWaterResource + ".jpg";
waterRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(waterTexture, this.getAssets(), resourceName, 0, 0, 2, 5);
waterTexture.load();
water = new AnimatedSprite(0, 0, waterRegion, this.getVertexBufferObjectManager());
} else {
Log.w("General", "Changed texture to 1 with resource: " + curWaterResource);
curWaterTexture = 1;
scene.attachChild(water);
water.animate(40);
scene.detachChild(water2);
curWaterResource = curWaterResource + 1;
if (curWaterResource > 4) curWaterResource = 1;
String resourceName = "testten" + curWaterResource + ".jpg";
waterRegion2 = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(waterTexture2, this.getAssets(), resourceName, 0, 0, 2, 5);
waterTexture2.load();
water2 = new AnimatedSprite(0, 0, waterRegion2, this.getVertexBufferObjectManager());
}
}
I would like to develop and app, which has the main functionality to show a 2D chart. There are others and settings, but this is the main.
Existing similar applications aren't using technologies as how it should and they are releasing apps with to few features or they are draining battery like crazy. This I would like to improve it.
This is for web / desktop
View attachment 2397770
Here are a few sentences from my experience, please correct me if I am wrong!
Many-many of implementations are using SDK and 2D graphics. They draw the whole screen every time. Just sere how your battery drained in 1-2 hours! - some really bad implementation they can drain in 3 minutes, I will show later. One exception is: Metatrader 4: it use NDK and OpenGL, Hey pay me, because I am advertising you!
I think the SDK code (.class files) it need to e compiled at runtime execution by virtual machine, which takes CPU usage.
NDK is compiled only one => will use less CPU => will drain less batter as the SDK version.
If this is correct, than it should move more code to NDK if is possible. Not sure about JNI calls overhead!
NDK huuuuge advantage: it will allow to use the phone max available memory ( 1.5GB was last time) instead of SDK max allowed value: 256MB ( in my case, but some devices allow only 24Mb for SDK apps)
If you don't touch this chart than nothing changes, if you set the "Live" option, than the last "candle" will change. The candles are those Red & Green rectangles with the line in upper side and down side with meaning of the open, high, low, close prices. - it is related to business logic, but this special bars can have those 2 lines, which are important. The border of the 1pixel black around the red-green rectangles are for visual effects only. To save battery can be omitted.
(The background text and logos are just for advertisements, nobody cares, not really needed for the user for his actions)
As you can see there is a toolbar, and there are maybe other components too, but when the user want to see highest amount of data than will rotate to landscape and there should be given a Full Screen (in portrait not by default)
I have started the development with a component for rendering with OpenGL ES 2.0.
The UI is in SDK , the renderer there is called, but the method implementation calls the native methods via JNI. The business logic, rendering implementation are all in NDK, which is a native shared library.
Not sure why I started with OpenGL, to have some cool effects, who want to drain his battery faster? or I tough if is faster than will consume less battery? - maybe faster drains, but more: 100 mA from GPU for 0.01 seconds rendering is the same as 10 mA for 0.1 rendering at CPU.
Here I am not sure if I am saving energy. Tell me your opinion!
So I have started learning OpenGL ES 2.0 and all what I saw in tutorials it was triangle triangle triangle, but in this chart there is no triangle, but rectangle, or rectangle+lines or just lines with set width or many triangles?
Here is a cool candle, I would like to see this, but I know the gradients will burn battery.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Here is a bit magnified and you can see how I am thinking:
but can't decide. Because I haven't enough experience, don't know the benchmark results. I would like to see a tear down and expected results:
GL_Lines + glLineWidth
GL_triangles
GL_triangle_strip
As the first option with GL_lines:
A candle would be 1x small line from the Low and High price drawn first. Lets say with 5 pixel width to have room for gradient too, if needed. In worse case only 1 pixel, as how they are using others now.
The candle body: the red/green rectangle with has the info of Open/Close price can be another GL_Lines with 50 pixel width - for example.
Will be gradient or not that would depends on user settings. Not sure how is possible to draw black 1-2 pixel of border for candle body in this case - if the user has that settings.
Seconds option with triangles:
2x triangle can make a square.
There is a square as the small line and there is another one the larger square : the candle body.
The triangle strip case:
if only one GL_triangle_strip:
bottomline: 4 vertices
body other 4
upper line 4 vertices
or small line 4x vertices
+
other 4x vertices , so 2x GL_triangle_strip
I made this:
The first thing it was:
Code:
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY)
It is a rectangle with 2x triangle and a line with width.
The line has less vertices of course, but in this chart is expected to have 50- 200 bars maximum. Minimum 10-20.
What is needed is that cross at mouse location: that dashed line and the numbers ( price ) on the right and some other texts in bottom. X, Y coordinates in text.
Please post your experience, benchmarks, opinion.
Hi matheszabi,
ok, your question was rather compheresive . So right way to find solution is rather complicated too.
I woudn't choose solution according to differences between JDK / NDK to same function calls of OpenGL ES 2.0
According to my experience, performance (and power consumption) is almost the same.
GLOBAL aproach: I suggest
1) you create your application in Java - use JDK versions - creating native function for just few draw calls is, imho, hard compared what you get
2) if your application is NativeActivity
- use direct calls - be prepared for differences between devices, proper creation of surface, .... but it's faster
- subclass Native Activity and use JAVA as well
3) not using OpenGL ES directly at all - i suggest trying layout and buttons / images inside of it, i saw 200 control buttons on 1 screen and it ran perfectly. And layout is movable by 1 command - offset. I suppose, this is completely written in native code anyway. You just get drawing interface in JAVA.
Now, to OPENGL ES itself (JAVA or NDK)
cons:
- OPENGL is 3D interface so pixel perfect drawing is something which is not supported by itself. (note: opengl has pixel / texel center at 0.5 not at 0.0/1.0)
- you need pixel perfect draw - boxes you draw must be perfectly aligned to screen pixels - othewise you get blurry results
- you might not need texturing - thats PLUS, otherwise drawing pixel perfect opengl suraces is "pain in the ..." - viz. texel interpolation and drawing a pixel checker aligned with screen pixels is real nightmare and it differs on each device (I tried )
- pixel perfect with mipmaps - awful again
- alpha blending (when you have something which is transparent) - you will need sorting to draw it properly
- will you need font ? oh my ...
- NO EMULATOR - will need to test each device if it's working properly (not every, at least each vendor)
to consider:
writing vertex/fragment shader in a world with 3500 (number of opengles 2.0 devices according google) suitable devices/compilers/android versions ... ehm
pluses:
- you draw exactly what you want
- use of fragment shader (alhough i suggest using gradient textures instead)
- i suggest draw primitives in vertex buffers (indexed triangles or triangle strips). Not one box by one - compose all in one array and draw it by one draw call. Doubling points in strips can help you
- instancing is not supported) but there is way surpassing this (preparing buffers with)
- i don't recommend using lines with width definition - each implementation draws this differently - and it's equal to drawing lit cylinder
- in native activity loop - handling if you need redraw - it's difficult
I would try normal android GUI first
pluses:
- you get pixel perfect draw, with / without bitmaps, images, gradients ....
- i suppose its fast enough
- no sorting needed
- redraws will be invoked when something changes
- translation / clipping will be handled internally
- no need to care about device !!! that's big plus
cons:
- zoom will be problematic
- rotations as well (but i suppose you don't need them)
note to power consupmption - both OpenGL :
just swaping screen buffers 30 per sec will deplete most of devices within 2-3 hours. But of course, doing it so only when needed is doable
But I might be wrong so best way is to decide by yourself and, of course, try it and see.
If you have qustions about drawing through ES, i'll post some samples of pixel perfect draw (from my gui)
Good luck, post your decision, and if you have some results, post them too! will be very interesting.
PS.
Petr Sovis said:
Hi matheszabi,
ok, your question was rather compheresive . So right way to find solution is rather complicated too.
I woudn't choose solution according to differences between JDK / NDK to same function calls of OpenGL ES 2.0
According to my experience, performance (and power consumption) is almost the same.
GLOBAL aproach: I suggest
1) you create your application in Java - use JDK versions - creating native function for just few draw calls is, imho, hard compared what you get
2) if your application is NativeActivity
- use direct calls - be prepared for differences between devices, proper creation of surface, .... but it's faster
- subclass Native Activity and use JAVA as well
3) not using OpenGL ES directly at all - i suggest trying layout and buttons / images inside of it, i saw 200 control buttons on 1 screen and it ran perfectly. And layout is movable by 1 command - offset. I suppose, this is completely written in native code anyway. You just get drawing interface in JAVA.
Now, to OPENGL ES itself (JAVA or NDK)
cons:
- OPENGL is 3D interface so pixel perfect drawing is something which is not supported by itself. (note: opengl has pixel / texel center at 0.5 not at 0.0/1.0)
- you need pixel perfect draw - boxes you draw must be perfectly aligned to screen pixels - othewise you get blurry results
- you might not need texturing - thats PLUS, otherwise drawing pixel perfect opengl suraces is "pain in the ..." - viz. texel interpolation and drawing a pixel checker aligned with screen pixels is real nightmare and it differs on each device (I tried )
- pixel perfect with mipmaps - awful again
- alpha blending (when you have something which is transparent) - you will need sorting to draw it properly
- will you need font ? oh my ...
- NO EMULATOR - will need to test each device if it's working properly (not every, at least each vendor)
to consider:
writing vertex/fragment shader in a world with 3500 (number of opengles 2.0 devices according google) suitable devices/compilers/android versions ... ehm
pluses:
- you draw exactly what you want
- use of fragment shader (alhough i suggest using gradient textures instead)
- i suggest draw primitives in vertex buffers (indexed triangles or triangle strips). Not one box by one - compose all in one array and draw it by one draw call. Doubling points in strips can help you
- instancing is not supported) but there is way surpassing this (preparing buffers with)
- i don't recommend using lines with width definition - each implementation draws this differently - and it's equal to drawing lit cylinder
- in native activity loop - handling if you need redraw - it's difficult
I would try normal android GUI first
pluses:
- you get pixel perfect draw, with / without bitmaps, images, gradients ....
- i suppose its fast enough
- no sorting needed
- redraws will be invoked when something changes
- translation / clipping will be handled internally
- no need to care about device !!! that's big plus
cons:
- zoom will be problematic
- rotations as well (but i suppose you don't need them)
note to power consupmption - both OpenGL :
just swaping screen buffers 30 per sec will deplete most of devices within 2-3 hours. But of course, doing it so only when needed is doable
But I might be wrong so best way is to decide by yourself and, of course, try it and see.
If you have qustions about drawing through ES, i'll post some samples of pixel perfect draw (from my gui)
Good luck, post your decision, and if you have some results, post them too! will be very interesting.
PS.
Click to expand...
Click to collapse
Hello thanks for sharing your idea experience.
I have asked in other forum a similar question.
It was a response than the GPU has optimised methods so it will have less power consumption
Also he likes to draw the whole frame not only a part - I'm case of my optimisation
Also I have asked an opengl expert and he told me to use the ortho instead of perspective projection. He has right.
Now I don't have bliry results anymore but is pixel perfect!
For benchmark I made 100 candles : 100 line + 200 triangles.
I have calculated how much is the wigth and the height for the surface => how much space can have a candle and used the matrix transformations and render it.
A nice surprise the fist time it took 18 milliseconds but after that only took 5-6 millisec the. Sdk->ndk->opengl-> SDK steps.
That is very good result on MY trash device. But I think it has a trick: the ndk gives order to render to GPU and it will return. So in those 5-6 milliseconds will start to work the GPU for who knows how much....
Note: audio , video , sensor intensive projects should be developed on real devices not at emulators.
With my method the problem is starting with text drawing and leak of knowledge.
Vbo or texture... Not sure which one but if a native 2D can do it than I can me too.
Cairo as rendering 2d engine is a bit big to include in android.
I still think the ndk is the correct place. Also is isn't so easy to watch the engine code as a decompiled SDK code
Ok! you chose your path - good for you!
18/5-6 ms is just for draw (200 triangles+100 lines) ?, or whole frame time ? Can you tell me the the device you are testing your app on ?
Note: Ortho, i didn't mean to advice perspective transform, ortho is still 3d, and pixel perfect - wait for texturing/text drawing, but you'll manage!
Just few tips to font rendering:
bitmap fonts: I can't add links so google: angelcode bmfont
font bitmap creator: google: angelcode bmfont
+ sample: google: nehe 2d_texture_font
freetype implementation - it's possible to compile it with ndk - i use it and it's simple
google: freetype
and code for starters: google: nehe freetype_fonts_in_opengl
Cheers
P.
Petr Sovis said:
Ok! you chose your path - good for you!
18/5-6 ms is just for draw (200 triangles+100 lines) ?, or whole frame time ? Can you tell me the the device you are testing your app on ?
Note: Ortho, i didn't mean to advice perspective transform, ortho is still 3d, and pixel perfect - wait for texturing/text drawing, but you'll manage!
Just few tips to font rendering:
bitmap fonts: I can't add links so google: angelcode bmfont
font bitmap creator: google: angelcode bmfont
+ sample: google: nehe 2d_texture_font
freetype implementation - it's possible to compile it with ndk - i use it and it's simple
google: freetype
and code for starters: google: nehe freetype_fonts_in_opengl
Cheers
P.
Click to expand...
Click to collapse
My phone is a THL W8S. has FHD resolution
It had a mixed layout, but better I show you:
I have misscalculated the lines positions but for now doesn't matter.
The GLSurface takes a considerable amount of the screen space and that is counted.
On a Samsung Note 10" - at least 1 year old device, lower resolution, but better CPU + GPU it is a lot less this numbers.
My device is a trash (by far not for gamming), I told you:
Hi,
ok, as I understand, the time is just for drawing 200 tris + 100 lines - ok that seems a "little to much" for that.
Besides, your device is not trash at all
I don't know if I can share my examples - but scene from app I released week ago draws 50KTris per frame with some heavy shaders (normal mapping + specular ligting from 2 light sources) and draws text over it + particles + GUI (my ndk gles2.0 engine) and I suppose it will run over 30 FPS on your device (its PoverVR 540 or something) (google play: "Asteroid Hunters" by me)
So, can you post fragment of your drawing code ? maybe there something not really right ?
P
Petr Sovis said:
So, can you post fragment of your drawing code ? maybe there something not really right ?
P
Click to expand...
Click to collapse
I will post, but for me this is good enough others are drawing in 200-2000 milliseconds
The SDK part:
Code:
@Override
public void onDrawFrame(GL10 gl) {
long start = System.currentTimeMillis();
LibJNIWrapper.rendererOnDrawFrame();
long end = System.currentTimeMillis();
//Log.e("Renderer", "onDrawFrame() took: "+ (end-start)+" millisec (1e-6)");
}
The related NDK part:
Code:
void renderer_on_draw_frame() //4
{
LOGE("renderer_on_draw_frame");
//copy
static float grey;
grey += 0.01f;
if (grey > 1.0f) {
grey = 0.0f;
}
glClearColor(grey, grey, grey, 1.0f);
checkGlError("glClearColor");
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
checkGlError("glClear");
int i;
for (i = 0; i < CANDLES_COUNT; i++) {
//LOGE("chartengine rendering i= %d",i);
renderLine((candles[i].coloredSingleLine));
renderRectangle((candles[i].coloredSingleRectangle));
}
glFlush();
}
line rendering:
Code:
void renderLine(ColoredSingleLine* pColoredSingleLine) {
if (pColoredSingleLine == NULL) {
return;
}
//matrixTranslateM(mvpMatrix, rndX, rndY, 0);
//LOGE("###renderLine pColoredSingleLine %p\n",pColoredSingleLine);
glUseProgram(pColoredSingleLine->programColoredLine.program);
checkGlError("Line: glUseProgram");
// Enable a handle to the triangle vertices
glEnableVertexAttribArray(pColoredSingleLine->programColoredLine.a_position_location);
checkGlError("Line: glEnableVertexAttribArray");
// Prepare the triangle coordinate data
glVertexAttribPointer(pColoredSingleLine->programColoredLine.a_position_location, pColoredSingleLine->lineData.COORDS_PER_VERTEX_LINE, GL_FLOAT, GL_FALSE,
pColoredSingleLine->lineData.vertexStride, pColoredSingleLine->lineData.vertices);
checkGlError("Line: glVertexAttribPointer");
// Set color for drawing the triangles
glUniform4fv(pColoredSingleLine->programColoredLine.u_color_location, 1, pColoredSingleLine->lineData.color_rgba);
checkGlError("Line: glUniform4fv");
// Apply the projection and view transformation
glUniformMatrix4fv(pColoredSingleLine->programColoredLine.u_mvp_matrix_location, 1, GL_FALSE, pColoredSingleLine->lineData.mvpMatrix);
checkGlError("Line: glUniformMatrix4fv");
glLineWidth(pColoredSingleLine->lineData.lineWidth);
// Draw the line
glDrawArrays(GL_LINES, 0, pColoredSingleLine->lineData.vertexCount); // (GLenum mode, GLint first, GLsizei count);
checkGlError("Line: glDrawArrays"); // GL_INVALID_ENUM
//GL_INVALID_ENUM is generated if mode is not an accepted value.
//GL_INVALID_ENUM is generated if type is not GL_UNSIGNED_BYTE or GL_UNSIGNED_SHORT.
GLint error = glGetError();
if (error == GL_OUT_OF_MEMORY) {
LOGE("Out of Video memory error...congrats...is your device a stone ?");
}
// Disable vertex array
glDisableVertexAttribArray(pColoredSingleLine->programColoredLine.a_position_location);
}
and the rectangle:
Code:
void renderRectangle(ColoredSingleRectangle* pColoredSingleRectangle) {
if (pColoredSingleRectangle == NULL) {
return;
}
//matrixTranslateM(mvpMatrix, rndX, rndY, 0);
glUseProgram(pColoredSingleRectangle->programColoredRectangle.program);
checkGlError("Rectangle: glUseProgram");
// Enable a handle to the triangle vertices
glEnableVertexAttribArray(pColoredSingleRectangle->programColoredRectangle.a_position_location);
checkGlError("Rectangle: glEnableVertexAttribArray");
// Prepare the triangle coordinate data
glVertexAttribPointer(pColoredSingleRectangle->programColoredRectangle.a_position_location, pColoredSingleRectangle->rectangleData.COORDS_PER_VERTEX_RECTANGLE, GL_FLOAT, GL_FALSE,
pColoredSingleRectangle->rectangleData.vertexStride, pColoredSingleRectangle->rectangleData.vertices);
checkGlError("Rectangle: glVertexAttribPointer");
// Set color for drawing the triangles
glUniform4fv(pColoredSingleRectangle->programColoredRectangle.u_color_location, 1, pColoredSingleRectangle->rectangleData.color_rgba);
checkGlError("Rectangle: glUniform4fv");
// Apply the projection and view transformation
glUniformMatrix4fv(pColoredSingleRectangle->programColoredRectangle.u_mvp_matrix_location, 1, GL_FALSE, pColoredSingleRectangle->rectangleData.mvpMatrix);
checkGlError("Rectangle: glUniformMatrix4fv");
// Draw the square
glDrawElements(GL_TRIANGLES, NELEMS(pColoredSingleRectangle->rectangleData.drawOrder), GL_UNSIGNED_SHORT, pColoredSingleRectangle->rectangleData.drawOrder); // GL_INVALID_ENUM on Galaxy note
checkGlError("Rectangle: glDrawElements"); // GL_INVALID_ENUM
//GL_INVALID_ENUM is generated if mode is not an accepted value.
//GL_INVALID_ENUM is generated if type is not GL_UNSIGNED_BYTE or GL_UNSIGNED_SHORT.
GLint error = glGetError();
if (error == GL_OUT_OF_MEMORY) {
LOGE("Out of Video memory error...congrats...is your device a stone ?");
}
// Disable vertex array
glDisableVertexAttribArray(pColoredSingleRectangle->programColoredRectangle.a_position_location);
}
At any benchmarks my fps is bellow 12, while other devices has 30 or 50 fps. Believe me not my device has the best CPU + GPU by far:
some output from on old code:
Code:
printGLString("Version", GL_VERSION);
printGLString("Vendor", GL_VENDOR);
printGLString("Renderer", GL_RENDERER);
printGLString("Extensions", GL_EXTENSIONS);
....
void printGLString(const char *name, GLenum s) {
const char *v = (const char *) glGetString(s);
LOGE("GL %s = %s\n", name, v);
}
// ### GT-N8000 ### Galaxy note 10" - GL Renderer = Mali-400 MP
// GL_EXT_debug_marker
// GL_OES_texture_npot
// GL_OES_compressed_ETC1_RGB8_texture
// GL_OES_standard_derivatives
// GL_OES_EGL_image
// GL_OES_depth24
// GL_ARM_rgba8
// GL_ARM_mali_shader_binary
// GL_OES_depth_texture
// GL_OES_packed_depth_stencil
// GL_EXT_texture_format_BGRA8888
// GL_EXT_blend_minmax
// GL_OES_EGL_image_external
// GL_OES_EGL_sync
// GL_OES_rgb8_rgba8
// GL_EXT_multisampled_render_to_texture
// GL_EXT_discard_framebuffer
// ### THL V8S - GL Renderer = PowerVR SGX 544MP
// GL_EXT_debug_marker
// GL_OES_rgb8_rgba8
// GL_OES_depth24
// GL_OES_vertex_half_float
// GL_OES_texture_float
// GL_OES_texture_half_float
// GL_OES_element_index_uint
// GL_OES_mapbuffer
// GL_OES_fragment_precision_high
// GL_OES_compressed_ETC1_RGB8_texture
// GL_OES_EGL_image
// GL_OES_EGL_image_external
// GL_OES_required_internalformat
// GL_OES_depth_texture
// GL_OES_get_program_binary
// GL_OES_packed_depth_stencil
// GL_OES_standard_derivatives
// GL_OES_vertex_array_object
// GL_OES_egl_sync
// GL_OES_texture_npot
// GL_EXT_multi_draw_arrays
// GL_EXT_texture_format_BGRA8888
// GL_EXT_discard_framebuffer
// GL_EXT_shader_texture_lod
// GL_IMG_shader_binary
// GL_IMG_texture_compression_pvrtc
// GL_IMG_texture_compression_pvrtc2
// GL_IMG_texture_npot
// GL_IMG_texture_format_BGRA8888
// GL_IMG_read_format
// GL_IMG_program_binary
// GL_IMG_uniform_buffer_object
// GL_IMG_multisampled_render_to_texture
materials
OK!
i know why it's so slow, you practically draw something 300x per frame and it doesn't really matter if it has 2 trinagles or 300 per one call.
300x setup shader per frame is almost a limit for slower(not slow) devices.
Main issues:
1) do not ever call glGetError when not debugging/running debug build - it makes pipeline stall (pipeline stops and waits until all commands are executed)
2) since you have 100 lines - and using for all of them same program, why not to group them in one array ?
2 solutions
-----------------
A)
= you are not using vertex buffers - so
1) create temporary memory and pre-transform all lines/triangles into one array - will be much faster
2) setup shader once + set uniforms
3) setup attributes - start of temporary array you created (every call - believe me, it will be faster, good practice is create array on stack, but beware of overflow - but for 300 lines is practically impossible)
3) call one draw call for all lines/triangles at once
B) even faster solution (fake instancing) - this is really fast
= create vertex buffer with data (and now create this as real VBO !)
- and not with only 1 instance of line, but with reasonable count - for instance 300 (fake instancing) - 300x line data repeated,
- in tex.x,y (for instance) - set index 0.299 -> x = (float(index % 256) / 256.0f ) y = ( (index & (~255)) / 256.0 ) - using lowp vec2 inTex; attribute
= in shader:
- create uniform array with coordinates for instance uniform mediump vec3 positions[300];
- in vertex part - something like this
gl_Position.xyz = inPosition.xyz + positions[(int) ((inTex.x * 256.0) + (inTex.y * 65536.0)) ];
1) use shader
2) fill array with positions and set it to uniform
3) set attributes
4) draw - and according to situation change count of elements drawn
if you need draw more than 300 lines, enlarge array OR just do more calls this time this is getting efficient
But i suppose 1st solution will be more than enough.
Cheers.
P.
Petr Sovis said:
OK!
i know why it's so slow, you practically draw something 300x per frame and it doesn't really matter if it has 2 trinagles or 300 per one call.
300x setup shader per frame is almost a limit for slower(not slow) devices.
Main issues:
1) do not ever call glGetError when not debugging/running debug build - it makes pipeline stall (pipeline stops and waits until all commands are executed)
2) since you have 100 lines - and using for all of them same program, why not to group them in one array ?
2 solutions
-----------------
A)
= you are not using vertex buffers - so
1) create temporary memory and pre-transform all lines/triangles into one array - will be much faster
2) setup shader once + set uniforms
3) setup attributes - start of temporary array you created (every call - believe me, it will be faster, good practice is create array on stack, but beware of overflow - but for 300 lines is practically impossible)
3) call one draw call for all lines/triangles at once
B) even faster solution (fake instancing) - this is really fast
= create vertex buffer with data (and now create this as real VBO !)
- and not with only 1 instance of line, but with reasonable count - for instance 300 (fake instancing) - 300x line data repeated,
- in tex.x,y (for instance) - set index 0.299 -> x = (float(index % 256) / 256.0f ) y = ( (index & (~255)) / 256.0 ) - using lowp vec2 inTex; attribute
= in shader:
- create uniform array with coordinates for instance uniform mediump vec3 positions[300];
- in vertex part - something like this
gl_Position.xyz = inPosition.xyz + positions[(int) ((inTex.x * 256.0) + (inTex.y * 65536.0)) ];
1) use shader
2) fill array with positions and set it to uniform
3) set attributes
4) draw - and according to situation change count of elements drawn
if you need draw more than 300 lines, enlarge array OR just do more calls this time this is getting efficient
But i suppose 1st solution will be more than enough.
Cheers.
P.
Click to expand...
Click to collapse
Thanks
When I wrote I saw the glerror maybe it will slow down a bit.
Since I am coming from an object oriented development environment it was designed on that way...
The candle: line + triangle can have other data too. Maybe need to keep elsewhere the data...
The last candle line and rectangle and his color can change almost at each draw method: just 1 of the 4 params will nort change.
When the last candle is closed a new one need to be staeted
In this case needs to. Shift to left all other candles. Maybe for this I am keeping in separate methods.
I thought the shader setup is done in other part at least there I am getting the pointer to they. On surface changed/ created - I am not at PC now.
Text with price + time scale should be with a texture to a rectangle?
I will reply inline:
matheszabi said:
Thanks
When I wrote I saw the glerror maybe it will slow down a bit.
Since I am coming from an object oriented development environment it was designed on that way...
Click to expand...
Click to collapse
Object development has nothing to do with this , glGetError is NOT a function to retrieve error status from GL functions, its for debugging purposes only. Its commonly used as: (simple form)
#ifdef _DEBUG
#define CHECKGL(x) x; assert(glGetError() == GL_NO_ERROR)
#else
#define CHECKGL(x) x
#endif
CHECKGL( glUniform4f(.... .) );
or still very fast
#define CHECKGL(x) x; if (globalDebugGL) { assert(glGetError() == GL_NO_ERROR); }
matheszabi said:
Thanks
The candle: line + triangle can have other data too. Maybe need to keep elsewhere the data...
The last candle line and rectangle and his color can change almost at each draw method: just 1 of the 4 params will nort change.
When the last candle is closed a new one need to be staeted
In this case needs to. Shift to left all other candles. Maybe for this I am keeping in separate methods.
Click to expand...
Click to collapse
Again - preparing something to vertex buffer is 100x faster than calling gluseProgram, gluniform and then draw call.
Different values per "candle": you can change (per candle) color, position, tex coords, and another values - to max 16 vec4 attributes per vertex in vertex buffer.
just for your imagination what does exactly glUniform: it recompiles and rebuilds shader with new values. It's not fast at all. So drawing 2 triangles with new shader setup (different uniform values) is not very smart. You have only 800-1000 such operations per frame tops. New card can handle much more. Look for term "draw call batching" to learn more. Unity's main feature.
Just imagine, even chip in your phone can easily draw 20 textured MTris per sec and you draw just few thousands and it's sweating.
Very nice article about GLES 2.0 from apple - google for "OpenGL ES Design Guidelines" most of it is true on android as well
matheszabi said:
Thanks
I thought the shader setup is done in other part at least there I am getting the pointer to they. On surface changed/ created - I am not at PC now.
Text with price + time scale should be with a texture to a rectangle?
Click to expand...
Click to collapse
That differs according to your situation.
- Is price/time always same ? (texture)
- it's changing per frame, (prerender texture)
- it's changing per "candle" ? - I posted articles about text in gl apps in the last post.
I thing you can choose your way !
Cheers
P.
Thanks for answer.
Petr Sovis said:
That differs according to your situation.
- Is price/time always same ? (texture)
- it's changing per frame, (prerender texture)
- it's changing per "candle" ? - I posted articles about text in gl apps in the last post.
Click to expand...
Click to collapse
Price/time is the same until: the user press a button, than will change the time ( From To values) and collecting data will result a min price and a max price. So the price probably will change at that button event, but not all the time.
Also the last candle price value is "moving" at least the close value, but an move the min or max value too, which can be the min or the max of the whole chart, on those rare situations need to change the coordinate system too. Can be used here a trick as it is changing and it will add +20% so what not need to change on each tick (frame)
233528246055
matheszabi said:
Thanks for answer.
Price/time is the same until: the user press a button, than will change the time ( From To values) and collecting data will result a min price and a max price. So the price probably will change at that button event, but not all the time.
Also the last candle price value is "moving" at least the close value, but an move the min or max value too, which can be the min or the max of the whole chart, on those rare situations need to change the coordinate system too. Can be used here a trick as it is changing and it will add +20% so what not need to change on each tick (frame)
Click to expand...
Click to collapse
I would definitely use rendering text technique I already posted. Its very fast (when implemented properly) and you can "print" whatever you want.
One of the following
bitmap fonts: (more content preparations - you need to prepare texture for each font)
-------------------
font bitmap creator: google: angelcode bmfont
+ sample: google: "nehe 2d_texture_font"
freetype implementation: (easier use - free type can generate font you want - also very fast)
-------------------------------------
it's possible to compile it with ndk - i use it and it's simple
google: freetype
and code for starters: google: "nehe freetype_fonts_in_opengl"
Cheers
P.
1. Java Swing Overview
Java uses a graphical user interface (GUI) to facilitate interaction between a user and a program. Java's Swing toolkit includes a number of classes to support GUI design. For example, component classes such as buttons, menus, lists, and text boxes, and container classes such as windows and panels.
The javax.swing package provides more powerful classes for designing GUIs. The UML class diagrams of some classes in the java.awt and javax.swing packages are as follows:
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
➢When learning GUI programming, you must have a good grasp of two concepts: container classes and component classes.
➢The JComponent class in the javax.swing package is a direct subclass of the Container class in the java.awt package and an indirect subclass of the Component class in the java.awt package. To learn GUI programming is to master some important subclasses of the Component class and their usage methods.
➢The following are the basics that are often mentioned in GUI programming.
(1) Java refers to an object created by a subclass or indirect subclass of a Component class as a component.
(2) In Java, an object created by a subclass or indirect subclass of a container is called a container.
(3) You can add components to the container. The Container class provides a public method: add(). A container can call this method to add a component to the container.
(4) The container invokes the removeAll() method to remove all components in the container. Invoke the remove(Component c) method to remove the component specified by parameter c in the container.
(5) Note that the container itself is also a component, so one container can be added to another container to achieve nesting of containers.
(6) Each time a new component is added or removed from the container, the container should call the validate() method to ensure that the components in the container can be displayed correctly.
2. Window
➢An instance of the JFrame class provided by Java is an underlying container, commonly referred to as a window. Other components must be added to the underlying container so that information can be exchanged with the operating system through this underlying container.
➢The JFrame class is an indirect subclass of the Container class. When you need a window, you can create an object using JFrame or its subclasses.
➢A window is also a container to which you can add components.
➢ It should be noted that windows are added by the system to the display screen by default, so adding one window to another container is not allowed.
2.1 Common JFrame Methods
(1) Construction method
1
2
3JFrame()//Create an untitled window.
JFrame(String s)// Create a window with the title s.
(2) Common methods
1public void setBounds(int a,int b,int width,int height)//
The initial position of the setting window is (a, b), that is, a pixel from the left side of the screen and b pixels from the upper side of the screen. The width of the window is width and the height is height.
1public void setSize(int width,int height)//
Sets the size of the window.
1public void setLocation(int x,int y)//
Sets the position of the window. The default position is (0, 0).
1public void setLocation(int x,int y)//
Specifies whether the window is visible. By default, the window is invisible.
1public void setResizable(boolean b)//
Specifies whether the window size can be adjusted. By default, the window size can be adjusted.
1public void dispose()//
Undoes the current window and releases the resources used by the current window.
1public void setExtendedState(int state)//
Sets the extended status of the window.
1public void setExtendedState(int state)//
This method is used to set how the program will handle after you click the close icon in the upper right corner of a window. For example: EXIT_ON_CLOSE
1public void setExtendedState(int state)//
Set the layout manager for this container.
1public Component add(Component comp)//
Appends the specified component to the end of this container.
1public void setMenuBar(MenuBar mb)//
Sets the menu bar of this frame to the specified menu bar.
1public void validate()//
Using the validate method causes the container to rearrange its subcomponents again. When you modify the subcomponents of this container (Add or remove components in the container, or change layout-related information) , the above method should be called.
The following example creates two windows using JFrame:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import javax.swing.*;
import java.awt.*;
public class Example1 {
public static void main(String[] args) {
JFrame window1 = new JFrame("First Window ");
JFrame window2 = new JFrame("Second window ");
Container con = window1.getContentPane();
con.setBackground(Color.red);// Set the color of the window
window1.setBounds(60, 100, 188, 108);// Set the position and size of the window on the screen.
window2.setBounds(260, 100, 188, 108);
window1.setVisible(true);
window1.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);// Release the current window.
window2.setVisible(true);
window2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// Exit the program.
}
}
2.2 Menu Bar, Menu, Menu Item
(1) Menu bar
JMenubar, a subclass of the JComponent class, is responsible for creating the menu bar, and the JFrame class has a method for placing the menu bar in a window: setJMenuBar(JMenuBar bar); this method adds the menu bar to the top of the window.
The method for constructing the JMenuBar class of the menu bar is as follows:
1
2JMenuBar ();
JMenuBar Mbar = new JMenuBar ()
(2)Menu
JMenu, a subclass of the JComponent class, is responsible for creating menus.
Method of constructing the menu JMenu class:
1
2
3JMenu();
JMenu(String s);
JMenu m = new JMenu();
Common methods:
1
2
3public void add(JMenuItem item)// Adds a menu item specified by the item parameter to a menu.
public JMenuItem getItem(int n)// Gets the menu options at the specified index.
public int getItemCount()//Gets the number of menu options.
(3) Menu items
The JMenuItem class, a subclass of the JComponent class, creates menu items. The main methods of the JMenuItem class are as follows:
1
2
3JMenuItem(String s)// Constructs a menu item with a title.
JMenuItem(String text, Icon icon) // Construct menu items with titles and icons
public void setAccelerator(KeyStroke keyStroke)// Set shortcut keys for menu items
Example 2 Use the JFrame subclass to create a window with a menu in the main method:
WindowMenu.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42import javax.swing.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
public class WindowMenu extends JFrame {
JMenuBar menubar; //Declare a menu bar menubar
JMenu menu, subMenu; //Declare two menus menu,subMenu
JMenuItem itemLiterature, itemCooking; //Declare two menu items itemLiterature, itemCooking
public WindowMenu() {
}
public WindowMenu(String s, int x, int y, int w, int h) { // constructors, creating windows
init(s);// Window initialization
setLocation(x, y);// Position of the window
setSize(w, h);// Window size
setVisible(true);// Window Visible
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);// Actions after closing the window
}
void init(String s) {
setTitle(s); // Set the title of the window
menubar = new JMenuBar(); // Creates a menu bar menubar.
menu = new JMenu("Menu"); // Create a menu called Menu
subMenu = new JMenu("Sports Topics"); // Create a menu called Sports Topics
// Icons on the menu
// Using the icon class Icon, declare an icon, and then create its subclass ImageIcon class Create an icon
//Icon icon = new ImageIcon("a.gif");
itemLiterature = new JMenuItem("Literary Topics", new ImageIcon("a.gif")); // Create a menu itemLiterature with a title and icon
itemCooking = new JMenuItem("Cooking Topics ", new ImageIcon("b.gif")); // Create a menu itemCooking with a title and icon
itemLiterature.setAccelerator(KeyStroke.getKeyStroke('A')); // Set shortcut keys for the itemLiterature menu item
itemCooking.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_MASK)); // Setting shortcut keys for the itemCooking menu item
menu.add(itemLiterature);
menu.addSeparator(); // Add dividers between menus
menu.add(itemCooking);
menu.add(subMenu);
subMenu.add(new JMenuItem("soccer", new ImageIcon("c.gif")));
subMenu.add(new JMenuItem("basketball", new ImageIcon("d.gif")));
menubar.add(menu); // Add a menu to a menu bar
setJMenuBar(menubar); // Place the menu bar in the window
}
}
Example2.java
1
2
3
4
5public class Example2 {
public static void main(String[] args) {
WindowMenu win=new WindowMenu("Window with Menu",20,30,200,190);
}
}
3. Common Components and Layout
You can decompile a component in the command line window to view the attributes and common methods of the component. For example:
1C:\>javap javax.swing.JComponent
For example:
3.1 Common Components
1. Text box: A text box created by JTextField, a subclass of JComponent, allows users to enter a single line of text in the text box.
1
2
3
4
5
6// Construction Methods
JTextField();
JTextField(int columns);
// Common Methods
public String getText();
public void setText(String t);
2. Text area: A text area is created by JTexArea, a subclass of JComponent, to allow users to enter multiple lines of text in the text area.
1
2
3
4
5
6// Construction Methods
JTextArea();
JTextArea(int rows, int columns);
// Common Methods
public String getText();
public void setText(String t);
3. Buttons: Used by the JButton class, a subclass of JComponent, to create buttons that allow users to click buttons.
1
2
3
4
5// Construction Methods
JButton();
JButton(String text);
// Common Methods
public void addActionListener(ActionListener l);
4. Tags: The JLabel class, a subclass of JComponent, creates tags and provides prompt information for users.
1
2
3
4
5
6
7// Construction Methods
JLabel();
JLabel(String text);
JLabel(Icon image);
// Common Methods
public String getText();
public void setText(String t);
5. Selection box: The JCheckBox class, a subclass of JComponent, is used to create selection boxes that provide users with multiple choices.
1
2
3
4
5
6// Construction Methods
JCheckBox();
JCheckBox(String text);
// Common Methods
public void addItemListener(ItemListener l);
public void addActionListener(ActionListener l);
6. Radio button: Used by the JRadioButton class, a subclass of JComponent, to create a single selection box.
1
2
3
4
5// Construction Methods
JRadioButton();
JRadioButton(String text);
// Common Methods
public void addItemListener(ItemListener l);
7. Drop-down list: Used by the JComponent subclass JComboBox class to create a drop-down list.
1
2
3
4
5
6
7// Construction Methods
JComboBox();
JComboBox(Object[] items)
// Common Methods
public void addItemListener(ItemListener l);
public Object getSelectedItem();
public int getSelectedIndex();
8. Password box: The JPasswordField subclass of JComponent creates a password box. The default response character of the password box is *.
1
2
3
4
5
6
7
8
9// Construction Methods
JPasswordField();
JPasswordField(int columns);
// Common Methods
public String getText();
public void setText(String t);
public void setEchoChar(char c)// Use this method to reset the echo character.
public char[] getPassword()//This method returns the actual password.
The following example shows some common components:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43import javax.swing.*;
import java.awt.*;
class ComponentInWindow extends JFrame {
JCheckBox checkBox1, checkBox2; // Declare two check boxes
JRadioButton radioM, radioF; // Declare two radio boxes
ButtonGroup group; // Declare a button group
JComboBox<String> comboBox; // drop-down list
public ComponentInWindow() { // construction method
init(); // Calling the init() method
setVisible(true); // Window Visible
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
void init() {
setLayout(new FlowLayout()); // Set the layout manager for this container
comboBox = new JComboBox<>(); // Create a drop-down list
// Create two check boxes
checkBox1 = new JCheckBox("Love Java");
checkBox2 = new JCheckBox("I like data structures.");
group = new ButtonGroup();
radioM = new JRadioButton("male");
radioF = new JRadioButton("female");
group.add(radioM);
group.add(radioF); // Single-choice is supported only by grouping.
add(checkBox1);
add(checkBox2);
add(radioM);
add(radioF);
comboBox.addItem("Object-oriented");
comboBox.addItem("Minimum Spanning Tree(MST)");
add(comboBox);
}
}
public class Example9_3 {
public static void main(String[] args) {
ComponentInWindow win = new ComponentInWindow();
win.setBounds(100, 100, 450, 260);
win.setTitle("Common Components");
}
}
3.2 Common Containers
JComponent is a subclass of Container. Therefore, all components created by JComponent subclasses are containers. Containers are often used to add components. The JFrame is the bottom container, and the containers mentioned in this section are traditionally called intermediate containers, which must be added to the bottom container to function.
1. JPanel panel:
1
2
3
4
5// Construction Methods
JPanel();
// For example: JPanel p = new JPanel();
// Common Methods
public void add();
Create a panel using JPanel, add components to the panel, and add the panel to other containers. The default layout for the JPanel panel is the FlowLayout layout.
2. JTabbedPane Tab Pane
You can use the JTabbedPane container as an intermediate container.
When a user adds a component to the JTabbedPane container, the JTabbedPane container automatically assigns a tab to the component. That is, a tab corresponds to a component.
The components corresponding to each tab are stacked in the JTabbedPane container. When a user clicks a tab, the JTabbedPane container displays the components corresponding to the tab.
The tabs are by default at the top of the JTabbedPane container, arranged from left to right.
The JTabbedPane container can use:
add(String text,Component c);
Method to add component c to the JTabbedPane container and specify that the text prompt for the tab corresponding to component c is text.
3. Scroll PaneJscrollPane:
You can add only one component to the scroll pane. You can place a component in a scroll pane and view the component through the scroll bar.
JTextArea does not come with a scroll bar, so you need to place the text area in a scrolling pane.
For example:
1JScrollPane scroll = new JScrollPane(new JTextArea());
4. Split Pane JSplitPane
A split pane is a container that is divided into two parts. There are two types of split panes: horizontal split and vertical split.
Horizontal split panes are divided into left and right parts by a split line. A component is placed on the left and a component is placed on the right. The split line can be moved horizontally. Splitting a pane vertically uses a split line to divide the pane into two parts, with one component on top and one component on bottom. The split line moves vertically.
/* Two Common Construction Methods of JSplitPane*/
JSplitPane(int a,Component b,Component c)
// Parameter a is set to the static constant HORIZONTAL SPLIT or VERTICAL _SPLIT of JSplitPane to determine whether to split horizontally or vertically.
// The last two parameters determine which component to place.
JSplitPane(int a, boolean b,Component c,Component d)
// Parameter a is set to the static constant HORIZONTAL SPLIT or VERTICAL_ SPLIT of JSplitPane to determine whether to split horizontally or vertically.
// Parameter b determines whether the component changes continuously as the split line moves (true is continuous).
5. JLayeredPane Layered Pane
If components added to a container often need to deal with overlap, consider adding components to the hierarchical pane. The hierarchical pane is divided into five layers. The hierarchical pane uses add(Jcomponent com, int layer).
Add component com and specify the layer where com is located. The value of layer is a class constant in the JLayeredPane class.
DEFAULT LAYER、PALETTE I AYER、MODAL LAYER、POPUP I AYER、DRAG LAYER。
DEFAULT_LAYER is the bottom layer. If components added to DEFAULT_LAYER overlap with components of other layers, they are obscured by other components. The DRAG Layer layer is the top layer. If many components are added to the layering pane, you can place a component on the DRAG_Layer layer when you move the component. In this way, the component is not blocked by other components when you move the component. If components that are added to the same layer overlap, the components that are added later obscure the components that are added earlier. The layered pane invokes public void setLayer(Component c, int layer) to reset the layer where component c resides, and invokes public int getLayer(Component c) to obtain the number of layers where component c resides.
3.3 Common Layouts
➢ When adding a component to a container, you want to control the location of the component in the container, which requires learning about layout design.
➢ We will introduce the FlowLayout, BorderLayout, CardLayout, GridLayout layout classes in the java.awt package and the BoxLayout layout classes in the java.swing.border package.
➢ Containers can be used in the following ways:
setLayout(layout object);
to set your own layout and control the placement of components in the container.
1. FlowLayout Layout: is the default layout for JPanel-type containers.
1) Create a layout object: FlowLayout flow=new FlowLayout();
2) Container con uses layout objects: == con.setLayout(flow); ==
3) The con can use the add method provided by the Container class to add components to the container sequentially.
The FlowLayout layout object invokes the corresponding method to reset the alignment mode of the layout.
For example: public void setAlignment(int align)
2. BorderLayout Layout:
The BorderLayout layout is the default layout for Window containers.
If the container con in the BorderLayout layout is used, you can use the add method to add component b to the central area: con.add(b, BorderLayout.CENTER).
or con.add(BorderLayour.CENTER, b);
3. CardLayout Layout: The general steps to use CardLayout are as follows:
1) Create the CardLayout object CardLayout card=new CardLayout();
2) Set the layout con.setLayout(card) for the container.
3) The container calls add(String s, Component b) to add component b to the container, and gives the code s for displaying the component.
4) The layout object card uses the show() method provided by the CardLayout class to display the component code s in the container con:
card.show(con,s);
Containers using CardLayout can hold multiple components, but in reality, containers can only select one of these components at a time to display, like a stack of "playing cards" that can only display the most at a time. As in the previous one, the components shown will take up all the container space, in sequence.
4. GridLayout Layout:
The GridLayout layout strategy divides the container into several rows by several columns, and the components are located in these small grids. The general steps for the GridLayout Layout Editor are as follows:
1) Create a layout object and specify the number of rows (m) and columns for grid division.
GridLayout grid=new new GridLayout(10, 8);
2) Use the container of the GridLayout layout to call the add (Component c) method to add component c to the container.
5. null layout
You can set the layout of a container to null (empty layout). An empty layout container can accurately locate the position and size of components in the container. The setBounds(int a, int b, int width, int height) method is a method owned by all components. A component can call this method to set its size and position in the container.
For example, p is a container,
p.setLayout(null);
Set the layout of p to an empty layout.
Adding a component c to an empty layout container p requires two steps.
First, container p uses the add(c) method to add a component, and then component c calls the setBounds(int a, int b, int width, int height) method to set the location and size of the component in container p. Each component is a rectangular structure, and parameters a and b in the method are location coordinates of an upper left corner of the component c in the container p, that is, the component is a pixel from the left side of the container p, and b pixels from the upper side of the container p, width, and height is the width and height of component c.
The following example adds a tab pane in the center of the window with a grid layout panel and an empty layout panel:
Example.java
1
2
3
4
5public class Example {
public static void main(String[] args) {
new ShowLayout();
}
}
ShowLayout.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26import java.awt.*;
import javax.swing.*;
public class ShowLayout extends JFrame {
PanelGridLayout panelGridLayout; // Panel for Grid Layout
PanelNullLayout panelNull; // Panel with empty layout
JTabbedPane p; // Tab Pane
ShowLayout() {
panelGridLayout = new PanelGridLayout();//Create a panel for a grid layout
panelNull = new PanelNullLayout();//Create a panel with an empty layout
p = new JTabbedPane();//Create a tab for selecting which panel layout
p.add("Panel for Grid Layout", panelGridLayout);// Adding a Grid Layout Board to the Tab Pane
p.add("Panel with empty layout", panelNull);// Add an empty layout panel to the Tab Pane
add(p, BorderLayout.CENTER);// Adding a Tab Pane to a ShowLayout Panel
// Add Buttons to Large Panels
add(new JButton("Form is BorderLayout Layout"), BorderLayout.NORTH);
add(new JButton("South"), BorderLayout.SOUTH);
add(new JButton("West"), BorderLayout.WEST);
add(new JButton("East"), BorderLayout.EAST);
setBounds(10, 10, 570, 390);
setVisible(true);// Window Visible
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
validate();
}
}
PanelGridLayout.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20import java.awt.*;
import javax.swing.*;
public class PanelGridLayout extends JPanel {// Mesh cloth panel
PanelGridLayout() {
GridLayout grid = new GridLayout(12, 12); // Grid Layout
setLayout(grid);
Label label[][] = new Label[12][12];
for (int i = 0; i < 12; i++) {
for (int j = 0; j < 12; j++) {
label[j] = new Label();
if ((i + j) % 2 == 0)
label[j].setBackground(Color.black);
else
label[j].setBackground(Color.white);
add(label[j]);// Add a small mesh to the panel
}
}
}
}
PanelNullLayout.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import javax.swing.*;
public class PanelNullLayout extends JPanel {// Blank Page Layout
JButton button;// “OK” button
JTextField text;// text box
PanelNullLayout() {
setLayout(null); // Empty Layout
button = new JButton("OK "); // Create “OK” button
text = new JTextField();//Create Text Box
add(text); // Add a text box to the PanelNullLayout panel
add(button); // Add a button to the PanelNullLayout panel
text.setBounds(100, 30, 90, 30); // Set Text Box Size
button.setBounds(190, 30, 66, 30); // Set Button Size
}
}
The following figure shows the running screenshot.
6. BoxLayout Layout
The class (static) method createHorizontalBox() of the Box class obtains a row-type box container.
Use the class (static) method createVerticalBox() of the Box class to obtain a column-type box container.
To control the distance between components in a box layout container, you need to use either horizontal or vertical braces.
In the following example, there are two column-type box containers, boxVOne, boxVTwo, and one row-type box container, boxH. Add boxVOne, boxVTwo to boxH and add horizontal braces between them.
Example.java
1
2
3
4
5
6
7
8public class Example {
public static void main(String[] args) {
WindowBoxLayout win = new WindowBoxLayout();
win.setBounds(100, 100, 310, 260);
win.setTitle("Nested Box Layout Container");
}
}
WindowBoxLayout .java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27import javax.swing.*;
public class WindowBoxLayout extends JFrame {
Box boxH; // Row Box
Box boxVOne, boxVTwo; // column box
public WindowBoxLayout() {
setLayout(new java.awt.FlowLayout());
init();
setVisible(true);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
void init() {
boxH = Box.createHorizontalBox();//Get a row box container
boxVOne = Box.createVerticalBox();//Get a column-type box container
boxVTwo = Box.createVerticalBox();//Get a column-type box container
boxVOne.add(new JLabel("姓名:"));// Adding Name Labels to Column-Type Box Containers
boxVOne.add(new JLabel("职业:"));// Add occupational labels to column box containers
boxVTwo.add(new JTextField(10));// Add the name text box for column-shaped box containers.
boxVTwo.add(new JTextField(10));// Add career input box for column-shaped box containers
boxH.add(boxVOne);
boxH.add(Box.createHorizontalStrut(10));
boxH.add(boxVTwo);
add(boxH);
}
}
The command output is as follows:
By Codeplus.
Original link: https://blog.csdn.net/m0_46518461/article/details/115876407