aFreeRDP: initial release

This is the initial release of aFreeRDP the FreeRDP Android client.
For build instructions have a look to docs/README.android.
This commit is contained in:
Bernhard Miklautz 2013-01-29 12:59:58 +01:00
parent 2fa23e598e
commit f239e1f9c4
213 changed files with 16217 additions and 1126 deletions

View File

@ -58,13 +58,23 @@ if (FREERDP_VERSION_SUFFIX)
else()
set(FREERDP_VERSION_FULL "${FREERDP_VERSION}")
endif()
# Allow to search the host machine for git
if(ANDROID)
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER, BOTH)
endif(ANDROID)
include(GetGitRevisionDescription)
if(ANDROID)
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER, ONLY)
endif(ANDROID)
git_describe(GIT_REVISION --match "[0-9]*" --abbrev=4 --tags --always)
message(STATUS "Git Revision ${GIT_REVISION}")
# Turn on solution folders (2.8.4+)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# Default to release build type
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
@ -183,6 +193,15 @@ if(APPLE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=10.4")
endif()
# Android
if(ANDROID)
if (NOT FREERDP_ANDROID_EXTERNAL_SSL_PATH)
message(STATUS "FREERDP_ANDROID_EXTERNAL_SSL_PATH not set! - Needs to be set if openssl is not found in the android NDK (which usually isn't)")
endif()
set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${FREERDP_ANDROID_EXTERNAL_SSL_PATH})
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/client/Android/libs/${ANDROID_ABI})
endif()
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
if(NOT ANDROID)
find_package(Threads REQUIRED)
@ -471,4 +490,13 @@ set(CPACK_COMPONENT_GROUP_RUNTIME_DESCRIPTION "Runtime")
set(CPACK_COMPONENT_GROUP_APPLICATIONS_DESCRIPTION "Applications")
set(CPACK_COMPONENT_GROUP_DEVELOPMENT_DESCRIPTION "Development")
# Workaround to remove c++ compiler macros and defines for Eclipse.
# If c++ macros/defines are set __cplusplus is also set which causes
# problems when compiling freerdp/jni. To prevent this problem
# we set the macros to "".
if (ANDROID AND CMAKE_EXTRA_GENERATOR STREQUAL "Eclipse CDT4")
set(CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS "")
message(STATUS "Disabled CXX system defines for eclipse (workaround).")
endif()
include(CPack)

1
client/.gitignore vendored
View File

@ -1,2 +1 @@
iOS
Android

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

10
client/Android/.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
# Ignore directories
bin/
obj/
gen/
jni/external/*
!libs
libs/armeabi*
AndroidManifest.xml
local.properties
!.project

33
client/Android/.project Normal file
View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>aFreeRDP</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,109 @@
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="auto"
package="com.freerdp.afreerdp"
android:versionCode="1"
android:versionName="@FREERDP_VERSION_FULL@" >
<uses-sdk android:targetSdkVersion="8" android:minSdkVersion="8"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="com.android.vending.BILLING" />
<supports-screens android:anyDensity="true" android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" />
<application android:name=".application.GlobalApp"
android:label="aFreeRDP"
android:icon="@drawable/icon_launcher_freerdp" >
<!-- Main activity -->
<activity android:name=".presentation.HomeActivity"
android:label="@string/app_title"
android:theme="@style/Theme.Main"
android:alwaysRetainTaskState="true"
>
<intent-filter android:label="@string/app_title">
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Acra crash report dialog activity -->
<activity android:name="org.acra.CrashReportDialog"
android:theme="@android:style/Theme.Dialog" android:launchMode="singleInstance"
android:excludeFromRecents="true" android:finishOnTaskLaunch="true" />
<!-- Session request handler activity - used for search and internally to start sessions -->
<activity android:name=".services.SessionRequestHandlerActivity"
android:theme="@android:style/Theme.NoDisplay"
android:noHistory="true"
android:excludeFromRecents="true">
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
<!-- Activity to create shortcuts -->
<activity android:name=".presentation.ShortcutsActivity"
android:theme="@style/Theme.Main"
android:label="@string/title_create_shortcut">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<!-- It is recommended that you use an activity-alias to provide the "CREATE_SHORTCUT" -->
<!-- intent-filter. This gives you a way to set the text (and optionally the -->
<!-- icon) that will be seen in the launcher's create-shortcut user interface. -->
<activity-alias android:name=".presentation.CreateShortcuts"
android:targetActivity=".presentation.ShortcutsActivity"
android:label="@string/title_create_shortcut">
<!-- This intent-filter allows your shortcuts to be created in the launcher. -->
<intent-filter>
<action android:name="android.intent.action.CREATE_SHORTCUT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity-alias>
<activity android:name=".presentation.BookmarkActivity"
android:label="@string/title_bookmark_settings"
android:theme="@style/Theme.Settings">
</activity>
<activity android:name=".presentation.ApplicationSettingsActivity"
android:label="@string/title_application_settings"
android:theme="@style/Theme.Settings"
android:windowSoftInputMode="stateHidden">
</activity>
<activity android:name=".presentation.SessionActivity"
android:theme="@android:style/Theme.Black.NoTitleBar"
android:configChanges="orientation|keyboardHidden|keyboard"
android:windowSoftInputMode="adjustResize">
</activity>
<activity android:name=".presentation.AboutActivity"
android:label="@string/title_about"
android:theme="@style/Theme.Main">
</activity>
<activity android:name=".presentation.HelpActivity"
android:label="@string/title_help"
android:theme="@style/Theme.Main">
</activity>
<provider android:name=".services.FreeRDPSuggestionProvider"
android:authorities="com.freerdp.afreerdp.services.freerdpsuggestionprovider"
>
</provider>
<receiver android:name=".application.NetworkStateReceiver" android:enabled="true">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
</application>
</manifest>

View File

@ -0,0 +1,64 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# Android Client
#
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
# Copyright 2013 Bernhard Miklautz <bmiklautz@thinstuff.at>
#
# 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.
set(ANDROID_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(ANDROID_PACKAGE_NAME "aFreeRDP")
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml.cmake ${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml @ONLY)
if (ANDROID_SDK)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/local.properties.cmake ${CMAKE_CURRENT_SOURCE_DIR}/local.properties @ONLY)
endif()
add_subdirectory(jni)
if(ANDROID_BUILD_JAVA)
if (NOT ANDROID_SDK)
message(FATAL_ERROR "ANDROID_SDK not set but required for building the java gui (ANDROID_BUILD_JAVA)")
endif()
# And isn't shiped with the android ndk/sdk so
# we need to find it on the local machine
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER, BOTH)
find_program(ANT_COMMAND ant)
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER, ONLY)
if(ANT_COMMAND STREQUAL "ANT_COMMAND-NOTFOUND")
message(FATAL_ERROR "ant not found but required to build android java")
endif()
if(ANDROID_BUILD_JAVA_DEBUG)
set(ANDROID_BUILD_TYPE "debug")
set(APK "${ANDROID_SOURCE_DIR}/bin/${ANDROID_PACKAGE_NAME}-release-unsigned.apk")
else()
set(ANDROID_BUILD_TYPE "release")
set(APK "${ANDROID_SOURCE_DIR}/bin/${ANDROID_PACKAGE_NAME}-debug.apk")
endif()
# command to create the android package
add_custom_command(
OUTPUT "${APK}"
COMMAND ${ANT_COMMAND} ${ANDROID_BUILD_TYPE}
WORKING_DIRECTORY "${ANDROID_SOURCE_DIR}"
MAIN_DEPENDENCY AndroidManifest.xml
DEPENDS freerdp-android local.properties
)
add_custom_target(android-package ALL SOURCES "${APK}")
SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "gen;bin")
endif()

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -0,0 +1,202 @@
<html>
<head>
<meta name='viewport' content='width=device-width; initial-scale=1.0; maximum-scale=1.0;' />
<script language="javascript">
function toggle() {
var ele = document.getElementById("toggleText");
var text = document.getElementById("displayText");
if(ele.style.display == "block") {
ele.style.display = "none";
text.innerHTML = "show";
}
else {
ele.style.display = "block";
text.innerHTML = "<b>hide</b>";
}
}
</script>
<style type="text/css">
@charset "utf-8";
body {
font: 100%%/1.4 Helvetica;
background-color:#E9EBF8;
height: 100%%; width: 100%%; margin: 0;
background-image:url(back.jpg);
background-position:center;
text-align:center;
}
.centered-table {
margin-left: auto;
margin-right: auto;
}
#headline{
background-color:#353639;
opacity:0.9;
color:FFF;
text-align:center;
}
#footer{
padding-top:10px;
}
#footer img{
padding top:10 px;
}
#article{
background-color:#FFFFFF;
opacity: 0.8;
z-index:0;
margin-bottom:3%%;
padding-bottom:0.1%%;
border-radius: 15px;
border-top-left-radius:0px;
border-top-right-radius:0px;
color:#000;
margin: 10px auto;
position:relative;
}
#introduction_headline{
width:inherit;
background-color:#353639;
opacity:0.9;
color:FFF;
text-align:center;
border-bottom-left-radius:15px;
border-bottom-right-radius:15px;
}
#introduction{
background-color:#FFFFFF;
opacity: 0.8;
z-index:0;
margin-bottom:3%%;
padding-bottom:0.1%%;
border-radius: 10px;
color:#000;
}
#container
{
margin-left: auto;
margin-right: auto;
width: 50em;
width:420px;
}
/* ~~ Element/tag selectors ~~ */
ul, ol, dl { /* Due to variations between browsers, it's best practices to zero padding and margin on lists. For consistency, you can either specify the amounts you want here, or on the list items (LI, DT, DD) they contain. Remember that what you do here will cascade to the .nav list unless you write a more specific selector. */
padding: 0;
margin: 0;
}
h1, h2, h3, h4, h5, h6, p {
margin-top: 0; /* removing the top margin gets around an issue where margins can escape from their containing div. The remaining bottom margin will hold it away from any elements that follow. */
padding-right: 1px;
padding-left: 1px; /* adding the padding to the sides of the elements within the divs, instead of the divs themselves, gets rid of any box model math. A nested div with side padding can also be used as an alternate method. */
}
a img { /* this selector removes the default blue border displayed in some browsers around an image when it is surrounded by a link */
border: none;
alignment: right;}
}
/* ~~ Styling for your site's links must remain in this order - including the group of selectors that create the hover effect. ~~ */
/*a:link {
color:#414958;
text-decoration: underline; unless you style your links to look extremely unique, it's best to provide underlines for quick visual identification */
a:hover, a:active, a:focus { /* this group of selectors will give a keyboard navigator the same hover experience as the person using a mouse. */
text-decoration: none;}
a:link { color:#0000FF; }
* {
-webkit-touch-callout: none;
-webkit-user-select: none; /* Disable selection/Copy of UIWebView */
}
</style>
</head>
<body>
<div id="container">
<div id="introduction_headline">
<h2>aFreeRDP </br>Remote Desktop Client</h2>
</div>
<p>
<img src="FreeRDP_Logo.png" width="30%%"></p>
<div id="introduction">
aFreeRDP is an open source client
capable of natively using Remote Desktop Protocol (RDP) in order to remotely access your Windows desktop.</div>
<div id="article">
<div id="headline"><h3>Version Information</h3></div>
<p>
<table class="centered-table" border=0 cellspacing=1 cellpadding=3 >
<tr>
<td>aFreeRDP Version</td> <td>%1$s</td> </tr>
<tr> <td>System Version</td> <td>%2$s</td> </tr>
<tr> <td>Model</td> <td>%3$s</td> </tr>
</table>
</p>
</div>
<div id="article">
<div id="headline">
<h3>Credits</h3>
</div>
aFreeRDP is a part of <a href="http://www.freerdp.com/">FreeRDP</a>
</div>
<div id="article">
<div id="headline">
<h3>License</h3>
</div>
This program is free software; you can redistribute it and/or modify it under the terms of the Mozilla Public License, v. 2.0.
You can obtain an online version of the License from <a href="http://mozilla.org/MPL/2.0/">http://mozilla.org/MPL/2.0/</a>.
</p>
<p>
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
</p>
<p>
A copy of the product's source code can be obtained from the FreeRDP GitHub repository at <a
href="https://github.com/FreeRDP/FreeRDP">https://github.com/FreeRDP/FreeRDP</a>.<br />
</p>
<br></div>
</body>
</html>

View File

@ -0,0 +1,200 @@
<html>
<head>
<meta name='viewport' content='width=device-width; initial-scale=1.0; maximum-scale=1.0;' />
<script language="javascript">
function toggle() {
var ele = document.getElementById("toggleText");
var text = document.getElementById("displayText");
if(ele.style.display == "block") {
ele.style.display = "none";
text.innerHTML = "show";
}
else {
ele.style.display = "block";
text.innerHTML = "<b>hide</b>";
}
}
</script>
<style type="text/css">
@charset "utf-8";
body {
font: 100%%/1 Helvetica;
background-color:#E9EBF8;
height: 100%%; width: 100%%; margin: 0;
background-image:url(back.jpg);
background-position:center;
text-align:center;
}
.centered-table {
margin-left: auto;
margin-right: auto;
}
#headline{
background-color:#353639;
opacity:0.9;
color:FFF;
text-align:center;
}
#footer{
padding-top:10px;
}
#footer img{
padding top:10 px;
}
#article{
background-color:#FFFFFF;
opacity: 0.8;
z-index:0;
margin-bottom:3%%;
padding-bottom:0.1%%;
border-radius: 15px;
border-top-left-radius:0px;
border-top-right-radius:0px;
color:#000;
margin: 10px auto;
position:relative;
}
#introduction_headline{
width:inherit;
background-color:#353639;
opacity:0.9;
color:FFF;
text-align:center;
border-bottom-left-radius:15px;
border-bottom-right-radius:15px;
}
#introduction{
background-color:#FFFFFF;
opacity: 0.8;
z-index:0;
margin-bottom:3%%;
padding-bottom:0.1%%;
border-radius: 10px;
color:#000;
}
#container
{
margin-left: auto;
margin-right: auto;
width:300px;
}
/* ~~ Element/tag selectors ~~ */
ul, ol, dl { /* Due to variations between browsers, it's best practices to zero padding and margin on lists. For consistency, you can either specify the amounts you want here, or on the list items (LI, DT, DD) they contain. Remember that what you do here will cascade to the .nav list unless you write a more specific selector. */
padding: 0;
margin: 0;
}
h1, h2, h3, h4, h5, h6, p {
margin-top: 0; /* removing the top margin gets around an issue where margins can escape from their containing div. The remaining bottom margin will hold it away from any elements that follow. */
padding-right: 1px;
padding-left: 1px; /* adding the padding to the sides of the elements within the divs, instead of the divs themselves, gets rid of any box model math. A nested div with side padding can also be used as an alternate method. */
}
a img { /* this selector removes the default blue border displayed in some browsers around an image when it is surrounded by a link */
border: none;
alignment: right;}
}
/* ~~ Styling for your site's links must remain in this order - including the group of selectors that create the hover effect. ~~ */
/*a:link {
color:#414958;
text-decoration: underline; unless you style your links to look extremely unique, it's best to provide underlines for quick visual identification */
a:hover, a:active, a:focus { /* this group of selectors will give a keyboard navigator the same hover experience as the person using a mouse. */
text-decoration: none;}
a:link { color:#0000FF; }
* {
-webkit-touch-callout: none;
-webkit-user-select: none; /* Disable selection/Copy of UIWebView */
}
}
</style>
</head>
<body>
<div id="container">
<div id="introduction_headline">
<h2>aFreeRDP</br>Remote Desktop Client</h2>
</div>
<p>
<img src="FreeRDP_Logo.png" width="25%%"></p>
<div id="introduction">
<b>aFreeRDP</b> is an open source client for Windows Remote Services using Remote Desktop Protocol (RDP) in order to remotely access your Windows desktop.</div>
<div id="article">
<div id="headline"><h3>Version Information</h3></div>
<p>
<table class="centered-table" border=0 cellspacing=1 cellpadding=3 >
<tr>
<td>aFreerdp Version</td> <td>%1$s</td> </tr>
<tr> <td>System Version</td> <td>%2$s</td> </tr>
<tr> <td>Model</td> <td>%3$s</td> </tr>
</table>
</p>
</div>
<div id="article">
<div id="headline">
<h3>Credits</h3>
</div>
aFreeRDP is part of <a href="http://www.freerdp.com/">FreeRDP</a>
</div>
<div id="article">
<div id="headline">
<h3>License</h3>
</div>
This program is free software; you can redistribute it and/or modify it under the terms of the Mozilla Public License, v. 2.0.
You can obtain an online version of the License from <a href="http://mozilla.org/MPL/2.0/">http://mozilla.org/MPL/2.0/</a>.
</p>
<p>
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
</p>
<p>
A copy of the product's source code can be obtained from the FreeRDP GitHub repository at <a
href="https://github.com/FreeRDP/FreeRDP">https://github.com/FreeRDP/FreeRDP</a>.<br />
</p> </div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

View File

@ -0,0 +1,159 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;" />
<title>Help</title>
<style type="text/css">
@charset "utf-8";
#container{
text-align:center;
}
body{
margin:0;
padding:<length> 0 0 0;
font: 100%/1.4 Helvetica;
background-image:url(back.jpg);
background-position:center;
color:#000;
}
#headline{
background-color:#353639;
opacity:0.9;
color:#000;
text-align:center;
}
#article{
background-color:#FFFFFF;
opacity: 0.8;
z-index:0;
margin-bottom:3%;
padding-bottom:0.1%;
border-radius: 15px;
border-top-left-radius:0px;
border-top-right-radius:0px;
color:#000;
margin: 10px auto;
position:relative;
}
#header{
height:auto;
width:100%;
background-color:#353639;
padding-bottom:5px;
padding-left:5px;
padding-right:5px;
padding-top:10px;
position: fixed;
top: 0;
left: 0;
height:40px;
overflow:visible;
min-width:400px;
z-index:20;
}
#content{
padding-top:70px;
z-index:-20;
max-width:420px;
}
/* ~~ Element/tag selectors ~~ */
ul, ol, dl { /* Due to variations between browsers, it's best practices to zero padding and margin on lists. For consistency, you can either specify the amounts you want here, or on the list items (LI, DT, DD) they contain. Remember that what you do here will cascade to the .nav list unless you write a more specific selector. */
padding: 0;
margin: 0;
}
h1, h2, h3, h4, h5, h6, p {
margin-top: 0; /* removing the top margin gets around an issue where margins can escape from their containing div. The remaining bottom margin will hold it away from any elements that follow. */
padding-right: 1px;
padding-left: 1px; /* adding the padding to the sides of the elements within the divs, instead of the divs themselves, gets rid of any box model math. A nested div with side padding can also be used as an alternate method.
*/
color:#000;
}
a img { /* this selector removes the default blue border displayed in some browsers around an image when it is surrounded by a link */
border: none;
}
/* ~~ Styling for your site's links must remain in this order - including the group of selectors that create the hover effect. ~~ */
/*a:link {
color:#414958;
text-decoration: underline; unless you style your links to look extremely unique, it's best to provide underlines for quick visual identification */
a:hover, a:active, a:focus { /* this group of selectors will give a keyboard navigator the same hover experience as the person using a mouse. */
text-decoration: none;}
* {
-webkit-touch-callout: none;
-webkit-user-select: none; /* Disable selection/Copy of UIWebView */
}
</style>
</head>
<body>
<div id="container">
<center>
<div id="header">
<a href="gestures.html"><img src="nav_gestures.png"></a>
<a href="toolbar.html"><img src="nav_toolbar.png"></a>
<a href="touch_pointer.html"><img src="nav_touch_pointer.png"></a>
</div>
<div id="content">
<h1>Gestures</h1>
<p>
aFreeRDP is designed for touch sensitive devices.
These gestures let you do the most usual operations with your fingers.</p>
<p> <img src="gestures.png"></p>
</div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

View File

@ -0,0 +1,159 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;" />
<title>Help</title>
<style type="text/css">
@charset "utf-8";
#container{
text-align:center;
color:#000;}
body{
margin:0;
padding:<length> 0 0 0;
font: 100% Helvetica;
background-image:url(back.jpg);
background-position:center;
}
#headline{
background-color:#353639;
opacity:0.9;
color:FFF;
text-align:center;
}
#article{
background-color:#FFFFFF;
opacity: 0.8;
z-index:0;
margin-bottom:3%;
padding-bottom:0.1%;
border-radius: 15px;
border-top-left-radius:0px;
border-top-right-radius:0px;
color:#000;
margin: 10px auto;
position:relative;
}
#header{
width:100%;
background-color:#353639;
padding-bottom:1px;
padding-left:5px;
padding-right:5px;
padding-top:5px;
position: fixed;
top: 0;
left: 0;
height:30px;
min-width:250px;
z-index:20;
}
#content{
padding-top:40px;
z-index:-20;
max-width:300px;
}
/* ~~ Element/tag selectors ~~ */
ul, ol, dl { /* Due to variations between browsers, it's best practices to zero padding and margin on lists. For consistency, you can either specify the amounts you want here, or on the list items (LI, DT, DD) they contain. Remember that what you do here will cascade to the .nav list unless you write a more specific selector. */
padding: 0;
margin: 0;
}
h1, h2, h3, h4, h5, h6, p {
margin-top: 0; /* removing the top margin gets around an issue where margins can escape from their containing div. The remaining bottom margin will hold it away from any elements that follow. */
padding-right: 1px;
padding-left: 1px; /* adding the padding to the sides of the elements within the divs, instead of the divs themselves, gets rid of any box model math. A nested div with side padding can also be used as an alternate method.
*/
color:#000;
}
a img { /* this selector removes the default blue border displayed in some browsers around an image when it is surrounded by a link */
border: none;
}
/* ~~ Styling for your site's links must remain in this order - including the group of selectors that create the hover effect. ~~ */
/*a:link {
color:#414958;
text-decoration: underline; unless you style your links to look extremely unique, it's best to provide underlines for quick visual identification */
a:hover, a:active, a:focus { /* this group of selectors will give a keyboard navigator the same hover experience as the person using a mouse. */
text-decoration: none;}
* {
-webkit-touch-callout: none;
-webkit-user-select: none; /* Disable selection/Copy of UIWebView */
}
</style>
</head>
<body>
<div id="container">
<center>
<div id="header">
<a href="gestures_phone.html"><img src="nav_gestures.png" height="90%"></a>
<a href="toolbar_phone.html"><img src="nav_toolbar.png" height="90%"></a>
<a href="touch_pointer_phone.html"><img src="nav_touch_pointer.png" height="90%""></a>
</div>
<div id="content">
<h2> Gestures</h2>
<p>
aFreeRDP is designed for touch sensitive devices.
These gestures let you do the most usual operations with your fingers.</p>
<p> <img src="gestures_phone.png"></p>
</div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,178 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;" />
<title>Help</title>
<style type="text/css">
@charset "utf-8";
#container{
text-align:center;
color:#FFFFFF;}
body{
margin:0;
padding:<length> 0 0 0;
font: 100%/1.4 Helvetica;
background-image:url(back.jpg);
background-position:center;
}
#headline{
background-color:#353639;
color:#FFF;
text-align:center;
}
#article{
background-color:#FFFFFF;
opacity: 0.8;
z-index:0;
margin-bottom:3%;
padding-bottom:0.1%;
border-radius: 15px;
border-top-left-radius:0px;
border-top-right-radius:0px;
color:#000;
margin: 10px auto;
position:relative;
}
#header{
height:auto;
width:100%;
background-color:#353639;
padding-bottom:5px;
padding-left:5px;
padding-right:5px;
padding-top:10px;
position: fixed;
top: 0;
left: 0;
height:40px;
overflow:visible;
min-width:400px;
z-index:20;
}
#content{
padding-top:70px;
z-index:-20;
max-width:420px;
}
/* ~~ Element/tag selectors ~~ */
ul, ol, dl { /* Due to variations between browsers, it's best practices to zero padding and margin on lists. For consistency, you can either specify the amounts you want here, or on the list items (LI, DT, DD) they contain. Remember that what you do here will cascade to the .nav list unless you write a more specific selector. */
padding: 0;
margin: 0;
}
h1, h2, h3, h4, h5, h6, p {
margin-top: 0; /* removing the top margin gets around an issue where margins can escape from their containing div. The remaining bottom margin will hold it away from any elements that follow. */
padding-right: 1px;
padding-left: 1px; /* adding the padding to the sides of the elements within the divs, instead of the divs themselves, gets rid of any box model math. A nested div with side padding can also be used as an alternate method.
*/
color:#000;
}
a img { /* this selector removes the default blue border displayed in some browsers around an image when it is surrounded by a link */
border: none;
}
/* ~~ Styling for your site's links must remain in this order - including the group of selectors that create the hover effect. ~~ */
/*a:link {
color:#414958;
text-decoration: underline; unless you style your links to look extremely unique, it's best to provide underlines for quick visual identification */
a:hover, a:active, a:focus { /* this group of selectors will give a keyboard navigator the same hover experience as the person using a mouse. */
text-decoration: none;}
* {
-webkit-touch-callout: none;
-webkit-user-select: none; /* Disable selection/Copy of UIWebView */
}
</style>
</head>
<body>
<div id="container">
<center>
<div id="header">
<a href="gestures.html"><img src="nav_gestures.png"></a>
<a href="toolbar.html"><img src="nav_toolbar.png"></a>
<a href="touch_pointer.html"><img src="nav_touch_pointer.png"></a>
</div>
<div id="content">
<h1>Toolbar</h1>
<p>
With the toolbar you'll be able to display and hide the main tools in your session. This allows together with the touch pointer and the gestures an intuitiv workflow for remote computing on touch sensitive screens.
</p>
<p><img src="toolbar.png"></p>
<div id="article">
<div id="headline">
<h3><span style="color:white">Keyboards</span></h3></div>
Display/hide the default keyboard as well as an extended keyboard with function keys</div>
<div id="article">
<div id="headline"><h3><span style="color:white">Touch Pointer</span></h3></div>
Display/hide the gesture controlled cursor</div>
<div id="article">
<div id="headline"><h3><span style="color:white">Disconnect</span></h3></div>
Disconnect your current session. Please be aware that a disconnect is not the same as a log out.</div>
</div>
</div></center>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,176 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;" />
<title>Help</title>
<style type="text/css">
@charset "utf-8";
#container{
text-align:center;
color:#FFFFFF;}
body{
margin:0;
padding:<length> 0 0 0;
font: 100% Helvetica;
background-image:url(back.jpg);
background-position:center;
}
#headline{
background-color:#353639;
opacity:0.9;
color:FFF;
text-align:center;
}
#article{
background-color:#FFFFFF;
opacity: 0.8;
z-index:0;
margin-bottom:3%;
padding-bottom:0.1%;
border-radius: 15px;
border-top-left-radius:0px;
border-top-right-radius:0px;
color:#000;
margin: 10px auto;
position:relative;
}
#header{
width:100%;
background-color:#353639;
padding-bottom:1px;
padding-left:5px;
padding-right:5px;
padding-top:5px;
position: fixed;
top: 0;
left: 0;
height:30px;
min-width:250px;
z-index:20;
}
#content{
padding-top:40px;
z-index:-20;
max-width:300px;
}
/* ~~ Element/tag selectors ~~ */
ul, ol, dl { /* Due to variations between browsers, it's best practices to zero padding and margin on lists. For consistency, you can either specify the amounts you want here, or on the list items (LI, DT, DD) they contain. Remember that what you do here will cascade to the .nav list unless you write a more specific selector. */
padding: 0;
margin: 0;
}
h1, h2, h3, h4, h5, h6, p {
margin-top: 0; /* removing the top margin gets around an issue where margins can escape from their containing div. The remaining bottom margin will hold it away from any elements that follow. */
padding-right: 1px;
padding-left: 1px; /* adding the padding to the sides of the elements within the divs, instead of the divs themselves, gets rid of any box model math. A nested div with side padding can also be used as an alternate method.
*/
color:#000;
}
a img { /* this selector removes the default blue border displayed in some browsers around an image when it is surrounded by a link */
border: none;
}
/* ~~ Styling for your site's links must remain in this order - including the group of selectors that create the hover effect. ~~ */
/*a:link {
color:#414958;
text-decoration: underline; unless you style your links to look extremely unique, it's best to provide underlines for quick visual identification */
a:hover, a:active, a:focus { /* this group of selectors will give a keyboard navigator the same hover experience as the person using a mouse. */
text-decoration: none;}
* {
-webkit-touch-callout: none;
-webkit-user-select: none; /* Disable selection/Copy of UIWebView */
}
</style>
</head>
<body>
<div id="container">
<center>
<div id="header">
<a href="gestures_phone.html"><img src="nav_gestures.png" height="90%"></a>
<a href="toolbar_phone.html"><img src="nav_toolbar.png" height="90%"></a>
<a href="touch_pointer_phone.html"><img src="nav_touch_pointer.png" height="90%""></a>
</div>
<div id="content">
<h2>Toolbar</h2>
<p>
With the toolbar you'll be able to display and hide the main tools in your session. This allows together with the touch pointer and the gestures an intuitiv workflow for remote computing on touch sensitive screens.
</p>
<p><img src="toolbar_phone.png"></p>
<div id="article">
<div id="headline">
<h4><span style="color:white">Keyboards</h4></span></div>
Display/hide the default keyboard as well as an extended keyboard with function keys</div>
<div id="article">
<div id="headline"><h4><span style="color:white">Touch Pointer</h4></div>
Display/hide the gesture controlled cursor</div></span>
<div id="article">
<div id="headline"><h4><span style="color:white">Disconnect</span></h4></div>
Disconnect your current session. Please be aware that a disconnect is not the same as a log out.</div>
</div>
</div></center>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

@ -0,0 +1,164 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;" />
<title>Help</title>
<style type="text/css">
@charset "utf-8";
#container{
text-align:center;
color:#FFFFFF;}
body{
margin:0;
padding:<length> 0 0 0;
font: 100%/1.4 Helvetica;
background-image:url(back.jpg);
background-position:center;
}
#headline{
background-color:#353639;
opacity:0.9;
color:FFF;
text-align:center;
}
#article{
background-color:#FFFFFF;
opacity: 0.8;
z-index:0;
margin-bottom:3%;
padding-bottom:0.1%;
border-radius: 15px;
border-top-left-radius:0px;
border-top-right-radius:0px;
color:#000;
margin: 10px auto;
position:relative;
}
#header{
height:auto;
width:100%;
background-color:#353639;
padding-bottom:5px;
padding-left:5px;
padding-right:5px;
padding-top:10px;
position: fixed;
top: 0;
left: 0;
height:40px;
overflow:visible;
min-width:400px;
z-index:20;
}
#content{
padding-top:70px;
z-index:-20;
max-width:420px;
}
/* ~~ Element/tag selectors ~~ */
ul, ol, dl { /* Due to variations between browsers, it's best practices to zero padding and margin on lists. For consistency, you can either specify the amounts you want here, or on the list items (LI, DT, DD) they contain. Remember that what you do here will cascade to the .nav list unless you write a more specific selector. */
padding: 0;
margin: 0;
}
h1, h2, h3, h4, h5, h6, p {
margin-top: 0; /* removing the top margin gets around an issue where margins can escape from their containing div. The remaining bottom margin will hold it away from any elements that follow. */
padding-right: 1px;
padding-left: 1px; /* adding the padding to the sides of the elements within the divs, instead of the divs themselves, gets rid of any box model math. A nested div with side padding can also be used as an alternate method.
*/
color:#000;
}
a img { /* this selector removes the default blue border displayed in some browsers around an image when it is surrounded by a link */
border: none;
}
/* ~~ Styling for your site's links must remain in this order - including the group of selectors that create the hover effect. ~~ */
/*a:link {
color:#414958;
text-decoration: underline; unless you style your links to look extremely unique, it's best to provide underlines for quick visual identification */
a:hover, a:active, a:focus { /* this group of selectors will give a keyboard navigator the same hover experience as the person using a mouse. */
text-decoration: none;}
* {
-webkit-touch-callout: none;
-webkit-user-select: none; /* Disable selection/Copy of UIWebView */
}
</style>
</head>
<body>
<div id="container">
<center>
<div id="header">
<a href="gestures.html"><img src="nav_gestures.png"></a>
<a href="toolbar.html"><img src="nav_toolbar.png"></a>
<a href="touch_pointer.html"><img src="nav_touch_pointer.png"></a>
</div>
<div id="content">
<h1>Touch Pointer</h1>
<p><img src="touch_pointer.png">
</div>
</center>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

View File

@ -0,0 +1,161 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;" />
<title>Help</title>
<style type="text/css">
@charset "utf-8";
#container{
text-align:center;
color:#FFFFFF;}
body{
margin:0;
padding:<length> 0 0 0;
font: 100% Helvetica;
background-image:url(back.jpg);
background-position:center;
}
#headline{
background-color:#353639;
opacity:0.9;
color:FFF;
text-align:center;
}
#article{
background-color:#FFFFFF;
opacity: 0.8;
z-index:0;
margin-bottom:3%;
padding-bottom:0.1%;
border-radius: 15px;
border-top-left-radius:0px;
border-top-right-radius:0px;
color:#000;
margin: 10px auto;
position:relative;
}
#header{
width:100%;
background-color:#353639;
padding-bottom:1px;
padding-left:5px;
padding-right:5px;
padding-top:5px;
position: fixed;
top: 0;
left: 0;
height:30px;
min-width:250px;
z-index:20;
}
#content{
padding-top:40px;
z-index:-20;
max-width:300px;
}
/* ~~ Element/tag selectors ~~ */
ul, ol, dl { /* Due to variations between browsers, it's best practices to zero padding and margin on lists. For consistency, you can either specify the amounts you want here, or on the list items (LI, DT, DD) they contain. Remember that what you do here will cascade to the .nav list unless you write a more specific selector. */
padding: 0;
margin: 0;
}
h1, h2, h3, h4, h5, h6, p {
margin-top: 0; /* removing the top margin gets around an issue where margins can escape from their containing div. The remaining bottom margin will hold it away from any elements that follow. */
padding-right: 1px;
padding-left: 1px; /* adding the padding to the sides of the elements within the divs, instead of the divs themselves, gets rid of any box model math. A nested div with side padding can also be used as an alternate method.
*/
color:#000;
}
a img { /* this selector removes the default blue border displayed in some browsers around an image when it is surrounded by a link */
border: none;
}
/* ~~ Styling for your site's links must remain in this order - including the group of selectors that create the hover effect. ~~ */
/*a:link {
color:#414958;
text-decoration: underline; unless you style your links to look extremely unique, it's best to provide underlines for quick visual identification */
a:hover, a:active, a:focus { /* this group of selectors will give a keyboard navigator the same hover experience as the person using a mouse. */
text-decoration: none;}
* {
-webkit-touch-callout: none;
-webkit-user-select: none; /* Disable selection/Copy of UIWebView */
}
</style>
</head>
<body>
<div id="container">
<center>
<div id="header">
<a href="gestures_phone.html"><img src="nav_gestures.png" height="90%"></a>
<a href="toolbar_phone.html"><img src="nav_toolbar.png" height="90%"></a>
<a href="touch_pointer_phone.html"><img src="nav_touch_pointer.png" height="90%""></a>
</div>
<div id="content">
<h2>Touch Pointer</h2>
<p><img src="touch_pointer_phone.png">
</p>
</div>
</center>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,128 @@
<html>
<head>
<meta name='viewport' content='width=device-width; initial-scale=1.0; maximum-scale=1.0;' />
<style type="text/css">
@charset "utf-8";
body {
font: 100%/1.4 Helvetica;
background-color:#E9EBF8;
height: 100%; width: 100%; margin: 0;
background-image:url(back.jpg);
}
/* ~~ Element/tag selectors ~~ */
h1, h2, h3, h4, h5, h6, p {
margin-top: 0; /* removing the top margin gets around an issue where margins can escape from their containing div. The remaining bottom margin will hold it away from any elements that follow. */
padding-right: 1px;
padding-left: 1px; /* adding the padding to the sides of the elements within the divs, instead of the divs themselves, gets rid of any box model math. A nested div with side padding can also be used as an alternate method. */
}
a img { /* this selector removes the default blue border displayed in some browsers around an image when it is surrounded by a link */
border: none;
alignment: right;}
/* ~~ Styling for your site's links must remain in this order - including the group of selectors that create the hover effect. ~~ */
/*a:link {
color:#414958;
text-decoration: underline; unless you style your links to look extremely unique, it's best to provide underlines for quick visual identification */
a:hover, a:active, a:focus { /* this group of selectors will give a keyboard navigator the same hover experience as the person using a mouse. */
text-decoration: none;}
#number
{
margin-left:0%;
opacity:0.9;
background:#DDD;
}
#content
{
margin-left: auto;
margin-right: auto;
width:420px;
}
#headline{
width:inherit;
background-color:#353639;
border-radius: 15px;
color:FFF;
text-align:center;
border-bottom-left-radius:0px;
border-bottom-right-radius:0px;
}
#article{
background-color:#FFFFFF;
opacity: 0.8;
z-index:0;
margin-bottom:3%;
padding-bottom:0.1%;
border-radius: 18px;
position:relative;
}
#text{
margin-left:30px;
position:static;
margin-bottom:3%;
margin-top:3%;
}
#button{
padding-top:10px;
padding-bottom:10px;
}
a:link { color:#0000FF; }
* {
-webkit-touch-callout: none;
-webkit-user-select: none; /* Disable selection/Copy of UIWebView */
}
</style>
</head>
<body>
<div id="content">
<div id="article">
<div id="headline">
<h1>New Connection</h1>
</div><div id="text">
You can specify your own connection settings - just hit the button below or choose "New Connection" from the application menu.</div>
<div id="button">
<center><a href="new_connection"><img src="new_connection.png"></a><center></a>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,121 @@
<html>
<head>
<meta name='viewport' content='width=device-width; initial-scale=1.0; maximum-scale=1.0;' />
<style type="text/css">
@charset "utf-8";
body {
font: 100%/1 Helvetica;
background-color:#E9EBF8;
height: 100%; width: 100%; margin: 0;
background-image:url(back.jpg);
}
/* ~~ Element/tag selectors ~~ */
h1, h2, h3, h4, h5, h6, p {
margin-top: 0; /* removing the top margin gets around an issue where margins can escape from their containing div. The remaining bottom margin will hold it away from any elements that follow. */
padding-right: 1px;
padding-left: 1px; /* adding the padding to the sides of the elements within the divs, instead of the divs themselves, gets rid of any box model math. A nested div with side padding can also be used as an alternate method. */
}
a img { /* this selector removes the default blue border displayed in some browsers around an image when it is surrounded by a link */
border: none;
alignment: right;}
/* ~~ Styling for your site's links must remain in this order - including the group of selectors that create the hover effect. ~~ */
/*a:link {
color:#414958;
text-decoration: underline; unless you style your links to look extremely unique, it's best to provide underlines for quick visual identification */
a:hover, a:active, a:focus { /* this group of selectors will give a keyboard navigator the same hover experience as the person using a mouse. */
text-decoration: none;}
#number
{
margin-left:0%;
opacity:0.9;
background:#DDD;
}
#content
{
margin-left: auto;
margin-right: auto;
width:300px;
}
#headline{
width:inherit;
background-color:#353639;
border-radius: 15px;
color:FFF;
text-align:center;
border-bottom-left-radius:0px;
border-bottom-right-radius:0px;
}
#article{
background-color:#FFFFFF;
opacity: 0.8;
z-index:0;
margin-bottom:3%;
padding-bottom:0.1%;
border-radius: 18px;
position:relative;
}
#text{
margin-left:30px;
position:static;
margin-bottom:3%;
margin-top:3%;
}
#button{
padding-top:10px;
padding-bottom:10px;
}
a:link { color:#0000FF; }
* {
-webkit-touch-callout: none;
-webkit-user-select: none; /* Disable selection/Copy of UIWebView */
}
</style>
</head>
<body>
<div id="content">
<div id="article">
<div id="headline">
<h2>New Connection</h2>
</div><div id="text">
You can specify your own connection settings - just hit the button below or choose "New Connection" from the application menu.</div>
<div id="button">
<center><a href="new_connection"><img src="new_connection.png"></a><center></a>
</div>
</div>
</div>
</body>
</html>

91
client/Android/build.xml Normal file
View File

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="aFreeRDP" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />
<!-- The ant.properties file can be created by you. It is only edited by the
'android' tool to add properties to it.
This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update:
source.dir
The name of the source directory. Default is 'src'.
out.dir
The name of the output directory. Default is 'bin'.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
Properties related to the SDK location or the project target should
be updated using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
-->
<property file="ant.properties" />
<!-- if sdk.dir was not set from one of the property file, then
get it from the ANDROID_HOME env var.
This must be done before we load project.properties since
the proguard config can use sdk.dir -->
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<!-- The project.properties file is created and updated by the 'android'
tool, as well as ADT.
This contains project specific properties such as project target, and library
dependencies. Lower level build properties are stored in ant.properties
(or in .classpath for Eclipse projects).
This file is an integral part of the build system for your
application and should be checked into Version Control Systems. -->
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<!--
Import per project custom build rules if present at the root of the project.
This is the place to put custom intermediary targets such as:
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
-->
<import file="custom_rules.xml" optional="true" />
<!-- Import the actual build file.
To customize existing targets, there are two options:
- Customize only one target:
- copy/paste the target into this file, *before* the
<import> task.
- customize it to your needs.
- Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
***********************
****** IMPORTANT ******
***********************
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
<!-- version-tag: 1 -->
<import file="${sdk.dir}/tools/ant/build.xml" />
</project>

View File

@ -0,0 +1,65 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# Android Client
#
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
# Copyright 2013 Bernhard Miklautz <bmiklautz@thinstuff.at>
#
# 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.
set(MODULE_NAME "freerdp-android")
set(MODULE_PREFIX "FREERDP_CLIENT_ANDROID")
include_directories(.)
include_directories(generated)
if(CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-pointer-sign")
endif()
set(${MODULE_PREFIX}_SRCS
android_debug.h
android_event.c
android_event.h
android_freerdp.c
android_freerdp.h
android_jni_callback.c
android_jni_callback.h)
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS}
generated/android_freerdp_jni.c
generated/android_freerdp_jni.h)
add_library(${MODULE_NAME} SHARED ${${MODULE_PREFIX}_SRCS})
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-client)
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE freerdp
MODULES freerdp-core freerdp-gdi freerdp-utils)
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE winpr
MODULES winpr-crt winpr-synch)
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} dl)
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} log)
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} jnigraphics)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${ANDROID_SOURCE_DIR}/libs/${ANDROID_ABI}")
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Client/Android")

View File

@ -0,0 +1,34 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Android Debug Interface
*
* Copyright 2013 Thinstuff Technologies GmbH, Author: Martin Fleisz
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef FREERDP_ANDROID_DEBUG_H
#define FREERDP_ANDROID_DEBUG_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <android/log.h>
#define TAG "LibFreeRDP"
#define DEBUG_ANDROID_NULL(fmt, ...) do { } while (0)
#define DEBUG_ANDROID_PRINT(_dbg_str, fmt, ...) __android_log_print(ANDROID_LOG_INFO, TAG, _dbg_str fmt "\n" , __FUNCTION__, __LINE__, ## __VA_ARGS__)
#define DEBUG_ANDROID_CLASS(_dbg_class, fmt, ...) DEBUG_ANDROID_PRINT("DBG_" #_dbg_class " %s (%d): ", fmt, ## __VA_ARGS__)
#ifdef WITH_DEBUG_ANDROID_JNI
#define DEBUG_ANDROID(fmt, ...) DEBUG_ANDROID_PRINT("DBG %s (%d): ", fmt, ## __VA_ARGS__)
#else
#define DEBUG_ANDROID(fmt, ...) DEBUG_ANDROID_NULL(fmt, ## __VA_ARGS__)
#endif
#endif /* FREERDP_ANDROID_DEBUG_H */

View File

@ -0,0 +1,289 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Android Event System
*
* Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2013 Thinstuff Technologies GmbH, Author: Martin Fleisz
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/types.h>
#include <freerdp/freerdp.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "android_freerdp.h"
int android_is_event_set(ANDROID_EVENT_QUEUE * queue)
{
fd_set rfds;
int num_set;
struct timeval time;
FD_ZERO(&rfds);
FD_SET(queue->pipe_fd[0], &rfds);
memset(&time, 0, sizeof(time));
num_set = select(queue->pipe_fd[0] + 1, &rfds, 0, 0, &time);
return (num_set == 1);
}
void android_set_event(ANDROID_EVENT_QUEUE * queue)
{
int length;
length = write(queue->pipe_fd[1], "sig", 4);
if (length != 4)
printf("android_set_event: error\n");
}
void android_clear_event(ANDROID_EVENT_QUEUE * queue)
{
int length;
while (android_is_event_set(queue))
{
length = read(queue->pipe_fd[0], &length, 4);
if (length != 4)
printf("android_clear_event: error\n");
}
}
void android_push_event(freerdp * inst, ANDROID_EVENT* event)
{
androidContext* aCtx = (androidContext*)inst->context;
if (aCtx->event_queue->count >= aCtx->event_queue->size)
{
aCtx->event_queue->size = aCtx->event_queue->size * 2;
aCtx->event_queue->events = realloc((void*) aCtx->event_queue->events, aCtx->event_queue->size);
}
aCtx->event_queue->events[(aCtx->event_queue->count)++] = event;
android_set_event(aCtx->event_queue);
}
ANDROID_EVENT* android_peek_event(ANDROID_EVENT_QUEUE * queue)
{
ANDROID_EVENT* event;
if (queue->count < 1)
return NULL;
event = queue->events[0];
return event;
}
ANDROID_EVENT* android_pop_event(ANDROID_EVENT_QUEUE * queue)
{
int i;
ANDROID_EVENT* event;
if (queue->count < 1)
return NULL;
event = queue->events[0];
(queue->count)--;
for (i = 0; i < queue->count; i++)
{
queue->events[i] = queue->events[i + 1];
}
return event;
}
int android_process_event(ANDROID_EVENT_QUEUE * queue, freerdp * inst)
{
ANDROID_EVENT* event;
while (android_peek_event(queue) != NULL)
{
event = android_pop_event(queue);
if (event->type == EVENT_TYPE_KEY)
{
ANDROID_EVENT_KEY* key_event = (ANDROID_EVENT_KEY*) event;
inst->input->KeyboardEvent(inst->input, key_event->flags, key_event->scancode);
android_event_key_free(key_event);
}
else if (event->type == EVENT_TYPE_KEY_UNICODE)
{
ANDROID_EVENT_KEY* key_event = (ANDROID_EVENT_KEY*) event;
inst->input->UnicodeKeyboardEvent(inst->input, key_event->flags, key_event->scancode);
android_event_key_free(key_event);
}
else if (event->type == EVENT_TYPE_CURSOR)
{
ANDROID_EVENT_CURSOR* cursor_event = (ANDROID_EVENT_CURSOR*) event;
inst->input->MouseEvent(inst->input, cursor_event->flags, cursor_event->x, cursor_event->y);
android_event_cursor_free(cursor_event);
}
else if (event->type == EVENT_TYPE_DISCONNECT)
{
android_event_disconnect_free(event);
return 1;
}
}
return 0;
}
BOOL android_get_fds(freerdp * inst, void ** read_fds,
int * read_count, void ** write_fds, int * write_count)
{
androidContext* aCtx = (androidContext*)inst->context;
if (aCtx->event_queue->pipe_fd[0] == -1)
return TRUE;
read_fds[*read_count] = (void *)(long) aCtx->event_queue->pipe_fd[0];
(*read_count)++;
return TRUE;
}
BOOL android_check_fds(freerdp * inst)
{
androidContext* aCtx = (androidContext*)inst->context;
if (aCtx->event_queue->pipe_fd[0] == -1)
return TRUE;
if (android_is_event_set(aCtx->event_queue))
{
android_clear_event(aCtx->event_queue);
if(android_process_event(aCtx->event_queue, inst) != 0)
return FALSE;
}
return TRUE;
}
ANDROID_EVENT_KEY* android_event_key_new(int flags, UINT16 scancode)
{
ANDROID_EVENT_KEY* event;
event = (ANDROID_EVENT_KEY*) malloc(sizeof(ANDROID_EVENT_KEY));
memset(event, 0, sizeof(ANDROID_EVENT_KEY));
event->type = EVENT_TYPE_KEY;
event->flags = flags;
event->scancode = scancode;
return event;
}
void android_event_key_free(ANDROID_EVENT_KEY* event)
{
if (event != NULL)
free(event);
}
ANDROID_EVENT_KEY* android_event_unicodekey_new(UINT16 key)
{
ANDROID_EVENT_KEY* event;
event = (ANDROID_EVENT_KEY*) malloc(sizeof(ANDROID_EVENT_KEY));
memset(event, 0, sizeof(ANDROID_EVENT_KEY));
event->type = EVENT_TYPE_KEY_UNICODE;
event->scancode = key;
return event;
}
void android_event_unicodekey_free(ANDROID_EVENT_KEY* event)
{
if (event != NULL)
free(event);
}
ANDROID_EVENT_CURSOR* android_event_cursor_new(UINT16 flags, UINT16 x, UINT16 y)
{
ANDROID_EVENT_CURSOR* event;
event = (ANDROID_EVENT_CURSOR*) malloc(sizeof(ANDROID_EVENT_CURSOR));
memset(event, 0, sizeof(ANDROID_EVENT_CURSOR));
event->type = EVENT_TYPE_CURSOR;
event->x = x;
event->y = y;
event->flags = flags;
return event;
}
void android_event_cursor_free(ANDROID_EVENT_CURSOR* event)
{
if (event != NULL)
free(event);
}
ANDROID_EVENT* android_event_disconnect_new()
{
ANDROID_EVENT* event;
event = (ANDROID_EVENT*) malloc(sizeof(ANDROID_EVENT));
memset(event, 0, sizeof(ANDROID_EVENT));
event->type = EVENT_TYPE_DISCONNECT;
return event;
}
void android_event_disconnect_free(ANDROID_EVENT* event)
{
if (event != NULL)
free(event);
}
void android_event_queue_init(freerdp * inst)
{
androidContext* aCtx = (androidContext*)inst->context;
aCtx->event_queue = (ANDROID_EVENT_QUEUE*) malloc(sizeof(ANDROID_EVENT_QUEUE));
memset(aCtx->event_queue, 0, sizeof(ANDROID_EVENT_QUEUE));
aCtx->event_queue->pipe_fd[0] = -1;
aCtx->event_queue->pipe_fd[1] = -1;
aCtx->event_queue->size = 16;
aCtx->event_queue->count = 0;
aCtx->event_queue->events = (ANDROID_EVENT**) malloc(sizeof(ANDROID_EVENT*) * aCtx->event_queue->size);
if (pipe(aCtx->event_queue->pipe_fd) < 0)
printf("android_pre_connect: pipe failed\n");
}
void android_event_queue_uninit(freerdp * inst)
{
androidContext* aCtx = (androidContext*)inst->context;
if (aCtx->event_queue->pipe_fd[0] != -1)
{
close(aCtx->event_queue->pipe_fd[0]);
aCtx->event_queue->pipe_fd[0] = -1;
}
if (aCtx->event_queue->pipe_fd[1] != -1)
{
close(aCtx->event_queue->pipe_fd[1]);
aCtx->event_queue->pipe_fd[1] = -1;
}
}

View File

@ -0,0 +1,74 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Android Event System
*
* Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef FREERDP_ANDROID_EVENT_H
#define FREERDP_ANDROID_EVENT_H
#include <freerdp/freerdp.h>
#define EVENT_TYPE_KEY 1
#define EVENT_TYPE_CURSOR 2
#define EVENT_TYPE_DISCONNECT 3
#define EVENT_TYPE_KEY_UNICODE 4
struct _ANDROID_EVENT
{
int type;
};
typedef struct _ANDROID_EVENT ANDROID_EVENT;
struct _ANDROID_EVENT_KEY
{
int type;
int flags;
UINT16 scancode;
};
typedef struct _ANDROID_EVENT_KEY ANDROID_EVENT_KEY;
struct _ANDROID_EVENT_CURSOR
{
int type;
UINT16 flags;
UINT16 x;
UINT16 y;
};
typedef struct _ANDROID_EVENT_CURSOR ANDROID_EVENT_CURSOR;
struct _ANDROID_EVENT_QUEUE
{
int size;
int count;
int pipe_fd[2];
ANDROID_EVENT **events;
};
typedef struct _ANDROID_EVENT_QUEUE ANDROID_EVENT_QUEUE;
int android_is_event_set(ANDROID_EVENT_QUEUE * queue);
void android_set_event(ANDROID_EVENT_QUEUE * queue);
void android_clear_event(ANDROID_EVENT_QUEUE * queue);
void android_push_event(freerdp * inst, ANDROID_EVENT* event);
ANDROID_EVENT* android_peek_event(ANDROID_EVENT_QUEUE * queue);
ANDROID_EVENT* android_pop_event(ANDROID_EVENT_QUEUE * queue);
int android_process_event(ANDROID_EVENT_QUEUE * queue, freerdp * inst);
BOOL android_get_fds(freerdp * inst, void ** read_fds,
int * read_count, void ** write_fds, int * write_count);
BOOL android_check_fds(freerdp * inst);
ANDROID_EVENT_KEY* android_event_key_new(int flags, UINT16 scancode);
ANDROID_EVENT_KEY* android_event_unicodekey_new(UINT16 key);
ANDROID_EVENT_CURSOR* android_event_cursor_new(UINT16 flags, UINT16 x, UINT16 y);
ANDROID_EVENT* android_event_disconnect_new();
void android_event_key_free(ANDROID_EVENT_KEY* event);
void android_event_unicodekey_free(ANDROID_EVENT_KEY* event);
void android_event_cursor_free(ANDROID_EVENT_CURSOR* event);
void android_event_disconnect_free(ANDROID_EVENT* event);
void android_event_queue_init(freerdp * inst);
void android_event_queue_uninit(freerdp * inst);
#endif /* FREERDP_ANDROID_EVENT_H */

View File

@ -0,0 +1,841 @@
/*
Android JNI Client Layer
Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Copyright 2013 Thinstuff Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <locale.h>
#include <sys/select.h>
#include <freerdp/codec/rfx.h>
#include <freerdp/channels/channels.h>
#include <freerdp/gdi/gdi.h>
#include <freerdp/utils/event.h>
#include <freerdp/constants.h>
#include <freerdp/locale/keyboard.h>
#include <android/bitmap.h>
#include <machine/cpu-features.h>
#include "android_freerdp.h"
#include "android_jni_callback.h"
#include "android_debug.h"
struct thread_data
{
freerdp* instance;
};
void android_context_new(freerdp* instance, rdpContext* context)
{
context->channels = freerdp_channels_new();
android_event_queue_init(instance);
}
void android_context_free(freerdp* instance, rdpContext* context)
{
freerdp_channels_free(context->channels);
android_event_queue_uninit(instance);
}
void android_begin_paint(rdpContext* context)
{
rdpGdi* gdi = context->gdi;
gdi->primary->hdc->hwnd->invalid->null = 1;
gdi->primary->hdc->hwnd->ninvalid = 0;
}
void android_end_paint(rdpContext* context)
{
DEBUG_ANDROID("ui_update");
rdpGdi *gdi = context->gdi;
if (gdi->primary->hdc->hwnd->invalid->null)
return;
int x = gdi->primary->hdc->hwnd->invalid->x;
int y = gdi->primary->hdc->hwnd->invalid->y;
int w = gdi->primary->hdc->hwnd->invalid->w;
int h = gdi->primary->hdc->hwnd->invalid->h;
DEBUG_ANDROID("ui_update: x:%d y:%d w:%d h:%d", x, y, w, h);
freerdp_callback("OnGraphicsUpdate", "(IIIII)V", context->instance, x, y, w, h);
}
void android_desktop_resize(rdpContext* context)
{
DEBUG_ANDROID("ui_desktop_resize");
rdpGdi *gdi = context->gdi;
rdpSettings* settings = context->instance->settings;
gdi_resize(gdi, settings->DesktopWidth, settings->DesktopHeight);
freerdp_callback("OnGraphicsResize", "(III)V", context->instance, settings->DesktopWidth, settings->DesktopHeight);
}
BOOL android_pre_connect(freerdp* instance)
{
DEBUG_ANDROID("android_pre_connect");
rdpSettings* settings = instance->settings;
BOOL bitmap_cache = settings->BitmapCacheEnabled;
settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE;
settings->OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE;
settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE;
settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE;
settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE;
settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE;
settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE;
settings->OrderSupport[NEG_LINETO_INDEX] = TRUE;
settings->OrderSupport[NEG_POLYLINE_INDEX] = TRUE;
settings->OrderSupport[NEG_MEMBLT_INDEX] = bitmap_cache;
settings->OrderSupport[NEG_MEM3BLT_INDEX] = TRUE;
settings->OrderSupport[NEG_MEMBLT_V2_INDEX] = bitmap_cache;
settings->OrderSupport[NEG_MEM3BLT_V2_INDEX] = FALSE;
settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE;
settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE;
settings->OrderSupport[NEG_FAST_INDEX_INDEX] = TRUE;
settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = TRUE;
settings->OrderSupport[NEG_POLYGON_SC_INDEX] = FALSE;
settings->OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE;
settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
settings->FrameAcknowledge = 10;
freerdp_channels_load_plugin(instance->context->channels, instance->settings, "tsxlc", NULL);
freerdp_channels_pre_connect(instance->context->channels, instance);
return TRUE;
}
BOOL android_post_connect(freerdp* instance)
{
DEBUG_ANDROID("android_post_connect");
freerdp_callback("OnSettingsChanged", "(IIII)V", instance, instance->settings->DesktopWidth, instance->settings->DesktopHeight, instance->settings->ColorDepth);
instance->context->cache = cache_new(instance->settings);
gdi_init(instance, CLRCONV_ALPHA | ((instance->settings->ColorDepth > 16) ? CLRBUF_32BPP : CLRBUF_16BPP), NULL);
instance->update->BeginPaint = android_begin_paint;
instance->update->EndPaint = android_end_paint;
instance->update->DesktopResize = android_desktop_resize;
//ai->rail = rail_new(instance->settings);
//instance->update->rail = (void*) ai->rail;
//rail_register_update_callbacks(xfi->rail, instance->update);
//android_rail_register_callbacks(xfi, xfi->rail);
freerdp_channels_post_connect(instance->context->channels, instance);
// send notifications
freerdp_callback("OnConnectionSuccess", "(I)V", instance);
return TRUE;
}
jobject create_string_builder(JNIEnv *env, char* initialStr)
{
jclass cls;
jmethodID methodId;
jobject obj;
// get class
cls = (*env)->FindClass(env, "java/lang/StringBuilder");
if(!cls)
return NULL;
if(initialStr)
{
// get method id for constructor
methodId = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/lang/String;)V");
if(!methodId)
return NULL;
// create string that holds our initial string
jstring jstr = (*env)->NewStringUTF(env, initialStr);
// construct new StringBuilder
obj = (*env)->NewObject(env, cls, methodId, jstr);
}
else
{
// get method id for constructor
methodId = (*env)->GetMethodID(env, cls, "<init>", "()V");
if(!methodId)
return NULL;
// construct new StringBuilder
obj = (*env)->NewObject(env, cls, methodId);
}
return obj;
}
char* get_string_from_string_builder(JNIEnv* env, jobject strBuilder)
{
jclass cls;
jmethodID methodId;
jstring strObj;
const jbyte* native_str;
char* result;
// get class
cls = (*env)->FindClass(env, "java/lang/StringBuilder");
if(!cls)
return NULL;
// get method id for constructor
methodId = (*env)->GetMethodID(env, cls, "toString", "()Ljava/lang/String;");
if(!methodId)
return NULL;
// get jstring representation of our buffer
strObj = (*env)->CallObjectMethod(env, strBuilder, methodId);
// read string
native_str = (*env)->GetStringUTFChars(env, strObj, NULL);
result = strdup(native_str);
(*env)->ReleaseStringUTFChars(env, strObj, native_str);
return result;
}
BOOL android_authenticate(freerdp* instance, char** username, char** password, char** domain)
{
DEBUG_ANDROID("Authenticate user:");
DEBUG_ANDROID(" Username: %s", *username);
DEBUG_ANDROID(" Domain: %s", *domain);
JNIEnv* env;
jboolean attached = jni_attach_thread(&env);
jobject jstr1 = create_string_builder(env, *username);
jobject jstr2 = create_string_builder(env, *domain);
jobject jstr3 = create_string_builder(env, *password);
jboolean res = freerdp_callback_bool_result("OnAuthenticate", "(ILjava/lang/StringBuilder;Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;)Z", instance, jstr1, jstr2, jstr3);
if(res == JNI_TRUE)
{
// read back string values
if(*username != NULL)
free(*username);
*username = get_string_from_string_builder(env, jstr1);
if(*domain != NULL)
free(*domain);
*domain = get_string_from_string_builder(env, jstr2);
if(*password == NULL)
free(*password);
*password = get_string_from_string_builder(env, jstr3);
}
if(attached == JNI_TRUE)
jni_detach_thread();
return ((res == JNI_TRUE) ? TRUE : FALSE);
}
BOOL android_verify_certificate(freerdp* instance, char* subject, char* issuer, char* fingerprint)
{
DEBUG_ANDROID("Certificate details:");
DEBUG_ANDROID("\tSubject: %s", subject);
DEBUG_ANDROID("\tIssuer: %s", issuer);
DEBUG_ANDROID("\tThumbprint: %s", fingerprint);
DEBUG_ANDROID("The above X.509 certificate could not be verified, possibly because you do not have "
"the CA certificate in your certificate store, or the certificate has expired."
"Please look at the documentation on how to create local certificate store for a private CA.\n");
JNIEnv* env;
jboolean attached = jni_attach_thread(&env);
jstring jstr1 = (*env)->NewStringUTF(env, subject);
jstring jstr2 = (*env)->NewStringUTF(env, issuer);
jstring jstr3 = (*env)->NewStringUTF(env, fingerprint);
jboolean res = freerdp_callback_bool_result("OnVerifyCertificate", "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z", instance, jstr1, jstr2, jstr3);
if(attached == JNI_TRUE)
jni_detach_thread();
return ((res == JNI_TRUE) ? TRUE : FALSE);
}
BOOL android_verify_changed_certificate(freerdp* instance, char* subject, char* issuer, char* new_fingerprint, char* old_fingerprint)
{
return android_verify_certificate(instance, subject, issuer, new_fingerprint);
}
/*
int xf_process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data)
{
rdpChanMan* chanman = (rdpChanMan*) user_data;
printf("loading plugin %s\n", name);
freerdp_chanman_load_plugin(chanman, settings, name, plugin_data);
return 1;
}
*/
int android_receive_channel_data(freerdp* instance, int channelId, UINT8* data, int size, int flags, int total_size)
{
return freerdp_channels_data(instance, channelId, data, size, flags, total_size);
}
void android_process_channel_event(rdpChannels* channels, freerdp* instance)
{
RDP_EVENT* event;
event = freerdp_channels_pop_event(channels);
if (event)
{
/* switch (event->event_class)
{
case RDP_EVENT_CLASS_RAIL:
xf_process_rail_event(ai, chanman, event);
break;
default:
break;
}
switch (event->event_type)
{
case RDP_EVENT_TYPE_CB_SYNC:
android_process_cb_sync_event(chanman, instance);
break;
default:
break;
}
*/
freerdp_event_free(event);
}
}
int android_freerdp_run(freerdp* instance)
{
int i;
int fds;
int max_fds;
int rcount;
int wcount;
void* rfds[32];
void* wfds[32];
fd_set rfds_set;
fd_set wfds_set;
memset(rfds, 0, sizeof(rfds));
memset(wfds, 0, sizeof(wfds));
if (!freerdp_connect(instance))
{
freerdp_callback("OnConnectionFailure", "(I)V", instance);
return 0;
}
((androidContext*)instance->context)->is_connected = TRUE;
while (1)
{
rcount = 0;
wcount = 0;
if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE)
{
DEBUG_ANDROID("Failed to get FreeRDP file descriptor\n");
break;
}
if (freerdp_channels_get_fds(instance->context->channels, instance, rfds, &rcount, wfds, &wcount) != TRUE)
{
DEBUG_ANDROID("Failed to get channel manager file descriptor\n");
break;
}
if (android_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE)
{
DEBUG_ANDROID("Failed to get android file descriptor\n");
break;
}
max_fds = 0;
FD_ZERO(&rfds_set);
FD_ZERO(&wfds_set);
for (i = 0; i < rcount; i++)
{
fds = (int)(long)(rfds[i]);
if (fds > max_fds)
max_fds = fds;
FD_SET(fds, &rfds_set);
}
if (max_fds == 0)
break;
if (select(max_fds + 1, &rfds_set, &wfds_set, NULL, NULL) == -1)
{
/* these are not really errors */
if (!((errno == EAGAIN) ||
(errno == EWOULDBLOCK) ||
(errno == EINPROGRESS) ||
(errno == EINTR))) /* signal occurred */
{
DEBUG_ANDROID("android_run: select failed\n");
break;
}
}
if (freerdp_check_fds(instance) != TRUE)
{
DEBUG_ANDROID("Failed to check FreeRDP file descriptor\n");
break;
}
if (android_check_fds(instance) != TRUE)
{
DEBUG_ANDROID("Failed to check android file descriptor\n");
break;
}
if (freerdp_channels_check_fds(instance->context->channels, instance) != TRUE)
{
DEBUG_ANDROID("Failed to check channel manager file descriptor\n");
break;
}
android_process_channel_event(instance->context->channels, instance);
}
// issue another OnDisconnecting here in case the disconnect was initiated by the sever and not our client
freerdp_callback("OnDisconnecting", "(I)V", instance);
freerdp_channels_close(instance->context->channels, instance);
freerdp_disconnect(instance);
gdi_free(instance);
cache_free(instance->context->cache);
freerdp_callback("OnDisconnected", "(I)V", instance);
return 0;
}
void* android_thread_func(void* param)
{
struct thread_data* data;
data = (struct thread_data*) param;
freerdp* instance = data->instance;
android_freerdp_run(instance);
free(data);
pthread_detach(pthread_self());
return NULL;
}
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
DEBUG_ANDROID("JNI_OnLoad");
jint res = init_callback_environment(vm);
setlocale(LC_ALL, "");
freerdp_channels_global_init();
return res;
}
JNIEXPORT jint JNICALL jni_freerdp_new(JNIEnv *env, jclass cls)
{
freerdp* instance;
// create instance
instance = freerdp_new();
instance->PreConnect = android_pre_connect;
instance->PostConnect = android_post_connect;
instance->Authenticate = android_authenticate;
instance->VerifyCertificate = android_verify_certificate;
instance->VerifyChangedCertificate = android_verify_changed_certificate;
instance->ReceiveChannelData = android_receive_channel_data;
// create context
instance->context_size = sizeof(androidContext);
instance->ContextNew = android_context_new;
instance->ContextFree = android_context_free;
freerdp_context_new(instance);
return (jint) instance;
}
JNIEXPORT void JNICALL jni_freerdp_free(JNIEnv *env, jclass cls, jint instance)
{
freerdp* inst = (freerdp*)instance;
freerdp_free(inst);
}
JNIEXPORT jboolean JNICALL jni_freerdp_connect(JNIEnv *env, jclass cls, jint instance)
{
freerdp* inst = (freerdp*)instance;
struct thread_data* data = (struct thread_data*) malloc(sizeof(struct thread_data));
data->instance = inst;
androidContext* ctx = (androidContext*)inst->context;
pthread_create(&ctx->thread, 0, android_thread_func, data);
return JNI_TRUE;
}
JNIEXPORT jboolean JNICALL jni_freerdp_disconnect(JNIEnv *env, jclass cls, jint instance)
{
freerdp* inst = (freerdp*)instance;
ANDROID_EVENT* event = (ANDROID_EVENT*)android_event_disconnect_new();
android_push_event(inst, event);
freerdp_callback("OnDisconnecting", "(I)V", instance);
return (jboolean) JNI_TRUE;
}
JNIEXPORT void JNICALL jni_freerdp_cancel_connection(JNIEnv *env, jclass cls, jint instance)
{
DEBUG_ANDROID("Cancelling connection ...");
freerdp* inst = (freerdp*)instance;
ANDROID_EVENT* event = (ANDROID_EVENT*)android_event_disconnect_new();
android_push_event(inst, event);
freerdp_callback("OnDisconnecting", "(I)V", instance);
}
JNIEXPORT void JNICALL jni_freerdp_set_data_directory(JNIEnv *env, jclass cls, jint instance, jstring jdirectory)
{
freerdp* inst = (freerdp*)instance;
rdpSettings * settings = inst->settings;
const jbyte *directory = (*env)->GetStringUTFChars(env, jdirectory, NULL);
free(settings->HomePath);
settings->HomePath = strdup(directory);
(*env)->ReleaseStringUTFChars(env, jdirectory, directory);
}
JNIEXPORT void JNICALL jni_freerdp_set_connection_info(JNIEnv *env, jclass cls, jint instance,
jstring jhostname, jstring jusername, jstring jpassword, jstring jdomain, jint width, jint height,
jint color_depth, jint port, jboolean console, jint security, jstring jcertname)
{
freerdp* inst = (freerdp*)instance;
rdpSettings * settings = inst->settings;
const jbyte *hostname = (*env)->GetStringUTFChars(env, jhostname, NULL);
const jbyte *username = (*env)->GetStringUTFChars(env, jusername, NULL);
const jbyte *password = (*env)->GetStringUTFChars(env, jpassword, NULL);
const jbyte *domain = (*env)->GetStringUTFChars(env, jdomain, NULL);
const jbyte *certname = (*env)->GetStringUTFChars(env, jcertname, NULL);
DEBUG_ANDROID("hostname: %s", (char*) hostname);
DEBUG_ANDROID("username: %s", (char*) username);
DEBUG_ANDROID("password: %s", (char*) password);
DEBUG_ANDROID("domain: %s", (char*) domain);
DEBUG_ANDROID("width: %d", width);
DEBUG_ANDROID("height: %d", height);
DEBUG_ANDROID("color depth: %d", color_depth);
DEBUG_ANDROID("port: %d", port);
DEBUG_ANDROID("security: %d", security);
settings->DesktopWidth = width;
settings->DesktopHeight = height;
settings->ColorDepth = color_depth;
settings->ServerPort = port;
// Hack for 16 bit RDVH connections:
// In this case we get screen corruptions when we have an odd screen resolution width ... need to investigate what is causing this...
if (color_depth <= 16)
settings->DesktopWidth &= (~1);
settings->ServerHostname = strdup(hostname);
if(username && strlen(username) > 0)
settings->Username = strdup(username);
if(password && strlen(password) > 0)
{
settings->Password = strdup(password);
settings->AutoLogonEnabled = TRUE;
}
settings->Domain = strdup(domain);
if(certname && strlen(certname) > 0)
settings->CertificateName = strdup(certname);
settings->ConsoleSession = (console == JNI_TRUE) ? TRUE : FALSE;
settings->SoftwareGdi = TRUE;
/* enable NSCodec */
settings->NSCodec = TRUE;
switch ((int) security)
{
case 1:
/* Standard RDP */
settings->RdpSecurity = TRUE;
settings->TlsSecurity = FALSE;
settings->NlaSecurity = FALSE;
settings->ExtSecurity = FALSE;
settings->DisableEncryption = TRUE;
settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
break;
case 2:
/* TLS */
settings->NlaSecurity = FALSE;
settings->TlsSecurity = TRUE;
settings->RdpSecurity = FALSE;
settings->ExtSecurity = FALSE;
break;
case 3:
/* NLA */
settings->NlaSecurity = TRUE;
settings->TlsSecurity = FALSE;
settings->RdpSecurity = FALSE;
settings->ExtSecurity = FALSE;
break;
default:
break;
}
// set US keyboard layout
settings->KeyboardLayout = 0x0409;
(*env)->ReleaseStringUTFChars(env, jhostname, hostname);
(*env)->ReleaseStringUTFChars(env, jusername, username);
(*env)->ReleaseStringUTFChars(env, jpassword, password);
(*env)->ReleaseStringUTFChars(env, jdomain, domain);
(*env)->ReleaseStringUTFChars(env, jcertname, certname);
return;
}
JNIEXPORT void JNICALL jni_freerdp_set_performance_flags(
JNIEnv *env, jclass cls, jint instance, jboolean remotefx, jboolean disableWallpaper, jboolean disableFullWindowDrag,
jboolean disableMenuAnimations, jboolean disableTheming, jboolean enableFontSmoothing, jboolean enableDesktopComposition)
{
freerdp* inst = (freerdp*)instance;
rdpSettings * settings = inst->settings;
DEBUG_ANDROID("remotefx: %d", (remotefx == JNI_TRUE) ? 1 : 0);
if (remotefx == JNI_TRUE)
{
settings->RemoteFxCodec = TRUE;
settings->FastPathOutput = TRUE;
settings->ColorDepth = 32;
settings->LargePointerFlag = TRUE;
settings->PerformanceFlags = PERF_FLAG_NONE;
settings->FrameMarkerCommandEnabled = TRUE;
}
/* store performance settings */
if (disableWallpaper == JNI_TRUE)
settings->DisableWallpaper = TRUE;
if (disableFullWindowDrag == JNI_TRUE)
settings->DisableFullWindowDrag = TRUE;
if (disableMenuAnimations == JNI_TRUE)
settings->DisableMenuAnims = TRUE;
if (disableTheming == JNI_TRUE)
settings->DisableThemes = TRUE;
if (enableFontSmoothing == JNI_TRUE)
settings->AllowFontSmoothing = TRUE;
if(enableDesktopComposition == JNI_TRUE)
settings->AllowDesktopComposition = TRUE;
/* Create performance flags from settings */
if (settings->AllowFontSmoothing)
settings->PerformanceFlags |= PERF_ENABLE_FONT_SMOOTHING;
if (settings->AllowDesktopComposition)
settings->PerformanceFlags |= PERF_ENABLE_DESKTOP_COMPOSITION;
if (settings->DisableWallpaper)
settings->PerformanceFlags |= PERF_DISABLE_WALLPAPER;
if (settings->DisableFullWindowDrag)
settings->PerformanceFlags |= PERF_DISABLE_FULLWINDOWDRAG;
if (settings->DisableMenuAnims)
settings->PerformanceFlags |= PERF_DISABLE_MENUANIMATIONS;
if (settings->DisableThemes)
settings->PerformanceFlags |= PERF_DISABLE_THEMING;
DEBUG_ANDROID("performance_flags: %04X", settings->PerformanceFlags);
}
JNIEXPORT void JNICALL jni_freerdp_set_advanced_settings(JNIEnv *env, jclass cls, jint instance, jstring jRemoteProgram, jstring jWorkDir)
{
freerdp* inst = (freerdp*)instance;
rdpSettings * settings = inst->settings;
const jbyte *remote_program = (*env)->GetStringUTFChars(env, jRemoteProgram, NULL);
const jbyte *work_dir = (*env)->GetStringUTFChars(env, jWorkDir, NULL);
DEBUG_ANDROID("Remote Program: %s", (char*) remote_program);
DEBUG_ANDROID("Work Dir: %s", (char*) work_dir);
if(remote_program && strlen(remote_program) > 0)
settings->AlternateShell = strdup(remote_program);
if(work_dir && strlen(work_dir) > 0)
settings->ShellWorkingDirectory = strdup(work_dir);
(*env)->ReleaseStringUTFChars(env, jRemoteProgram, remote_program);
(*env)->ReleaseStringUTFChars(env, jWorkDir, work_dir);
}
void copy_pixel_buffer(UINT8* dstBuf, UINT8* srcBuf, int x, int y, int width, int height, int wBuf, int hBuf, int bpp)
{
int i, j;
int length;
int scanline;
UINT8 *dstp, *srcp;
length = width * bpp;
scanline = wBuf * bpp;
srcp = (UINT8*) &srcBuf[(scanline * y) + (x * bpp)];
dstp = (UINT8*) &dstBuf[(scanline * y) + (x * bpp)];
if (bpp == 4)
{
for (i = 0; i < height; i++)
{
for (j = 0; j < width * 4; j += 4)
{
// ARGB <-> ABGR
dstp[j + 0] = srcp[j + 2];
dstp[j + 1] = srcp[j + 1];
dstp[j + 2] = srcp[j + 0];
dstp[j + 3] = srcp[j + 3];
}
srcp += scanline;
dstp += scanline;
}
}
else
{
for (i = 0; i < height; i++)
{
memcpy(dstp, srcp, length);
srcp += scanline;
dstp += scanline;
}
}
}
JNIEXPORT jboolean JNICALL jni_freerdp_update_graphics(
JNIEnv *env, jclass cls, jint instance, jobject bitmap, jint x, jint y, jint width, jint height)
{
int ret;
void* pixels;
AndroidBitmapInfo info;
freerdp* inst = (freerdp*)instance;
rdpGdi *gdi = inst->context->gdi;
if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0)
{
DEBUG_ANDROID("AndroidBitmap_getInfo() failed ! error=%d", ret);
return JNI_FALSE;
}
if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0)
{
DEBUG_ANDROID("AndroidBitmap_lockPixels() failed ! error=%d", ret);
return JNI_FALSE;
}
copy_pixel_buffer(pixels, gdi->primary_buffer, x, y, width, height, gdi->width, gdi->height, gdi->bytesPerPixel);
AndroidBitmap_unlockPixels(env, bitmap);
return JNI_TRUE;
}
JNIEXPORT void JNICALL jni_freerdp_send_key_event(
JNIEnv *env, jclass cls, jint instance, jint keycode, jboolean down)
{
RDP_SCANCODE scancode;
ANDROID_EVENT* event;
freerdp* inst = (freerdp*)instance;
scancode = freerdp_keyboard_get_rdp_scancode_from_virtual_key_code(keycode);
int flags = (down == JNI_TRUE) ? KBD_FLAGS_DOWN : KBD_FLAGS_RELEASE;
flags |= (RDP_SCANCODE_EXTENDED(scancode)) ? KBD_FLAGS_EXTENDED : 0;
event = (ANDROID_EVENT*) android_event_key_new(flags, RDP_SCANCODE_CODE(scancode));
android_push_event(inst, event);
DEBUG_ANDROID("send_key_event: %d, %d", scancode, flags);
}
JNIEXPORT void JNICALL jni_freerdp_send_unicodekey_event(
JNIEnv *env, jclass cls, jint instance, jint keycode)
{
ANDROID_EVENT* event;
freerdp* inst = (freerdp*)instance;
event = (ANDROID_EVENT*) android_event_unicodekey_new(keycode);
android_push_event(inst, event);
DEBUG_ANDROID("send_unicodekey_event: %d", keycode);
}
JNIEXPORT void JNICALL jni_freerdp_send_cursor_event(
JNIEnv *env, jclass cls, jint instance, jint x, jint y, jint flags)
{
ANDROID_EVENT* event;
freerdp* inst = (freerdp*)instance;
event = (ANDROID_EVENT*) android_event_cursor_new(flags, x, y);
android_push_event(inst, event);
DEBUG_ANDROID("send_cursor_event: (%d, %d), %d", x, y, flags);
}
JNIEXPORT jstring JNICALL jni_freerdp_get_version(JNIEnv *env, jclass cls)
{
return (*env)->NewStringUTF(env, GIT_REVISION);
}

View File

@ -0,0 +1,53 @@
/*
Android JNI Client Layer
Copyright 2013 Thinstuff Technologies GmbH, Author: Martin Fleisz
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef __ANDROID_FREERDP_H
#define __ANDROID_FREERDP_H
#include <jni.h>
#include <pthread.h>
#include <freerdp/freerdp.h>
#include "android_event.h"
struct android_context
{
rdpContext rdpCtx;
ANDROID_EVENT_QUEUE* event_queue;
pthread_t thread;
BOOL is_connected;
};
typedef struct android_context androidContext;
void copy_remotefx_tile(UINT8* dstBuf, UINT8* srcBuf, int x, int y, int width, int height, int bpp);
void copy_pixel_buffer(UINT8* dstBuf, UINT8* srcBuf, int x, int y, int width, int height, int wBuf, int hBuf, int bpp);
JNIEXPORT jint JNICALL jni_freerdp_new(JNIEnv *env, jclass cls);
JNIEXPORT void JNICALL jni_freerdp_free(JNIEnv *env, jclass cls, jint instance);
JNIEXPORT jboolean JNICALL jni_freerdp_connect(JNIEnv *env, jclass cls, jint instance);
JNIEXPORT jboolean JNICALL jni_freerdp_disconnect(JNIEnv *env, jclass cls, jint instance);
JNIEXPORT void JNICALL jni_freerdp_cancel_connection(JNIEnv *env, jclass cls, jint instance);
JNIEXPORT void JNICALL jni_freerdp_set_connection_info(JNIEnv *env, jclass cls, jint instance,
jstring jhostname, jstring jusername, jstring jpassword, jstring jdomain, jint width,
jint height, jint color_depth, jint port, jboolean console, jint security, jstring jcertname);
JNIEXPORT void JNICALL jni_freerdp_set_performance_flags(JNIEnv *env, jclass cls, jint instance, jboolean remotefx, jboolean disableWallpaper, jboolean disableFullWindowDrag,
jboolean disableMenuAnimations, jboolean disableTheming, jboolean enableFontSmoothing, jboolean enableDesktopComposition);
JNIEXPORT void JNICALL jni_freerdp_set_advanced_settings(JNIEnv *env, jclass cls, jint instance, jstring jRemoteProgram, jstring jWorkDir);
JNIEXPORT void JNICALL jni_freerdp_set_data_directory(JNIEnv *env, jclass cls, jint instance, jstring jdirectory);
JNIEXPORT jboolean JNICALL jni_freerdp_update_graphics(JNIEnv *env, jclass cls, jint instance, jobject bitmap, jint x, jint y, jint width, jint height);
JNIEXPORT void JNICALL jni_freerdp_send_cursor_event(JNIEnv *env, jclass cls, jint instance, jint x, jint y, jint flags);
JNIEXPORT void JNICALL jni_freerdp_send_key_event(JNIEnv *env, jclass cls, jint instance, jint keycode, jboolean down);
JNIEXPORT void JNICALL jni_freerdp_send_unicodekey_event(JNIEnv *env, jclass cls, jint instance, jint keycode);
JNIEXPORT jstring JNICALL jni_freerdp_get_version(JNIEnv *env, jclass cls);
#endif /* __ANDROID_FREERDP_H */

View File

@ -0,0 +1,179 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Android JNI Callback Helpers
*
* Copyright 2011-2013 Thinstuff Technologies GmbH, Author: Martin Fleisz
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <android/log.h>
#include "android_jni_callback.h"
#include "android_debug.h"
#include "android_freerdp_jni.h"
JavaVM *jVM;
jobject jLibFreeRDPObject;
const char *jLibFreeRDPPath = JAVA_LIBFREERDP_CLASS;
void jni_load_class(JNIEnv *env, const char *path, jobject *objptr)
{
jclass class;
jmethodID method;
jobject object;
DEBUG_ANDROID("jni_load_class: %s", path);
class = (*env)->FindClass(env, path);
if (!class)
{
DEBUG_ANDROID("jni_load_class: failed to find class %s", path);
}
method = (*env)->GetMethodID(env, class, "<init>", "()V");
if (!method)
{
DEBUG_ANDROID("jni_load_class: failed to find class constructor of %s", path);
}
object = (*env)->NewObject(env, class, method);
if (!object)
{
DEBUG_ANDROID("jni_load_class: failed create new object of %s", path);
}
(*objptr) = (*env)->NewGlobalRef(env, object);
}
jint init_callback_environment(JavaVM* vm)
{
JNIEnv* env;
if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK)
{
DEBUG_ANDROID("JNI_OnLoad: failed to obtain current JNI environment");
return -1;
}
jVM = vm;
jni_load_class(env, jLibFreeRDPPath, &jLibFreeRDPObject);
return JNI_VERSION_1_4;
}
/* attach current thread to jvm */
jboolean jni_attach_thread(JNIEnv** env)
{
if ((*jVM)->GetEnv(jVM, (void**) env, JNI_VERSION_1_4) != JNI_OK)
{
DEBUG_ANDROID("android_java_callback: attaching current thread");
(*jVM)->AttachCurrentThread(jVM, env, NULL);
if ((*jVM)->GetEnv(jVM, (void**) env, JNI_VERSION_1_4) != JNI_OK)
{
DEBUG_ANDROID("android_java_callback: failed to obtain current JNI environment");
}
return JNI_TRUE;
}
return JNI_FALSE;
}
/* attach current thread to JVM */
void jni_detach_thread()
{
(*jVM)->DetachCurrentThread(jVM);
}
/* callback with void result */
void java_callback_void(jobject obj, const char * callback, const char* signature, va_list args)
{
jclass jObjClass;
jmethodID jCallback;
jboolean attached;
JNIEnv *env;
DEBUG_ANDROID("java_callback: %s (%s)", callback, signature);
attached = jni_attach_thread(&env);
jObjClass = (*env)->GetObjectClass(env, obj);
if (!jObjClass) {
DEBUG_ANDROID("android_java_callback: failed to get class reference");
}
jCallback = (*env)->GetStaticMethodID(env, jObjClass, callback, signature);
if (!jCallback) {
DEBUG_ANDROID("android_java_callback: failed to get method id");
}
(*env)->CallStaticVoidMethodV(env, jObjClass, jCallback, args);
if(attached == JNI_TRUE)
jni_detach_thread();
}
/* callback with bool result */
jboolean java_callback_bool(jobject obj, const char * callback, const char* signature, va_list args)
{
jclass jObjClass;
jmethodID jCallback;
jboolean attached;
JNIEnv *env;
DEBUG_ANDROID("java_callback: %s (%s)", callback, signature);
attached = jni_attach_thread(&env);
jObjClass = (*env)->GetObjectClass(env, obj);
if (!jObjClass) {
DEBUG_ANDROID("android_java_callback: failed to get class reference");
}
jCallback = (*env)->GetStaticMethodID(env, jObjClass, callback, signature);
if (!jCallback) {
DEBUG_ANDROID("android_java_callback: failed to get method id");
}
jboolean res = (*env)->CallStaticBooleanMethodV(env, jObjClass, jCallback, args);
if(attached == JNI_TRUE)
jni_detach_thread();
return res;
}
/* callback to freerdp class */
void freerdp_callback(const char * callback, const char * signature, ...)
{
va_list vl;
va_start(vl, signature);
java_callback_void(jLibFreeRDPObject, callback, signature, vl);
va_end(vl);
}
jboolean freerdp_callback_bool_result(const char * callback, const char * signature, ...)
{
va_list vl;
va_start(vl, signature);
jboolean res = java_callback_bool(jLibFreeRDPObject, callback, signature, vl);
va_end(vl);
return res;
}

View File

@ -0,0 +1,27 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Android JNI Callback Helpers
*
* Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2011-2013 Thinstuff Technologies GmbH, Author: Martin Fleisz
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef FREERDP_ANDROID_JNI_CALLBACK_H
#define FREERDP_ANDROID_JNI_CALLBACK_H
#include <jni.h>
#include <stdarg.h>
jint init_callback_environment(JavaVM* vm);
jboolean jni_attach_thread(JNIEnv** env);
void jni_detach_thread();
void freerdp_callback(const char * callback, const char * signature, ...);
jboolean freerdp_callback_bool_result(const char * callback, const char * signature, ...);
void tsxconnect_callback(const char * callback, const char * signature, ...);
#endif /* FREERDP_ANDROID_JNI_CALLBACK_H */

View File

@ -0,0 +1,101 @@
/*
FreeRDP: A Remote Desktop Protocol client.
Android JNI Bindings and Native Code
Copyright 2010 Marc-Andre Moreau <marcandre.moreau@gmail.com>
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 "android_freerdp.h"
#include "android_freerdp_jni.h"
JNIEXPORT jint JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1new(JNIEnv *env, jclass cls)
{
return jni_freerdp_new(env, cls);
}
JNIEXPORT void JNICALL JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1free(JNIEnv *env, jclass cls, jint instance)
{
jni_freerdp_free(env, cls, instance);
}
JNIEXPORT jboolean JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1connect(JNIEnv *env, jclass cls, jint instance)
{
return jni_freerdp_connect(env, cls, instance);
}
JNIEXPORT jboolean JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1disconnect(JNIEnv *env, jclass cls, jint instance)
{
return jni_freerdp_disconnect(env, cls, instance);
}
JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1cancel_1connection(JNIEnv *env, jclass cls, jint instance)
{
jni_freerdp_cancel_connection(env, cls, instance);
}
JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1set_1connection_1info(JNIEnv *env, jclass cls, jint instance,
jstring jhostname, jstring jusername, jstring jpassword, jstring jdomain, jint width, jint height, jint color_depth, jint port,
jboolean console, jint security, jstring certname)
{
jni_freerdp_set_connection_info(env, cls, instance, jhostname, jusername, jpassword, jdomain,
width, height, color_depth, port, console, security, certname);
}
JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1set_1advanced_1settings(JNIEnv *env, jclass cls, jint instance, jstring remote_program, jstring work_dir)
{
jni_freerdp_set_advanced_settings(env, cls, instance, remote_program, work_dir);
}
JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1set_1data_1directory(JNIEnv *env, jclass cls, jint instance, jstring directory)
{
jni_freerdp_set_data_directory(env, cls, instance, directory);
}
JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1set_1performance_1flags(
JNIEnv *env, jclass cls, jint instance, jboolean remotefx, jboolean disableWallpaper, jboolean disableFullWindowDrag,
jboolean disableMenuAnimations, jboolean disableTheming, jboolean enableFontSmoothing, jboolean enableDesktopComposition)
{
jni_freerdp_set_performance_flags(env, cls, instance, remotefx, disableWallpaper, disableFullWindowDrag, disableMenuAnimations, disableTheming, enableFontSmoothing, enableDesktopComposition);
}
JNIEXPORT jboolean JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1update_1graphics(
JNIEnv *env, jclass cls, jint instance, jobject bitmap, jint x, jint y, jint width, jint height)
{
return jni_freerdp_update_graphics(env, cls, instance, bitmap, x, y, width, height);
}
JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1send_1cursor_1event(
JNIEnv *env, jclass cls, jint instance, jint x, jint y, jint flags)
{
jni_freerdp_send_cursor_event(env, cls, instance, x, y, flags);
}
JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1send_1key_1event(
JNIEnv *env, jclass cls, jint instance, jint keycode, jboolean down)
{
jni_freerdp_send_key_event(env, cls, instance, keycode, down);
}
JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1send_1unicodekey_1event
(JNIEnv *env, jclass cls, jint instance, jint keycode)
{
jni_freerdp_send_unicodekey_event(env, cls, instance, keycode);
}
JNIEXPORT jstring JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1get_1version(JNIEnv *env, jclass cls)
{
return jni_freerdp_get_version(env, cls);
}

View File

@ -0,0 +1,28 @@
/*
FreeRDP: A Remote Desktop Protocol client.
Android FreeRDP JNI Definitions
Copyright 2010 Marc-Andre Moreau <marcandre.moreau@gmail.com>
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.
*/
#ifndef __ANDROID_FREERDP_JNI_H
#define __ANDROID_FREERDP_JNI_H
#include "com_freerdp_afreerdp_services_LibFreeRDP.h"
#define JAVA_LIBFREERDP_CLASS "com/freerdp/afreerdp/services/LibFreeRDP"
#endif /* __ANDROID_FREERDP_JNI_H */

View File

@ -0,0 +1,125 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_freerdp_afreerdp_services_LibFreeRDP */
#ifndef _Included_com_freerdp_afreerdp_services_LibFreeRDP
#define _Included_com_freerdp_afreerdp_services_LibFreeRDP
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_freerdp_afreerdp_services_LibFreeRDP
* Method: freerdp_new
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1new
(JNIEnv *, jclass);
/*
* Class: com_freerdp_afreerdp_services_LibFreeRDP
* Method: freerdp_free
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1free
(JNIEnv *, jclass, jint);
/*
* Class: com_freerdp_afreerdp_services_LibFreeRDP
* Method: freerdp_connect
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1connect
(JNIEnv *, jclass, jint);
/*
* Class: com_freerdp_afreerdp_services_LibFreeRDP
* Method: freerdp_disconnect
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1disconnect
(JNIEnv *, jclass, jint);
/*
* Class: com_freerdp_afreerdp_services_LibFreeRDP
* Method: freerdp_cancel_connection
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1cancel_1connection
(JNIEnv *, jclass, jint);
/*
* Class: com_freerdp_afreerdp_services_LibFreeRDP
* Method: freerdp_set_connection_info
* Signature: (ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIIZILjava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1set_1connection_1info
(JNIEnv *, jclass, jint, jstring, jstring, jstring, jstring, jint, jint, jint, jint, jboolean, jint, jstring);
/*
* Class: com_freerdp_afreerdp_services_LibFreeRDP
* Method: freerdp_set_performance_flags
* Signature: (IZZZZZZZ)V
*/
JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1set_1performance_1flags
(JNIEnv *, jclass, jint, jboolean, jboolean, jboolean, jboolean, jboolean, jboolean, jboolean);
/*
* Class: com_freerdp_afreerdp_services_LibFreeRDP
* Method: freerdp_set_advanced_settings
* Signature: (ILjava/lang/String;Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1set_1advanced_1settings
(JNIEnv *, jclass, jint, jstring, jstring);
/*
* Class: com_freerdp_afreerdp_services_LibFreeRDP
* Method: freerdp_set_data_directory
* Signature: (ILjava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1set_1data_1directory
(JNIEnv *, jclass, jint, jstring);
/*
* Class: com_freerdp_afreerdp_services_LibFreeRDP
* Method: freerdp_update_graphics
* Signature: (ILandroid/graphics/Bitmap;IIII)Z
*/
JNIEXPORT jboolean JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1update_1graphics
(JNIEnv *, jclass, jint, jobject, jint, jint, jint, jint);
/*
* Class: com_freerdp_afreerdp_services_LibFreeRDP
* Method: freerdp_send_cursor_event
* Signature: (IIII)V
*/
JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1send_1cursor_1event
(JNIEnv *, jclass, jint, jint, jint, jint);
/*
* Class: com_freerdp_afreerdp_services_LibFreeRDP
* Method: freerdp_send_key_event
* Signature: (IIZ)V
*/
JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1send_1key_1event
(JNIEnv *, jclass, jint, jint, jboolean);
/*
* Class: com_freerdp_afreerdp_services_LibFreeRDP
* Method: freerdp_send_unicodekey_event
* Signature: (II)V
*/
JNIEXPORT void JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1send_1unicodekey_1event
(JNIEnv *, jclass, jint, jint);
/*
* Class: com_freerdp_afreerdp_services_LibFreeRDP
* Method: freerdp_get_version
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_freerdp_afreerdp_services_LibFreeRDP_freerdp_1get_1version
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,2 @@
# This file is automatically generated by cmake.
sdk.dir=@ANDROID_SDK@

View File

@ -0,0 +1,11 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system use,
# "ant.properties", and override values to adapt the script to your
# project structure.
# Project target.
target=android-8

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 838 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 707 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 771 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 892 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 506 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 572 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Some files were not shown because too many files have changed in this diff Show More