Accessing full resolution photo of Lumia 1020 - Windows Phone 8 Development and Hacking

I thought it'll be nice to post this here, in any event that it's needed in future. So there was an app called phriz.be in Nokia Collection that was released recently, it was the first third party app that have the ability to upload full resolution photo. I gave it a try on reverse engineering it, hoping that it was an undocumented API and not a new capability.
Unfortunately, there's simply no way to do it unless the device is interop unlocked which is rather useless on Nokia Lumia 1020 when the only WP8 device that's unlocked is Samsung Ativ S.
Deploying an app with such capability will give you the following:
{
"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"
}
Anyway.
<Capability Name="ID_CAP_MEDIALIB_PHOTO_FULL" />
Code:
private struct <getPhotos>d__2a : IAsyncStateMachine
Code:
this.<>4__this.IsPhotoLoading = true;
this.<>4__this.PhotoList.Clear();
taskAwaiter = this.<>4__this._deviceService.GetPhotos(this.<>4__this._currentAlbumName, 0, StateData.RecentMaxCount, true).GetAwaiter();
System.Collections.Generic.List<PhotoDisplay> arg_C9_0 = taskAwaiter.GetResult();
taskAwaiter = default(TaskAwaiter<System.Collections.Generic.List<PhotoDisplay>>);
System.Collections.Generic.List<PhotoDisplay> list = arg_C9_0;
this.<list>5__2b = list;
System.Collections.Generic.List<PhotoDisplay>.Enumerator enumerator = this.<list>5__2b.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
PhotoDisplay current = enumerator.Current;
this.<>4__this.PhotoList.Add(current);
}
}
finally
{
if (flag)
{
((System.IDisposable)enumerator).Dispose();
}
}
this.<>4__this.TryShowMoreLink();
this.<>4__this.RaisePropertyChanged("IsPhotoAvailable");
Code:
// Phrizbe.ViewModel.MainViewModel
private readonly IDeviceService<PhotoDisplay, DocumentDisplay, AlbumDisplay, TransferLogItem, ActivityLogItem, ActivityLog> _deviceService;
Code:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
namespace Phrizbe.Lib.Model
{
public interface IDeviceService<P, D, A, TL, ALI, AL>
{
void AddActivityLogItem(string deviceName, long deviceId, long deviceOSPlatform, string emailAddress, ALI logItem);
void AddApprovedDevice(string deviceName);
bool AddDownloadBackgroundTransfer(ALI ali, Target sender);
string AddUploadBackgroundTransfer(TransferItemDetail detail);
void ClearCachedPhotos();
void CreateTransferThumbnail(byte[] bytes, string fileName);
List<AL> GetActivityLogs();
Task<ObservableCollection<string>> GetAlbumNames();
Task<List<A>> GetAlbums();
Task<P> GetAlbumThumbnail(string albumName);
string GetCleanFileName(string fileName);
Device GetDeviceInfo();
Task<List<D>> GetDocuments(bool useCache);
Task<P> GetPhoto(string albumName, string fileName, bool useCache);
Task<List<P>> GetPhotos(string albumName, int startIndex, int returnCount, bool useCache);
Task<LocationReport> GetLocation(bool useCache);
bool IsApprovedDevice(string deviceName);
bool IsNetworkAvailable();
bool IsThumbnailDownloaded(long transferId);
long LoadDeviceId();
void RemoveActivityLogItem(string deviceName, ALI logItem);
void RemoveBackgroundTransfer(string requestId, bool forceRemove);
void RemoveActivityLog(string deviceName);
void SaveDeviceId(long deviceId);
Task<bool> SaveFile(ReceiveDataResponse response, string fileName, ActivityContentTypes contentType);
void SaveLogData();
Task<bool> SavePreviewFile(ReceiveDataResponse response, string fileName, long transferId);
void UpdateActivityLogNewCount(string deviceName, long deviceId, int count, bool saveLogData);
}
}
Task<P> GetPhoto(string albumName, string fileName, bool useCache);

Related

[Q] Commands for Hardware controll

Hello,
i just starting with C# dev. and now i search the "commands" or the "way" to controll the Mobile phone.
i use a HTC Leo WinMo 6.5.3 and VB2010 or VB2008. the first little "hello world" app runs great, bit i want to controll the Hardware, like enable or disable the Camera LED or something link that.
other phones like the Sonim xp3 have a "Developer Readme" and list the complet commands for hardware access.
i search for the HTC Leo the same, but i found only the "Microsoft WinMo Dev." side with the standart commands.
give it a "Dev HowTo" from HTC for Leo or something like that?
thank you
I'd go with a bit of IDA (or PE Explorer, if it can show DLL entrypoints) and try disassembling the camera.dll or HTCCameraUtility.dll files from OEMDrivers/camera packages. I bet there will be one entrypoint named something like EnableLight and DisableLight.
As OndraSter said, disassembling files is the only way to learn how to control hardware.
CreateFileW + DeviceIoControl are typically used to control leds (excluding camera's led (at least on X1, TP2, etc)).
All leds can be controlled directly using "I2C1:" device or manufacter's wrapper (on SE X1 there is "LED1:" device).
Kay, i installed the PE Explorer, i open the HTCCameraUtility.dll and the Camera.exe from the windows dir, but in both cases the PE Explorer disable the disassembling function. i try a other exe file and this works fine with pe explorer...
and now? what means "IDA" ?
IDA stands for Interactive Disassembler, which is ... disassembler of dll/exe/... for many platforms (win32, wince arm etc supported in demo version).
When I get home (tomorrow, on saturday, or the day after on sunday), I will help you with that, but I dont own any LED-flash integrated device, so I'll have to do a lot more work .
@ultrashot
I didn't realize it might be on I2C, thanks for pointing that out
- Andrew
Attention, as usual: All code below is rather device-specific. If you don't know what you do, don't use it!
Probably i2c_ functions are the same on all htc devices (at least I hope so).
On Kovsky I use these functions to control i2c devices directly:
*.h:
Code:
#define I2CMgr_WriteMultiBytes_Ioctl 0x80100024
#define I2CMgr_WriteByte_Ioctl 0x8010000C
#define I2CMgr_ReadMultiBytes_Ioctl 0x80100028
#pragma pack(1)
typedef struct
{
unsigned char device_id;
unsigned char smth1;
unsigned short address;
unsigned int inBufLength;
unsigned char *inBuf;
}I2C;
typedef struct
{
unsigned char device_id;
unsigned char address;
unsigned short data;
}I2C2;
#pragma pack()
.cpp:
Code:
int i2c_write(int device_id, int address, unsigned char *buf, int buf_size)
{
HANDLE device=CreateFileW(L"I2C1:",0xC0000000,0,0,3,0,0);
I2C i2c;
i2c.device_id=device_id;
i2c.address=address;
i2c.smth1=1;
i2c.inBufLength=buf_size;
i2c.inBuf=buf;
for (int x=0;x<3;x++)
{
if (DeviceIoControl(device,I2CMgr_WriteMultiBytes_Ioctl,&i2c,sizeof(I2C),NULL,NULL,NULL,NULL))
{
CloseHandle(device);
return S_OK;
}
DeviceIoControl(device,0x80100014,&i2c,sizeof(I2C),NULL,NULL,NULL,NULL);
Sleep(0xA);
}
CloseHandle(device);
return -1;
};
int i2c_writewbyte(int device_id, int address, unsigned short data)
{
HANDLE device=CreateFileW(L"I2C1:",0xC0000000,0,0,3,0,0);
I2C2 i2c;
i2c.device_id=device_id;
i2c.address=address;
i2c.data=data;
for (int x=0;x<3;x++)
{
if (DeviceIoControl(device,I2CMgr_WriteByte_Ioctl,&i2c,sizeof(I2C2),NULL,NULL,NULL,NULL))
{
CloseHandle(device);
return S_OK;
}
DeviceIoControl(device,0x80100014,&i2c,sizeof(I2C2),NULL,NULL,NULL,NULL);
Sleep(0xA);
}
CloseHandle(device);
return -1;
};
int i2c_read(int device_id, int address, unsigned char *outBuf, int outBufLength)
{
HANDLE device=CreateFileW(L"I2C1:",0xC0000000,0,0,3,0,0);
I2C i2c;
i2c.device_id=device_id;
i2c.address=address;
i2c.smth1=1;
i2c.inBufLength=outBufLength;
i2c.inBuf=outBuf;
for (int x=0;x<3;x++)
{
if (DeviceIoControl(device,I2CMgr_ReadMultiBytes_Ioctl,&i2c,sizeof(I2C),outBuf,outBufLength,NULL,NULL))
{
CloseHandle(device);
return S_OK;
}
DeviceIoControl(device,0x80100014,&i2c,sizeof(I2C),NULL,NULL,NULL,NULL);
Sleep(0xA);
}
CloseHandle(device);
return -1;
};
For example, I get info from Kovsky's lightsensor this way. You shouldn't use this code on other devices.
Code:
int lightsensor_read()
{
unsigned char buf[2]={0,0};
int res=i2c_read(MICROP_KLT, MICROP_KLT_ID_LIGHT_SENSOR_KOVS, buf, sizeof(buf));
if (res!=S_OK)
return -1;
int r3=buf[0];
int r2=buf[1];
r3=r3&3;
r2=r2|(r3<<8);
return r2;
};
Full code here: http://forum.xda-developers.com/showpost.php?p=7121525&postcount=231
Debugging on PPC and...
Stress test your application with UAEDT = Unrecoverable Application Error Debugging Tool.
UAE Debugging Tool (UAEDT) is a debug monitor, stress tester etc. for developers of Windows Mobile software. A great free alternative to IDA Pro: assembler/disassembler though of course not as advanced
Ultimate device/radio commander AT Commander :: use only if you know what you are doing it can brick your phone easily!!
{
"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"
}
[PC] ATCommander;
http://atcommander.com
The above link does not provide us with much information / links
Thus I searched some more and came up with;
http://atcommander.com/download/
Same page though not reachable via the first link. Anyway here you can download the latest .zip or .exe
Also do not forget to check this link;
http://atcommander.com/public/
Here some AT Commands reference links provided in a pdf file;
http://atcommander.com/download/AT_Command_Specification/
[PPC] ATCommander;
http://forum.xda-developers.com/showthread.php?t=375395
ChARMeD is a Windows Mobile / Pocket PC / Win CE (for ARM CPUs) Disassembler and Assembler
The name ChARMeD stands for:
Carolo's Hexadecimal ARM Editor and Disassembler
ARM Classic Processors
ARM Infocenter
Use all these applications with caution!!
o/~

[MOD/GUIDE] X-Recents

Hey Guys!
After a few requests I decided to share my X-Recents mod with you, so that other developers get the ability to add it to their Rom. This is just for Developers building Roms from Source! Also, medium skills on java coding are recommended!
What is X-Recents mod?
It's a mod improving the stock android recents, to make them more user-friendly and feature-rich. It was already implemented in my X-Bean Rom for i9000
Please note:
- you can use this for all ICS/JB Roms and for all devices
- just add me to the credits, if you want to use it, and notify me: [email protected]
- The swype FC Bug (occurs when swyping over the Button) still exists, to fix it just add try/catch blocks at all points that cause the FC it (use adb/logcat for analysis)
- If you like my work and want to support me, the Thanks & the Donate button are always appreciated!
Okay, so let's get started: You can find all files in: system/frameworks/base/packages/SystemUI/src/com/android/systemui/recent (in your working directory, or whereever you're SystemUI sourcecode is)
At first, we modify the RecentTasksLoader.java:
l.260: final int first = 1;
to : final int first = 0;
This loads the current activity into the recents list.. Only problem: The launcher shall not be shown in the recents list, so we have to make a exeption for it:
l.270: if (item != null) {
to : if (item != null && item.packageName!="com.cyanogenmod.trebuchet") { // You can add as many exeptions for apps as you want
Next point: Adding the Taskmanager button:
At first, open RecentsVerticalScrollView.java:
Insert this at line 95:
Code:
private void opentaskmanager() {
PackageManager pm = getContext().getPackageManager();
Intent appStartIntent = pm.getLaunchIntentForPackage("your.taskmanager.packagename.here");
if (null != appStartIntent)
{
getContext().startActivity(appStartIntent);
}
}
Remember to change the "your.taskmanager.packagename.here" to the package name of your taskmanager!
Now, wrap a try/catch block around the loop content in line 107:
Code:
for (int i = 0; i < mLinearLayout.getChildCount(); i++) {
try {
View v = mLinearLayout.getChildAt(i);
addToRecycledViews(v);
mAdapter.recycleView(v);
} catch (Exception ex) {
}
}
Also add a try here (I can't give you a line, because you inserted something before) :
Code:
for (int i = 0; i < mAdapter.getCount(); i++) {
try {
View old = null;
And a catch here:
Code:
calloutLine.setOnTouchListener(noOpListener);
mLinearLayout.addView(view);
} catch (Exception ex) {
}
}
To add the button, insert this:
Code:
Button bt_taskmanager = new Button(getContext());
bt_taskmanager.setText("Task Manager");
bt_taskmanager.setWidth(mLinearLayout.getWidth());
bt_taskmanager.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
opentaskmanager();
}
});
mLinearLayout.addView(bt_taskmanager);
Between these two lines:
setLayoutTransition(transitioner);
// Scroll to end after layout.
Okay, now we've got the button!
At last I want to give you something you can experiment with:
Code:
private void clearalltasks() {
final ActivityManager am = (ActivityManager)
mContext.getSystemService(Context.ACTIVITY_SERVICE);
final List<ActivityManager.RecentTaskInfo> recentTasks =
am.getRecentTasks(50, ActivityManager.RECENT_IGNORE_UNAVAILABLE);
for (int i = 0; i >= recentTasks.size(); i++) {
RecentTaskInfo item = recentTasks.get(i);
if (am != null && item!=null) {
try {
am.removeTask(item.persistentId, ActivityManager.REMOVE_TASK_KILL_PROCESS);
} catch (Exception ex) {
}
try {
am.killBackgroundProcesses(item.origActivity.getPackageName());
} catch (Exception ex) {
}
}
}
mLinearLayout.removeAllViews();
try {
update();
} catch (Exception ex) {
ex.printStackTrace();
}
}
This is my first attempt to add a clear all button.. Do with it what you want, I tried it and it works half-ways.. But not perfectly. I will add some more things later, for example how to add several more Buttons!
Screenshot:
{
"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"
}
Very good ...
Awesome post!

What is this, guys?

I installed CWM 6.0.3.6. But it show this message when I enter recovery. I tried to disregard. But it is annoying.
So what does mean that, guys?
{
"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"
}
It happens to me too... duuno why is that...
Have you tried to wipe dalvik cache? Sometimes FAIL's to me ._.
DevastatingTech said:
I installed CWM 6.0.3.6. But it show this message when I enter recovery. I tried to disregard. But it is annoying.
So what does mean that, guys?
Click to expand...
Click to collapse
found this on github
This is not a bug, it's a simple warning after some CM SELinux changes. Nothing should break by this message
Click to expand...
Click to collapse
and this on xda
_alp1ne said:
This happened to me also, but it has nothing to do with flashing or anything. It is best to ignore as it only means some file it is reading has no context.
Click to expand...
Click to collapse
and it started after flashing CWM 6.0.3.6 from CM10.1 thread ...(for me)
so basically we're safe....
is nothing to worry about, but , if you want to be 100% sure, add a durex
copy from CyanogenMod Forum:
it looks like the error is related to SELinux. But it seems safe to ignore.
------------------------------------------------------------------------------
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include "edify/expr.h"
#include "updater.h"
#include "install.h"
#include "minzip/Zip.h"
// Generated by the makefile, this function defines the
// RegisterDeviceExtensions() function, which calls all the
// registration functions for device-specific extensions.
#include "register.inc"
// Where in the package we expect to find the edify script to execute.
// (Note it's "updateR-script", not the older "update-script".)
#define SCRIPT_NAME "META-INF/com/google/android/updater-script"
struct selabel_handle *sehandle;
int main(int argc, char** argv) {
// Various things log information to stdout or stderr more or less
// at random. The log file makes more sense if buffering is
// turned off so things appear in the right order.
setbuf(stdout, NULL);
setbuf(stderr, NULL);
if (argc != 4) {
fprintf(stderr, "unexpected number of arguments (%d)\n", argc);
return 1;
}
char* version = argv[1];
if ((version[0] != '1' && version[0] != '2' && version[0] != '3') ||
version[1] != '\0') {
// We support version 1, 2, or 3.
fprintf(stderr, "wrong updater binary API; expected 1, 2, or 3; "
"got %s\n",
argv[1]);
return 2;
}
// Set up the pipe for sending commands back to the parent process.
int fd = atoi(argv[2]);
FILE* cmd_pipe = fdopen(fd, "wb");
setlinebuf(cmd_pipe);
// Extract the script from the package.
char* package_data = argv[3];
ZipArchive za;
int err;
err = mzOpenZipArchive(package_data, &za);
if (err != 0) {
fprintf(stderr, "failed to open package %s: %s\n",
package_data, strerror(err));
return 3;
}
const ZipEntry* script_entry = mzFindZipEntry(&za, SCRIPT_NAME);
if (script_entry == NULL) {
fprintf(stderr, "failed to find %s in %s\n", SCRIPT_NAME, package_data);
return 4;
}
char* script = malloc(script_entry->uncompLen+1);
if (!mzReadZipEntry(&za, script_entry, script, script_entry->uncompLen)) {
fprintf(stderr, "failed to read script from package\n");
return 5;
}
script[script_entry->uncompLen] = '\0';
// Configure edify's functions.
RegisterBuiltins();
RegisterInstallFunctions();
RegisterDeviceExtensions();
FinishRegistration();
// Parse the script.
Expr* root;
int error_count = 0;
yy_scan_string(script);
int error = yyparse(&root, &error_count);
if (error != 0 || error_count > 0) {
fprintf(stderr, "%d parse errors\n", error_count);
return 6;
}
struct selinux_opt seopts[] = {
{ SELABEL_OPT_PATH, "/file_contexts" }
};
sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1);
if (!sehandle) {
fprintf(stderr, "Warning: No file_contexts\n");
fprintf(cmd_pipe, "ui_print Warning: No file_contexts\n");
}
// Evaluate the parsed script.
UpdaterInfo updater_info;
updater_info.cmd_pipe = cmd_pipe;
updater_info.package_zip = &za;
updater_info.version = atoi(version);
State state;
state.cookie = &updater_info;
state.script = script;
state.errmsg = NULL;
char* result = Evaluate(&state, root);
if (result == NULL) {
if (state.errmsg == NULL) {
fprintf(stderr, "script aborted (no error message)\n");
fprintf(cmd_pipe, "ui_print script aborted (no error message)\n");
} else {
fprintf(stderr, "script aborted: %s\n", state.errmsg);
char* line = strtok(state.errmsg, "\n");
while (line) {
fprintf(cmd_pipe, "ui_print %s\n", line);
line = strtok(NULL, "\n");
}
fprintf(cmd_pipe, "ui_print\n");
}
free(state.errmsg);
return 7;
} else {
fprintf(stderr, "script result was [%s]\n", result);
free(result);
}
if (updater_info.package_zip) {
mzCloseZipArchive(updater_info.package_zip);
}
free(script);
return 0;
}
http://forum.cyanogenmod.com/topic/75956-cwm-on-nexus-4-after-43-update/
Okay guys, I will ignore this. Already, I hadn't any error. Thanks.

[Q] empty fields crast my app

Hello everyone,
I have start my first app, with this app, can you count your small change. And It works fine.
But, the fields must have a number, otherwise will my app cras.
Is there a solution to fix this? I mean if the user no number set on a row, that the app see this as a zero?
This looks my app:
{
"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"
}
this is the code what i use, it is maby not perfect but I am a beginner.
Code:
Button btn_optellen = (Button) findViewById(R.id.btn_optellen);
btn_optellen.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
double een = Double.valueOf(txt_001.getText().toString());
double twee = Double.valueOf(txt_002.getText().toString());
double total_een = een * 0.01 ;
double total_twee = twee * 0.02 ;
double totaal = total_een + total_twee;
tt_001.setText(String.format("= €%.2f", total_een ));
tt_002.setText(String.format("= €%.2f", total_twee ));
tt_totaal.setText(String.format("= €%.2f", totaal));
After you write the values to een and twee, you should do a check if they are null. And if that check is true, then set the value to 0.
So to be precise: do this check just before the line
double total_een = een * 0.01;
Click to expand...
Click to collapse
--------------------
Phone: Nexus 4
OS: rooted Lollipop LRX21T
Bootloader: unlocked
Recovery: TWRP 2.8.2.0
Thanxs for your answer.
I hope I don't ask to muts. But I am ana beginner. Can your show how I must write it?
Ok so i just researched a bit and found out that if the string to parse is invalid, then there is an exception thrown immediately. I thought that just null would be returned, so we need a different approach. But here os how to do it:
Code:
Button btn_optellen = (Button) findViewById(R.id.btn_optellen);
btn_optellen.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//we should initialize the two doubles to 0, so that we can just leave it like this in case of an error
double een = 0;
double twee = 0;
try {
een = Double.valueOf(txt_001.getText()); //btw, you dont need to call toString() after getText(). That method already returns a string so doing this would be redundant
} catch (Exception e) {} //nothing has to be done here, because the double has already been initialised to be 0
//same here
try {
twee = Double.valueOf(txt_002.getText());
} catch (Exception e) {}
//so now the two doubles are either set to 0 or to the value entered by the user, if it was a correct number
double total_een = een * 0.01 ;
double total_twee = twee * 0.02 ;
double totaal = total_een + total_twee;
tt_001.setText(String.format("= €%.2f", total_een ));
tt_002.setText(String.format("= €%.2f", total_twee ));
tt_totaal.setText(String.format("= €%.2f", totaal));
--------------------
Phone: Nexus 4
OS: rooted Lollipop LRX21T
Bootloader: unlocked
Recovery: TWRP 2.8.2.0
Very muth thanx, I am going try it out.

[Tutorial] Learn to parse HTML Pages on Android with JSoup

Hello,
I create that thread to offer you a tutorial learning you to parse HTML pages on Android by using the JSoup Library. You can also discover this tutorial in video on Youtube :
When you make Android applications, you can have to parse HTML data or HTML pages got from the Web. One of the most known solution to make that in Java is to use JSoup Library. Like said on the official website of JSoup : "It is a Java library for working with real-world HTML. It provides a very convenient API for extracting and manipulating data, using the best of DOM, CSS, and jquery-like methods."
JSoup can be used in Android applications and we're going to study how to parse an HTML Page on Android with JSoup.
First, you need to add the JSoup dependency in your Gradle build file :
Code:
compile 'org.jsoup:jsoup:1.10.1'
For our example, we are going to download the content of the SSaurel's Blog and display all the links of the main page. To download the content of a website, JSoup offers the connect method and then a get method. This last method works synchronously. So, we should call these methods in a separated Thread. Our application will have just a simple layout with a Button to launch the download of the website and a TextView to display the links.
It will have the following form :
Code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.ssaurel.jsouptut.MainActivity">
<Button
android:id="@+id/getBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Get website"
android:layout_marginTop="50dp"
android:layout_centerHorizontal="true"/>
<TextView
android:id="@+id/result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Result ..."
android:layout_centerHorizontal="true"
android:layout_marginTop="30dp"
android:layout_below="@id/getBtn"
android:textSize="17sp"/>
</RelativeLayout>
In the main Activity of the application, we are going to get instances of the Button and the TextView from our layout. Then, we set a click listener on the Button to start the download of the website when the user will click it.
In the getWebsite() method, we create a new Thread to download the content of the website. We use the connect() method of the Jsoup object to connect the application to the website, then we call the get() method to download the content. These calls return a Document object instance. We have to call the select() method of this instance with the query to get all the links of the content. This query returns an Elements instance and finally, we have just to iterate on the elements contained in this object to display the content of each link to the screen.
At the end of our separated Thread, we refresh the UI with the links got from the website. This refresh is embedded inside a runOnUiThread call because it's forbidden to refresh the UI elements inside a separated thread.
The code of the MainActivity has the following form :
Code:
package com.ssaurel.jsouptut;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
private Button getBtn;
private TextView result;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
result = (TextView) findViewById(R.id.result);
getBtn = (Button) findViewById(R.id.getBtn);
getBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
getWebsite();
}
});
}
private void getWebsite() {
new Thread(new Runnable() {
@Override
public void run() {
final StringBuilder builder = new StringBuilder();
try {
Document doc = Jsoup.connect("http://www.ssaurel.com/blog").get();
String title = doc.title();
Elements links = doc.select("a[href]");
builder.append(title).append("\n");
for (Element link : links) {
builder.append("\n").append("Link : ").append(link.attr("href"))
.append("\n").append("Text : ").append(link.text());
}
} catch (IOException e) {
builder.append("Error : ").append(e.getMessage()).append("\n");
}
runOnUiThread(new Runnable() {
@Override
public void run() {
result.setText(builder.toString());
}
});
}
}).start();
}
}
Last step is to run the application and to enjoy the final result with all the links of the SSaurel's blog displayed on the screen :
{
"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"
}
Don't hesitate to try JSoup on your Android application and give me your feedbacks on this tutorial.
Thanks.
Sylvain

Categories

Resources