Added Pepper Farm Simulator sample and updated the README.md.

This commit is contained in:
Tomi Paananen 2014-02-20 16:47:30 +02:00
Родитель 085e79804f
Коммит e046b2b2f4
81 изменённых файлов: 3145 добавлений и 6 удалений

Просмотреть файл

@ -1,7 +1,9 @@
Payment One APK
===============
Simple demonstration application to show how to have Nokia IAP and Google IAB in same application
Simple example application demonstrating how to utilise both Nokia In-App
Payment and Google In-App Billing in the same application. The resulting APK
will run in both Nokia X and Google Android devices.
Building with Eclipse
---------------------
@ -13,13 +15,13 @@ Building with Eclipse
Building with Gradle wrapper
----------------------------
###### Linux & OS X
**Linux & OS X**
```
$ ./gradlew installDebug
```
###### Windows
**Windows**
```
C:\PaymentOneAPK> gradlew installDebug

Просмотреть файл

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

Просмотреть файл

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Pepper Farm Simulator Aidl</name>
<comment></comment>
<projects>
<project>NokiaInappPaymentLib</project>
</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>

Просмотреть файл

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
See the license text file delivered with this project for more information.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.nokia.example.pepperfarm.client"
android:versionCode="1"
android:versionName="Prod" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="16" />
<uses-permission android:name="com.nokia.payment.BILLING"/>
<application
android:name="Pepperfarm"
android:allowBackup="true"
android:icon="@drawable/launchicon"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity android:name="PepperFarmSplashScreen"
android:label="@string/app_name"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="ProductListActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.PRODUCT_LIST" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name="PepperFarmMainScreenActivity"></activity>
</application>
</manifest>

Просмотреть файл

@ -0,0 +1,68 @@
Nokia In-App Payment API sample: Pepper Farm Simulator
======================================================
This Nokia sample application demonstrates how to implement the support for
Nokia In-App Payment enabler. This application contains sample code to:
* Connect to Nokia In-App Payment enabler service
* Check if your application supports In-App billing
* Return product information
* Purchase content
* Consume content
* Restore content
Instructions
--------------------------------------------------------------------------------
Import the project to your IDE. The recommended build target for the project is
Android 4.1.2, API level 16.
Implementation
--------------------------------------------------------------------------------
Description of the classes:
* Package `com.nokia.example.pepperfarm.client`:
* `MainScreenPepperListFragment`: Fragment for the main screen of the
Pepper Farm Simulator. Contains all purchased peppers in a list.
* `PepperFarmMainScreenActivity`: This is the first screen that loads in the
Pepper Farm application. It shows you a list of peppers you have already
purchased and includes buttons allowing you to purchase, restore and
consume peppers.
* `PepperFarmSplashScreen`: Splash screen that is shown when application is
launched for the first time.
* `ProductListActivity`: Activity representing a list of purchasable products.
* `ProductListFragment`: Fragment containing a list of all purchasable peppers.
* Package `com.nokia.example.pepperfarm.client.util`:
* `ProductDetails`: Holds product details response data.
* `Purchase`: Holds purchase and restoration response data.
* Package `com.nokia.example.pepperfarm.iap`:
* `Payment`: This class creates a `ServiceConnection` with Nokia In-App
Payment enabler. Used to do all Nokia In-App Payment enabler specific
actions.
* Package `com.nokia.example.pepperfarm.product`:
* `Config`: Product ID mapping for all purchasable content.
* `Content`: Used to represent a collection of Nokia Store IAP items.
* Package `com.nokia.example.pepperfarm.product.adapters`:
* `ContentListAdapter`: An adapter used to show a list of Peppers you
currently own.
* `ContentPurchaseAdapter`: This adapter is used to display a list of
products that can be purchased.
Known issues
--------------------------------------------------------------------------------
None.
License
--------------------------------------------------------------------------------
See the separate license file provided with this project.

Просмотреть файл

@ -0,0 +1,49 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.7.+'
}
}
apply plugin: 'android'
dependencies {
compile fileTree(dir: 'libs', include: '*.jar')
}
android {
compileSdkVersion 16
buildToolsVersion "18.1.1"
buildTypes {
release {
runProguard false
proguardFile getDefaultProguardFile('proguard-android.txt')
}
}
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
// Move the tests to tests/java, tests/res, etc...
instrumentTest.setRoot('tests')
// Move the build types to build-types/<type>
// For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
// This moves them out of them default location under src/<type>/... which would
// conflict with src/ being used by the main source set.
// Adding new build types or product flavors should be accompanied
// by a similar customization.
debug.setRoot('build-types/debug')
release.setRoot('build-types/release')
}
}

Двоичные данные
PepperFarmSimulator/gradle/wrapper/gradle-wrapper.jar поставляемый Normal file

Двоичный файл не отображается.

6
PepperFarmSimulator/gradle/wrapper/gradle-wrapper.properties поставляемый Normal file
Просмотреть файл

@ -0,0 +1,6 @@
#Wed Feb 05 15:41:42 EET 2014
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=http\://services.gradle.org/distributions/gradle-1.9-all.zip

164
PepperFarmSimulator/gradlew поставляемый Normal file
Просмотреть файл

@ -0,0 +1,164 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

90
PepperFarmSimulator/gradlew.bat поставляемый Normal file
Просмотреть файл

@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

Двоичные данные
PepperFarmSimulator/ic_launcher-web.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 53 KiB

Двоичные данные
PepperFarmSimulator/libs/android-support-v13.jar Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,40 @@
Copyright © 2014 Nokia Corporation. All rights reserved.
Nokia, Nokia Developer, and HERE are trademarks and/or registered trademarks of
Nokia Corporation. Other product and company names mentioned herein may be
trademarks or trade names of their respective owners.
License
Subject to the conditions below, you may use, copy, modify and/or merge copies
of this software and associated content and documentation files (the “Software”)
to test, develop, publish, distribute, sub-license and/or sell new software
derived from or incorporating the Software, solely in connection with Nokia
devices. Some of the documentation, content and/or software maybe licensed under
open source software or other licenses. To the extent such documentation,
content and/or software are included, licenses and/or other terms and conditions
shall apply in addition and/or instead of this notice. The exact terms of the
licenses, disclaimers, acknowledgements and notices are reproduced in the
materials provided, or in other obvious locations. No other license to any other
intellectual property rights is granted herein.
This file, unmodified, shall be included with all copies or substantial portions
of the Software that are distributed in source code form.
The Software cannot constitute the primary value of any new software derived
from or incorporating the Software.
Any person dealing with the Software shall not misrepresent the source of the
Software.
Disclaimer
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE, QUALITY AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES (INCLUDING,
WITHOUT LIMITATION, DIRECT, SPECIAL, INDIRECT, PUNITIVE, CONSEQUENTIAL,
EXEMPLARY AND/ OR INCIDENTAL DAMAGES) OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Nokia Corporation retains the right to make changes to this document at any
time, without notice.

Просмотреть файл

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<lint>
</lint>

Просмотреть файл

@ -0,0 +1,20 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

Просмотреть файл

@ -0,0 +1,15 @@
# 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 edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-16
android.library=false

Двоичные данные
PepperFarmSimulator/res/drawable-hdpi/arrow.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 550 B

Двоичные данные
PepperFarmSimulator/res/drawable-hdpi/bellpepper.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 13 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-hdpi/farm.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 19 KiB

Просмотреть файл

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#D5DDE0"
android:centerColor="#e7e7e8"
android:endColor="#CFCFCF"
android:angle="270" />
</shape>

Просмотреть файл

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#D5DDE0"
android:centerColor="#e7e7e8"
android:endColor="#CFCFCF"
android:angle="270" />
</shape>

Двоичные данные
PepperFarmSimulator/res/drawable-hdpi/habenero.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 13 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-hdpi/ic_launcher.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 5.7 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-hdpi/jalapeno.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 9.9 KiB

Просмотреть файл

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_selected="false"
android:state_pressed="false"
android:drawable="@drawable/gradient_background" />
<item android:state_pressed="true"
android:drawable="@drawable/gradient_background_on_hover" />
<item android:state_selected="true"
android:state_pressed="false"
android:drawable="@drawable/gradient_background_on_hover" />
</selector>

Двоичные данные
PepperFarmSimulator/res/drawable-hdpi/pepperseed.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 15 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-hdpi/pepperspray.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 8.0 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-hdpi/placeholder.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 107 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-hdpi/splashscreen.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 507 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-ldpi/bellpepper.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 6.4 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-ldpi/farm.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 7.7 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-ldpi/habenero.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 6.3 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-ldpi/ic_launcher.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 9.9 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-ldpi/jalapeno.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 5.4 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-ldpi/launchicon.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 9.9 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-ldpi/pepperseed.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 6.7 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-ldpi/pepperspray.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 4.3 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-ldpi/splashscreen.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 507 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-mdpi/bellpepper.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 9.7 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-mdpi/farm.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 13 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-mdpi/habenero.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 9.4 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-mdpi/ic_launcher.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 3.1 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-mdpi/jalapeno.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 7.4 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-mdpi/pepperseed.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 10 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-mdpi/pepperspray.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 6.0 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-mdpi/splashscreen.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 507 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-xhdpi/bellpepper.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 20 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-xhdpi/farm.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 32 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-xhdpi/habenero.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 18 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-xhdpi/ic_launcher.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 7.8 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-xhdpi/jalapeno.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 14 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-xhdpi/pepperseed.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 23 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-xhdpi/pepperspray.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 11 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-xhdpi/splashscreen.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 507 KiB

Двоичные данные
PepperFarmSimulator/res/drawable-xxhdpi/ic_launcher.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 12 KiB

Просмотреть файл

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
See the license text file delivered with this project for more information.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="@+id/product_list"
android:name="com.nokia.example.pepperfarm.client.ProductListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/get_new_peppers_link"
tools:context=".ProductListActivity"
tools:layout="@android:layout/list_content" />
<TextView
android:id="@+id/get_new_peppers_link"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="@string/new_peppers"
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>

Просмотреть файл

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
See the license text file delivered with this project for more information.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dip" >
<!-- ListRow Left side Thumbnail image -->
<LinearLayout
android:id="@+id/thumbnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginRight="5dip"
android:padding="3dip" >
<ImageView
android:id="@+id/list_image"
android:layout_width="60dip"
android:layout_height="60dip"
android:contentDescription="@string/app_name"
android:src="@drawable/farm"
android:visibility="gone" />
</LinearLayout>
<!-- Rightend Arrow -->
<!-- IAP Name -->
<Button
android:id="@+id/start_purchase"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="Buy" />
<TextView
android:id="@+id/iapName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toLeftOf="@+id/start_purchase"
android:layout_toRightOf="@+id/thumbnail"
android:text="@string/appname"
android:textSize="20sp" />
<TextView
android:id="@+id/product_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/iapName"
android:layout_below="@+id/iapName"
android:layout_toLeftOf="@+id/start_purchase"
android:text="@string/product_description"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/product_description"
android:layout_toLeftOf="@+id/start_purchase"
android:text="@string/price"
android:textSize="15sp" />
</RelativeLayout>

Просмотреть файл

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
See the license text file delivered with this project for more information.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="8dp"
android:paddingRight="8dp">
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawSelectorOnTop="false" />
<TextView android:id="@android:id/empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="No peppers"/>
<TextView
android:id="@+id/get_new_peppers_link"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/get_new_peppers_underline"
android:textAppearance="?android:attr/textAppearanceMedium" />
<ProgressBar
android:id="@+id/fetching_peppers_progressbar"
style="?android:attr/progressBarStyleLarge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone" />
<TextView
android:id="@+id/fetching_peppers_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/get_restorables"
android:textAppearance="?android:attr/textAppearanceMedium"
android:visibility="gone" />
</LinearLayout>

Просмотреть файл

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
See the license text file delivered with this project for more information.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/buy_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginRight="14dp"
android:text="@string/buy_peppers" />
<TextView
android:id="@+id/your_peppers"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/buy_button"
android:layout_alignBottom="@+id/buy_button"
android:layout_alignParentLeft="true"
android:text="@string/owned_peppers"
android:textAppearance="?android:attr/textAppearanceLarge" />
<fragment
android:id="@+id/product_list"
android:name="com.nokia.example.pepperfarm.client.MainScreenPepperListFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/fetch_restorable_products"
android:layout_below="@+id/buy_button"
class="com.nokia.example.pepperfarm.client.MainScreenPepperListFragment"
tools:layout="@layout/pepper_list_row_view" />
<Button
android:id="@+id/reset_purchases"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:text="@string/reset_purchase" />
<Button
android:id="@+id/fetch_restorable_products"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/reset_purchases"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:text="@string/fetch_all_restorables" />
</RelativeLayout>

Просмотреть файл

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
See the license text file delivered with this project for more information.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageView android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="@drawable/splashscreen"
android:contentDescription="@string/splash_screen_description"/>
</LinearLayout>

Просмотреть файл

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
See the license text file delivered with this project for more information.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dip" >
<TextView
android:id="@+id/pepper_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/pepperName"
android:layout_below="@+id/pepperName"
android:layout_toLeftOf="@+id/eat_pepper"
android:lines="2"
android:text="@string/pepper_description"
android:textSize="12sp"
android:visibility="gone" />
<Button
android:id="@+id/eat_pepper"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:paddingTop="10dp"
android:text="@string/consume_pepper" />
<ImageView
android:id="@+id/list_image"
android:layout_width="120dip"
android:layout_height="120dip"
android:layout_alignRight="@+id/pepperName"
android:layout_below="@+id/pepper_description"
android:contentDescription="@string/pepper_name"
android:src="@drawable/farm"
android:visibility="gone" />
<TextView
android:id="@+id/itemcount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/pepperName"
android:layout_alignBottom="@+id/pepperName"
android:layout_toRightOf="@+id/pepperName" />
<TextView
android:id="@+id/pepperName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/eat_pepper"
android:layout_alignBottom="@+id/eat_pepper"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@+id/eat_pepper"
android:text="@string/pepper_name"
android:textSize="20sp" />
</RelativeLayout>

Просмотреть файл

@ -0,0 +1,11 @@
<resources>
<!--
Base application theme for API 11+. This theme completely replaces
AppBaseTheme from res/values/styles.xml on API 11+ devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Holo">
<!-- API 11 theme customizations can go here. -->
</style>
</resources>

Просмотреть файл

@ -0,0 +1,12 @@
<resources>
<!--
Base application theme for API 14+. This theme completely replaces
AppBaseTheme from BOTH res/values/styles.xml and
res/values-v11/styles.xml on API 14+ devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Holo">
<!-- API 14 theme customizations can go here. -->
</style>
</resources>

Просмотреть файл

@ -0,0 +1,11 @@
<!--
Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
See the license text file delivered with this project for more information.
-->
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>

Просмотреть файл

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
See the license text file delivered with this project for more information.
-->
<resources>
<string name="app_name">Pepper Farm Simulator</string>
<string name="title_product_detail">Product Detail</string>
<string name="action_settings">Settings</string>
<string name="appname">appName</string>
<string name="price">price</string>
<string name="your_peppers">Your Items</string>
<string name="buy_peppers">Buy Peppers!</string>
<string name="pepper_name">Pepper Name</string>
<string name="pepper_description">Pepper Description</string>
<string name="eat_pepper">Consume Pepper</string>
<string name="splash_screen_description">Pepper Farm Simulator Splash Screen</string>
<string name="product_description">Product description</string>
<string name="no_peppers">No peppers</string>
<string name="reset_purchase">Reset purchases</string>
<string name="owned_peppers">Your peppers</string>
<string name="new_peppers">New peppers</string>
<string name="consume_pepper">Consume</string>
<string name="get_new_peppers_string">Get New Peppers</string>
<string name="get_new_peppers_underline"><u>Get New Peppers</u></string>
<string name="pepper_farm">Pepper Farm</string>
<string name="pepper_seeds">Pepper Seeds</string>
<string name="jalapeno">Jalapeno</string>
<string name="sweet_bell">Sweet Bell</string>
<string name="habenero">Habenero</string>
<string name="pepper_spray">Pepper Spray</string>
<string name="pepper_farm_description">Your Pepper Farm. Use it to grow new peppers.</string>
<string name="pepper_seeds_description">A good start to a farm.</string>
<string name="jalapeno_description">Looking for something a little more spicy? Try the Jalapeno.</string>
<string name="sweet_bell_description">Jumpstart your farm with a Sweet Bell</string>
<string name="habenero_description">A good middle ground.</string>
<string name="pepper_spray_description">Keep the bears away.</string>
<string name="get_restorables">Fetching owned peppers</string>
<string name="fetch_all_restorables">Fetch restorable products</string>
</resources>

Просмотреть файл

@ -0,0 +1,24 @@
<!--
Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
See the license text file delivered with this project for more information.
-->
<resources>
<!--
Base application theme, dependent on API level. This theme is replaced
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Holo">
<!--
Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here.
-->
</style>
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
</style>
</resources>

Просмотреть файл

@ -0,0 +1,190 @@
/**
* Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
* See the license text file delivered with this project for more information.
*/
package com.nokia.example.pepperfarm.client;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.nokia.example.pepperfarm.product.Content;
import com.nokia.example.pepperfarm.product.Content.Product;
import com.nokia.example.pepperfarm.product.adapters.ContentListAdapter;
import java.util.List;
/**
* This is the Fragment for the main screen of the Pepper Farm Simulator.
* Mostly it's job is to set up the ContentListAdapter which does the real work of determining how to
* display the list of purchased products.
*/
public class MainScreenPepperListFragment extends ListFragment {
public static TextView getpeppers;
public static View fetch_peppers_progressbar;
public static TextView fetching_peppers;
/**
* The fragment's current callback object, which is notified of list item
* clicks.
*/
private Callbacks mCallbacks = sDummyCallbacks;
public static MainScreenPepperListFragment reference;
private final static String LOG_TAG = MainScreenPepperListFragment.class.getCanonicalName();
/**
* The adapter used to display the list of peppers that have already been purchased.
*/
public ArrayAdapter<Product> adapter;
/**
* A callback interface that all activities containing this fragment must
* implement. This mechanism allows activities to be notified of item
* selections.
*/
public interface Callbacks {
/**
* Callback for when an item has been selected.
*
* @param id
*/
public void onItemSelected(String id);
}
/**
* A dummy implementation of the {@link Callbacks} interface that does
* nothing. Used only when this fragment is not attached to an activity.
*/
private static Callbacks sDummyCallbacks = new Callbacks() {
@Override
public void onItemSelected(String id) {
}
};
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public MainScreenPepperListFragment() {
}
/**
* Renders a Fragment representing one pepper in the list that has already been purchased by the user.
* Also is responsible for updating the list
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
reference = this;
List<Product> purchasedItems = Content.getPurchasedItems();
if (purchasedItems.isEmpty()) {
//We need to display some text saying you have no peppers.
adapter = new ContentListAdapter(getActivity(), R.layout.pepper_list_row_view, purchasedItems);
setListAdapter(adapter);
} else {
adapter = new ContentListAdapter(getActivity(), R.layout.pepper_list_row_view, purchasedItems);
setListAdapter(adapter);
}
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
fetching_peppers = (TextView) view.findViewById(R.id.fetching_peppers_text);
fetch_peppers_progressbar = view.findViewById(R.id.fetching_peppers_progressbar);
//Get new peppers linkbutton
getpeppers = (TextView) view.findViewById(R.id.get_new_peppers_link);
getpeppers.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("android.intent.action.PRODUCT_LIST");
startActivity(intent);
}
});
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.main_screen_pepper_list_fragment, container, false);
}
/**
* Used for error checking to make sure that any Activity attaching to this fragment properly supports
* Callbacks.
*/
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Activities containing this fragment must implement its callbacks.
if (!(activity instanceof Callbacks)) {
throw new IllegalStateException(
"Activity must implement fragment's callbacks.");
}
mCallbacks = (Callbacks) activity;
}
@Override
public void onDetach() {
super.onDetach();
// Reset the active callbacks interface to the dummy implementation.
mCallbacks = sDummyCallbacks;
}
/**
* Notifies the activity that an item has been selected.
*/
@Override
public void onListItemClick(ListView listView, View view, int position,
long id) {
super.onListItemClick(listView, view, position, id);
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mCallbacks.onItemSelected(Content.ITEMS.get(position).productId);
}
/**
* On resume of this Fragment, we need to refresh the list of peppers available to the user.
* This is because peppers could have been bought and the view may not have an updated list of purchased peppers.
* This is a little inefficient but simple enough for demonstration purposes. If you had a large list of items to display,
* you may want to consider having a listener that gets updated when items are purchased. The listener could then update the adapter
* only when items are purchased or consumed.
*/
@Override
public void onResume() {
super.onResume();
if (adapter != null) {
adapter.clear();
adapter.addAll(Content.getPurchasedItems());
adapter.notifyDataSetChanged();
} else {
System.out.println("Adapter is null");
}
Log.d(LOG_TAG, "List Frag Resumed.");
}
}

Просмотреть файл

@ -0,0 +1,136 @@
/**
* Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
* See the license text file delivered with this project for more information.
*/
package com.nokia.example.pepperfarm.client;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import com.nokia.example.pepperfarm.iap.Payment;
import com.nokia.example.pepperfarm.product.Config;
import com.nokia.example.pepperfarm.product.Content;
import com.nokia.example.pepperfarm.product.Content.Product;
import java.security.GeneralSecurityException;
/**
* This is the first screen that loads in the Pepper Farm application.
* It shows you a list of Peppers you have already purchased and includes a button allowing you to purchase more Peppers.
*/
public class PepperFarmMainScreenActivity extends FragmentActivity implements MainScreenPepperListFragment.Callbacks {
/**
* Used for logging so you know exactly where the logging messages are coming from.
*/
private final static String LOG_TAG = PepperFarmMainScreenActivity.class.getCanonicalName();
/**
* A public string representing the full path name of this file. This is used in order to let the Enabler
* know where to return to after a purchase request is completed.
*/
public final static String PEPPER_FARM_MAIN_SCREEN_ACTIVITY =
"com.nokia.example.pepperfarm.client.PepperFarmMainScreenActivity";
public static Payment purchaseHandler;
/**
* Sets up the UI container for the Pepper Farm Main Screen
* <p/>
* As part of the set up, we use the Nokia In App Payment Library to request
* the Enabler to return pricing data for each in app purchasable item we are selling.
* For simplicity, this is done on the Main (UI) thread. Ideally you could spawn a new thread to set up
* the NPayProductPricepoint objects and make the product data request to the library.
*/
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(LOG_TAG, "Pepper Farm Main Screen Activity Created");
Config.setVersiontitle(this);
setContentView(R.layout.pepper_farm_main_view);
Button buyPepperButton = (Button) findViewById(R.id.buy_button);
buyPepperButton.setVisibility(View.INVISIBLE);
View product_list = findViewById(R.id.product_list);
product_list.refreshDrawableState();
//Listener for the Purchase Requisition button
buyPepperButton.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent("android.intent.action.PRODUCT_LIST");
startActivity(intent);
}
});
Button resetPurchases = (Button) findViewById(R.id.reset_purchases);
resetPurchases.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
Log.i("resetPurchases", "Consuming all items");
for (Product product : Content.ITEMS) {
product.consumeItem();
}
if (MainScreenPepperListFragment.reference.adapter != null) {
MainScreenPepperListFragment.reference.adapter.clear();
MainScreenPepperListFragment.reference.adapter.notifyDataSetChanged();
}
}
});
Button fetchRestorables = (Button) findViewById(R.id.fetch_restorable_products);
fetchRestorables.setOnClickListener
(new Button.OnClickListener() {
public void onClick(View v) {
Log.i("fetchRestorables", "Fetching all restorable items");
purchaseHandler.getPurchases(true);
}
});
}
/**
* This method is used to allow a fragment to notify the controlling activity that a specific
* item in the list has been selected. It could be used in layouts where you want to display the list
* of items, and specific information about one item on the same screen, and need a way of displaying
* to the user which item they have selected. Pepper Farm Simulator does not use this as each item
* selection brings you to an entirely new activity.
*/
@Override
public void onItemSelected(String id) {
}
@Override
public void onStart() {
Log.i(LOG_TAG, "onStart");
super.onStart();
try {
if (purchaseHandler != null) {
if (!purchaseHandler.npayAvailable) {
purchaseHandler.connectToService(this);
}
} else {
purchaseHandler = new Payment(this);
purchaseHandler.connectToService(this);
Log.i(LOG_TAG, "Npay initialization SUCCESS, waiting for service connection");
}
} catch (GeneralSecurityException e) {
Log.e(LOG_TAG, "Npay initialization FAILED: " + e.getMessage(), e);
}
}
@Override
public void onStop() {
Log.i(LOG_TAG, "onStop");
super.onStop();
purchaseHandler.cleanUp();
}
}

Просмотреть файл

@ -0,0 +1,53 @@
/**
* Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
* See the license text file delivered with this project for more information.
*/
package com.nokia.example.pepperfarm.client;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.Window;
import android.widget.ProgressBar;
import com.nokia.example.pepperfarm.product.Content;
/**
* A splash screen used to give some time to complete the first get Product data call.
* In a real game this may not be necessary as it is less likely (but still possible) that the user will get to any screens requiring
* IAP Product data before the call returns.
*/
public class PepperFarmSplashScreen extends Activity {
private final int SECONDS_DELAYED = 1;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
//Show a little spinning wheel while we load.
final ProgressDialog progressDialog = ProgressDialog.show(this, null, null);
progressDialog.setContentView(new ProgressBar(this));
setContentView(R.layout.pepper_farm_splash_screen);
if (Content.products_initialized == false) {
Content.initializeProducts(getResources());
}
new Handler().postDelayed(new Runnable() {
public void run() {
startActivity(new Intent(PepperFarmSplashScreen.this, PepperFarmMainScreenActivity.class));
progressDialog.dismiss();
finish();
}
}, SECONDS_DELAYED * 1000);
}
}

Просмотреть файл

@ -0,0 +1,23 @@
/**
* Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
* See the license text file delivered with this project for more information.
*/
package com.nokia.example.pepperfarm.client;
import android.app.Application;
public class Pepperfarm extends Application {
static Pepperfarm pepperfarm;
public Pepperfarm() {
pepperfarm = this;
}
public static Pepperfarm getContext() {
return pepperfarm;
}
}

Просмотреть файл

@ -0,0 +1,183 @@
/**
* Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
* See the license text file delivered with this project for more information.
*/
package com.nokia.example.pepperfarm.client;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.NavUtils;
import android.util.Log;
import android.view.MenuItem;
import com.nokia.example.pepperfarm.client.util.Purchase;
import com.nokia.example.pepperfarm.iap.Payment;
import com.nokia.example.pepperfarm.product.Config;
import com.nokia.example.pepperfarm.product.Content;
import com.nokia.example.pepperfarm.product.Content.Product;
import java.security.GeneralSecurityException;
/**
* An activity representing a list of purchasable IAP Products.
* Much of the work of displaying the actual list is handled by ProductListFragment.java and especially ContentPurchaseAdapter,
* which extends android.widget.ArrayAdapter
* <p/>
* This activity also implements the required
* {@link ProductListFragment.Callbacks} interface to listen for item
* selections.
*/
public class ProductListActivity extends FragmentActivity implements
ProductListFragment.Callbacks {
public static Activity reference;
public static Payment purchaseHandler;
/**
* Used for logging so you know exactly where the logging messages are coming from.
*/
private final static String LOG_TAG = ProductListActivity.class.getCanonicalName();
/**
* Sets version title and enables the back button.
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(LOG_TAG, " onCreate");
Config.setVersiontitle(this);
setContentView(R.layout.activity_product_list);
reference = this;
// Show the Up (Back) button in the action bar.
getActionBar().setDisplayHomeAsUpEnabled(true);
}
/**
* Callback method from {@link ProductListFragment.Callbacks}
*/
@Override
public void onItemSelected(String id) {
}
/**
* This method is used to handle the Up (Back) button.
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// This ID represents the Home or Up button. In the case of this
// activity, the Up button is shown. Use NavUtils to allow users
// to navigate up one level in the application structure. For
// more details, see the Navigation pattern on Android Design:
//
// http://developer.android.com/design/patterns/navigation.html#up-vs-back
//
NavUtils.navigateUpTo(this, new Intent(this,
MainScreenPepperListFragment.class));
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* Handles the purchase response.
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
/*
* Verify that onActivityResult was successful,
*/
if (resultCode == Activity.RESULT_OK) {
//Verify that the purchase was successful,
int responseCode = data.getIntExtra("RESPONSE_CODE", Payment.RESULT_ERR);
try {
switch (responseCode) {
case Payment.RESULT_OK:
//Unlock content
if (data.getStringExtra("INAPP_PURCHASE_DATA") != null) {
Purchase purchaseInfo = new Purchase(data.getStringExtra("INAPP_PURCHASE_DATA"));
purchaseHandler.setPurchaseInProgress(Payment.KEY_NOT_IN_PROGRESS);
Product purchasedProduct = Content.ITEM_MAP.get(purchaseInfo.getProductId());
purchasedProduct.setPurchased(purchaseInfo);
}
if (ProductListFragment.purchaseListAdapter != null) {
ProductListFragment.purchaseListAdapter.notifyDataSetChanged();
}
break;
case Payment.RESULT_ITEM_ALREADY_OWNED:
Log.i(LOG_TAG, " User already bought the item");
//Item has already been bought, but we still made it available for purchasing. Need to sync all purchases.
purchaseHandler.getPurchases(true);
break;
case Payment.RESULT_USER_CANCELED:
//User pressed cancel in purchase dialog.
Log.i(LOG_TAG, "User canceled purchase dialog");
break;
default:
Log.i(LOG_TAG, "Purchase failed: " + responseCode);
break;
}
} catch (Exception e) {
Log.i(LOG_TAG, "Exception while parsing payment response: " + e.getMessage());
e.printStackTrace();
}
}
}
private void connectToService() {
try {
if (purchaseHandler != null) {
if (!purchaseHandler.npayAvailable) {
purchaseHandler.connectToService(this);
}
} else {
purchaseHandler = new Payment(this);
purchaseHandler.connectToService(this);
Log.i(LOG_TAG, "Npay initialization SUCCESS, waiting for service connection");
}
} catch (GeneralSecurityException e) {
Log.e(LOG_TAG, "Npay initialization FAILED: " + e.getMessage(), e);
}
}
@Override
public void onStart() {
Log.i(LOG_TAG, "onStart");
super.onStart();
connectToService();
}
@Override
public void onDestroy() {
Log.i(LOG_TAG, "onDestroy");
super.onStop();
purchaseHandler.cleanUp();
}
}

Просмотреть файл

@ -0,0 +1,130 @@
/**
* Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
* See the license text file delivered with this project for more information.
*/
package com.nokia.example.pepperfarm.client;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.View;
import android.widget.ListView;
import com.nokia.example.pepperfarm.product.Content;
import com.nokia.example.pepperfarm.product.adapters.ContentPurchaseAdapter;
/**
* A list fragment representing a list of Products.
* <p/>
* Activities containing this fragment MUST implement the {@link Callbacks}
* interface.
*/
public class ProductListFragment extends ListFragment {
/**
* The fragment's current callback object, which is notified of list item
* clicks.
*/
private Callbacks mCallbacks = sDummyCallbacks;
/**
* The ContentPurchaseAdapter extends android.widget.ArrayAdapter and is responsible for displaying a list of purchasable items.
* If an item has already been purchased, it will appear greyed out.
*/
public static ContentPurchaseAdapter purchaseListAdapter = null;
/**
* A callback interface that all activities containing this fragment must
* implement. This mechanism allows activities to be notified of item
* selections.
*/
public interface Callbacks {
/**
* Callback for when an item has been selected.
*
* @param id The id of the item selected
*/
public void onItemSelected(String id);
}
/**
* A dummy implementation of the {@link Callbacks} interface that does
* nothing. Used only when this fragment is not attached to an activity.
*/
private static Callbacks sDummyCallbacks = new Callbacks() {
@Override
public void onItemSelected(String id) {
}
};
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public ProductListFragment() {
}
/**
* Sets the List Adapter to ContentPurchaseAdapter.
* <p/>
* ContentPurchaseAdapter does the real work of setting the UI for each
* Product in the list, through use of its getView method.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
purchaseListAdapter = new ContentPurchaseAdapter(getActivity(), R.layout.activity_product_list_row_view, Content.ITEMS);
setListAdapter(purchaseListAdapter);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
/**
* Used for error checking to make sure that any Activity attaching to this fragment properly supports
* Callbacks.
*/
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// Activities containing this fragment must implement its callbacks.
if (!(activity instanceof Callbacks)) {
throw new IllegalStateException(
"Activity must implement fragment's callbacks.");
}
mCallbacks = (Callbacks) activity;
}
@Override
public void onDetach() {
super.onDetach();
// Reset the active callbacks interface to the dummy implementation.
mCallbacks = sDummyCallbacks;
}
/**
* Notifies the activity that an item has been selected.
*/
@Override
public void onListItemClick(ListView listView, View view, int position,
long id) {
super.onListItemClick(listView, view, position, id);
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mCallbacks.onItemSelected(Content.ITEMS.get(position).productId);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
}

Просмотреть файл

@ -0,0 +1,92 @@
/**
* Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
* See the license text file delivered with this project for more information.
*/
package com.nokia.example.pepperfarm.client.util;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Represents an in-app product's listing details.
*/
public class ProductDetails {
String mProductId;
String mType;
String mPrice;
String mCurrency;
String mPriceFormatted;
String mTitle;
String mDescription;
String mJson;
String mPurchaseToken;
boolean mRestorable;
public ProductDetails(String jsonProductDetails) throws JSONException {
mJson = jsonProductDetails;
JSONObject o = new JSONObject(mJson);
//optString returns empty string by default
mProductId = o.optString("productId");
mType = o.optString("type");
mPrice = o.optString("priceValue");
mCurrency = o.optString("currency");
mPriceFormatted = o.optString("price");
mTitle = o.optString("title");
mDescription = o.optString("description");
mPurchaseToken = o.optString("purchaseToken");
mRestorable = false;
if (o.optString("restorable").equalsIgnoreCase("true")) {
mRestorable = true;
}
}
public String getProductId() {
return mProductId;
}
public String getType() {
return mType;
}
public String getPrice() {
return mPrice;
}
public String getCurrency() {
return mCurrency;
}
public String getPriceFormatted() {
return mPriceFormatted;
}
public String getTitle() {
return mTitle;
}
public String getDescription() {
return mDescription;
}
public String getPurchaseToken() {
return mPurchaseToken;
}
public boolean getRestorable() {
return mRestorable;
}
public void setRestore(boolean restore) {
mRestorable = restore;
}
@Override
public String toString() {
return "Product details:" + mJson;
}
}

Просмотреть файл

@ -0,0 +1,71 @@
/**
* Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
* See the license text file delivered with this project for more information.
*/
package com.nokia.example.pepperfarm.client.util;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Represents an in-app billing purchase.
*/
public class Purchase {
String mProductId;
String mDeveloperPayload;
String mToken;
String mOriginalJson;
public Purchase(String jsonPurchaseInfo) throws JSONException {
if (jsonPurchaseInfo != null) {
mOriginalJson = jsonPurchaseInfo;
JSONObject o = new JSONObject(mOriginalJson);
mProductId = o.optString("productId");
mDeveloperPayload = o.optString("developerPayload");
mToken = o.optString("purchaseToken");
} else {
mOriginalJson = "";
mProductId = "";
mDeveloperPayload = "";
mToken = "";
}
}
public String getProductId() {
return mProductId;
}
public String getDeveloperPayload() {
return mDeveloperPayload;
}
public String getToken() {
return mToken;
}
public String getOriginalJson() {
return mOriginalJson;
}
public void setProductId(String input) {
mProductId = input;
}
public void setDeveloperPayload(String input) {
mDeveloperPayload = input;
}
public void setToken(String input) {
mToken = input;
}
public void setOriginalJson(String input) {
mOriginalJson = input;
}
@Override
public String toString() {
return "PurchaseInfo:" + mOriginalJson;
}
}

Просмотреть файл

@ -0,0 +1,449 @@
/**
* Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
* See the license text file delivered with this project for more information.
*/
package com.nokia.example.pepperfarm.iap;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.*;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import com.nokia.example.pepperfarm.client.MainScreenPepperListFragment;
import com.nokia.example.pepperfarm.client.ProductListFragment;
import com.nokia.example.pepperfarm.client.util.ProductDetails;
import com.nokia.example.pepperfarm.client.util.Purchase;
import com.nokia.example.pepperfarm.product.Content;
import com.nokia.example.pepperfarm.product.Content.Product;
import com.nokia.payment.iap.aidl.INokiaIAPService;
import org.json.JSONException;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
public class Payment implements ServiceConnection {
public Activity activity;
public INokiaIAPService npay;
public boolean npayAvailable = false;
public static boolean purchases_asked = false;
public static final String SHARED_PREFERENCE_KEY = "IAPDATA";
public static final String PRODUCT_ID_KEY = "PRODUCTKEY";
public static final String KEY_NOT_IN_PROGRESS = "NOTINPROGRESS";
public static final String PREFLOAD_FAILED = "FAIL";
public static final int RESULT_OK = 0;// - success
public static final int RESULT_USER_CANCELED = 1;// - user pressed back or canceled a dialog
public static final int RESULT_BILLING_UNAVAILABLE = 3;// - this billing API version is not supported for the type requested or billing is otherwise impossible (for example there is no SIM card inserted)
public static final int RESULT_ITEM_UNAVAILABLE = 4;// - requested ProductID is not available for purchase
public static final int RESULT_DEVELOPER_ERROR = 5;// - invalid arguments provided to the API
public static final int RESULT_ERROR = 6;// - Fatal error during the API action
public static final int RESULT_ITEM_ALREADY_OWNED = 7;// - Failure to purchase since item is already owned
public static final int RESULT_ITEM_NOT_OWNED = 8;// - Failure to consume since item is not owned
public static final int RESULT_NO_SIM_CARD = 9;
public static final int RESULT_ERR = -100; //Used as a default value for Bundle.getInt, not part of the API
public static String PURCHASE_IN_PROGRESS_FOR_PRODUCT = "";
private static String ITEM_TYPE_INAPP = "inapp";
//This is the expected SHA1 finger-print in HEX format
private static final String EXPECTED_SHA1_FINGERPRINT = "C476A7D71C4CB92641A699C1F1CAC93CA81E0396";
private static final String ENABLER_PACKAGENAME = "com.nokia.payment.iapenabler";
/**
* Constructor of the Payment object. Needs to be initialized to access NIAP methods.
*
* @param context - The activity where Payment object is initialized
*/
public Payment(Context context) {
}
/**
* Binds to Nokia in-app payment service.
*
* @param ctx
* @throws GeneralSecurityException If Nokia In-App payment enabler fingerprint is not valid
*/
public void connectToService(Context ctx) throws GeneralSecurityException {
activity = (Activity) ctx;
//Verifies enabler fingerprint
if (!verifyFingreprint()) {
npayAvailable = false;
errorAlert("Nokia In-App Payment Enabler is not available.");
throw new GeneralSecurityException("Enabler fingerprint incorrect. Billing unavailable");
} else {
//Enabler fingerprint OK. Continue with binding.
Intent paymentEnabler = new Intent("com.nokia.payment.iapenabler.InAppBillingService.BIND");
paymentEnabler.setPackage(ENABLER_PACKAGENAME);
activity.bindService(paymentEnabler, this, Context.BIND_AUTO_CREATE);
}
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
npay = INokiaIAPService.Stub.asInterface(service);
Log.i("onServiceConnected", "IAP service connected");
npayAvailable = true;
if (isBillingAvailable()) {
getPurchases(false);
fetchPrices();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
/**
* Checks SHA1 fingerprint of the enabler
*
* @return true if signature matches, false if package is not found or signature does not match.
*/
private boolean verifyFingreprint() {
try {
PackageInfo info = activity.getBaseContext().getPackageManager().getPackageInfo(ENABLER_PACKAGENAME, PackageManager.GET_SIGNATURES);
if (info.signatures.length == 1) {
byte[] cert = info.signatures[0].toByteArray();
MessageDigest digest;
digest = MessageDigest.getInstance("SHA1");
byte[] ENABLER_FINGERPRINT = digest.digest(cert);
byte[] EXPECTED_FINGERPRINT = hexStringToByteArray(EXPECTED_SHA1_FINGERPRINT);
if (Arrays.equals(ENABLER_FINGERPRINT, EXPECTED_FINGERPRINT)) {
Log.i("isBillingAvailable", "NIAP signature verified");
return true;
}
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NameNotFoundException e) {
e.printStackTrace();
}
return false;
}
private static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
}
return data;
}
public boolean isBillingAvailable() {
boolean isAvailable = false;
try {
int responseCode = RESULT_ERR;
if (npayAvailable)
responseCode = npay.isBillingSupported(1, activity.getPackageName(), ITEM_TYPE_INAPP);
switch (responseCode) {
case RESULT_OK:
isAvailable = true;
break;
case RESULT_NO_SIM_CARD:
errorAlert("No SIM. Please Insert SIM card.");
break;
case RESULT_ERR:
errorAlert("Nokia In-App Payment Enabler is not available.");
break;
default:
errorAlert("Billing is not supported. " + responseCode);
break;
}
} catch (RemoteException e) {
Log.e("isBillingAvailable", e.getMessage(), e);
errorAlert("Billing is not supported. " + e.getMessage());
}
return isAvailable;
}
/**
* Fetches the prices asynchronously
*/
public void fetchPrices() {
if (!isBillingAvailable())
return;
for (Product p : Content.ITEMS) {
if (p.getPrice() != "") {
Log.i("fetchPrices", "Prices already available. Not fetching.");
return;
}
}
AsyncTask<Void, String, Void> pricesTask = new AsyncTask<Void, String, Void>() {
@Override
protected Void doInBackground(Void... params) {
ArrayList<String> productIdArray = new ArrayList<String>(Content.ITEM_MAP.keySet());
Bundle productBundle = new Bundle();
productBundle.putStringArrayList("ITEM_ID_LIST", productIdArray);
try {
Bundle priceInfo = npay.getProductDetails(1, activity.getPackageName(), ITEM_TYPE_INAPP, productBundle);
if (priceInfo.getInt("RESPONSE_CODE", RESULT_ERR) == RESULT_OK) {
ArrayList<String> productDetailsList = priceInfo.getStringArrayList("DETAILS_LIST");
for (String productDetails : productDetailsList) {
parseProductDetails(productDetails);
}
} else {
Log.e("fetchPrices", "PRICE - priceInfo was not ok: Result was: " + priceInfo.getInt("RESPONSE_CODE", -100));
}
} catch (JSONException e) {
Log.e("fetchPrices", "PRODUCT DETAILS PARSING EXCEPTION: " + e.getMessage(), e);
} catch (RemoteException e) {
Log.e("fetchPrices", "PRICE EXCEPTION: " + e.getMessage(), e);
}
return null;
}
private void parseProductDetails(String productDetails) throws JSONException {
ProductDetails details = new ProductDetails(productDetails);
Log.i("fetchPrices", productDetails);
Product p = Content.ITEM_MAP.get(details.getProductId());
if (p != null) {
p.setPrice(details.getPriceFormatted());
Log.i("fetchPrices", "PRICE RECEIVED - " + details.getPrice() + " " + details.getCurrency());
} else {
Log.i("fetchPrices", "Unable to set price for product " + details.getProductId() + ". Product not found.");
}
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
if (ProductListFragment.purchaseListAdapter != null) {
ProductListFragment.purchaseListAdapter.notifyDataSetChanged();
}
if (MainScreenPepperListFragment.reference.adapter != null) {
MainScreenPepperListFragment.reference.adapter.notifyDataSetChanged();
}
}
};
pricesTask.execute();
}
/**
* Check the products that we have already purchased
*/
public void getPurchases(boolean ignoreLifeCycleCheck) {
if (!isBillingAvailable())
return;
if (ignoreLifeCycleCheck == false) {
if (purchases_asked) {
Log.i("getPurchases", "Restorables already asked.");
return;
}
}
MainScreenPepperListFragment.getpeppers.setVisibility(View.INVISIBLE);
MainScreenPepperListFragment.fetch_peppers_progressbar.setVisibility(View.VISIBLE);
MainScreenPepperListFragment.fetching_peppers.setVisibility(View.VISIBLE);
AsyncTask<Void, String, Void> restoreTask = new AsyncTask<Void, String, Void>() {
@Override
protected Void doInBackground(Void... params) {
ArrayList<String> productIdArray = new ArrayList<String>(Content.ITEM_MAP.keySet());
Bundle productBundle = new Bundle();
productBundle.putStringArrayList("ITEM_ID_LIST", productIdArray);
try {
Bundle purchases = npay.getPurchases(1, activity.getPackageName(), ITEM_TYPE_INAPP, productBundle, null);
Log.i("getPurchases", "GET PURCHASES RESPONSE CODE: " + purchases.getInt("RESPONSE_CODE", RESULT_ERR));
if (purchases.getInt("RESPONSE_CODE", RESULT_ERR) == RESULT_OK) {
ArrayList<String> purchaseDataList = purchases.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
for (String purchaseData : purchaseDataList) {
parsePurchaseData(purchaseData);
}
purchases_asked = true;
} else {
Log.e("getPurchases", "GET PURCHASES - response was not ok: Result was: " + purchases.getInt("RESPONSE_CODE", RESULT_ERR));
}
} catch (JSONException e) {
Log.e("getPurchases", "PURCHASE DATA PARSING EXCEPTION: " + e.getMessage(), e);
} catch (RemoteException e) {
Log.e("getPurchases", "EXCEPTION: " + e.getMessage(), e);
}
return null;
}
private void parsePurchaseData(String purchaseData) throws JSONException {
Purchase purchase = new Purchase(purchaseData);
Product p = Content.ITEM_MAP.get(purchase.getProductId());
if (p != null) {
p.setPurchased(purchase);
Log.i("getPurchases", "Restoring product " + purchase.getProductId() + " Purchase token: " + purchase.getToken());
} else {
Log.i("getPurchases", "Unable to restore product " + purchase.getProductId() + ". Product not found.");
}
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
MainScreenPepperListFragment.getpeppers.setVisibility(View.VISIBLE);
MainScreenPepperListFragment.fetch_peppers_progressbar.setVisibility(View.GONE);
MainScreenPepperListFragment.fetching_peppers.setVisibility(View.GONE);
if (ProductListFragment.purchaseListAdapter != null) {
ProductListFragment.purchaseListAdapter.notifyDataSetChanged();
}
if (MainScreenPepperListFragment.reference.adapter != null) {
MainScreenPepperListFragment.reference.adapter.notifyDataSetChanged();
}
}
};
restoreTask.execute();
}
/**
* Starts the payment process for the given product id. Application is suspended and the Npay service will complete the purchase.
*
* @param caller - The response from the purchase is sent to the caller activity. Caller activity must override "protected void onActivityResult(int requestCode, int resultCode, Intent data)" method to get the response.
* @param product_id - The product id that is being purchased.
* @throws Exception
*/
public void startPayment(Activity caller, String product_id) throws Exception {
if (!isBillingAvailable())
return;
Bundle intentBundle = npay.getBuyIntent(1, activity.getPackageName(), product_id, ITEM_TYPE_INAPP, "");
PendingIntent purchaseIntent = intentBundle.getParcelable("BUY_INTENT");
//Set purchase in progress
setPurchaseInProgress(product_id);
caller.startIntentSenderForResult(
purchaseIntent.getIntentSender(),
Integer.valueOf(0),
new Intent(),
Integer.valueOf(0),
Integer.valueOf(0),
Integer.valueOf(0));
}
public boolean consumeProduct(String productId, String token) {
if (!isBillingAvailable())
return false;
boolean consumed = false;
try {
Log.i("consumeProduct", "Consuming product: " + productId + " PurchaseToken: " + token);
int response = npay.consumePurchase(1, activity.getPackageName(), productId, token);
if (response == RESULT_OK)
consumed = true;
} catch (RemoteException e) {
Log.e("isBillingAvailable", e.getMessage(), e);
}
return consumed;
}
public void setPurchaseInProgress(String productId) {
if (productId.equals(KEY_NOT_IN_PROGRESS))
Log.i("setPurchaseInProgress", "Resetting purcahse progress");
else
Log.i("setPurchaseInProgress", "Starting purchase for product " + productId);
SharedPreferences prefs = activity.getSharedPreferences(SHARED_PREFERENCE_KEY, Context.MODE_PRIVATE);
prefs.edit().putString(PRODUCT_ID_KEY, productId).commit();
}
public String getPurchaseInProgress() {
SharedPreferences prefs = activity.getSharedPreferences(SHARED_PREFERENCE_KEY, Context.MODE_PRIVATE);
String progress = prefs.getString(PRODUCT_ID_KEY, PREFLOAD_FAILED);
Log.i("getPurchaseInProgress", "Purchase in progress is: " + progress);
return progress;
}
/**
* Shows an alert dialog when billing is not available.
*/
public void errorAlert(String msg) {
Log.i("errorAlert", "Displaying error alert");
new AlertDialog.Builder(activity).setTitle("PepperFarm").setMessage(msg).setNeutralButton("Close", null).show();
}
public void cleanUp() {
try {
activity.unbindService(this);
npayAvailable = false;
Log.i("Payment", "Service disconnected");
} catch (Exception ignored) {
Log.i("cleanUp", "Service was cleared up already previously");
//Unable to clean up. This means it is not registered or another error. Ignored exception
}
}
}

Просмотреть файл

@ -0,0 +1,44 @@
/**
* Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
* See the license text file delivered with this project for more information.
*/
package com.nokia.example.pepperfarm.product;
import android.app.Activity;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
public class Config {
public static final String APPTITLE = "Pepperfarm";
public static final String PEPPER_FARM_PRODUCTID = "1081412";
public static final String PEPPER_SEEDS_PRODUCTID = "1081413";
public static final String JALAPENO_PRODUCTID = "1081414";
public static final String SWEET_BELL_PRODUCTID = "1081416";
public static final String HABENERO_PRODUCTID = "1081417";
public static final String PEPPER_SPRAY_PRODUCTID = "1081418";
/**
* Sets the title of application according to APPTITLE
*
* @param reference
*/
public static void setVersiontitle(Activity reference) {
try {
PackageInfo pInfo = reference.getPackageManager().getPackageInfo(reference.getPackageName(), 0);
String version_code = Integer.toString(pInfo.versionCode);
PackageInfo iapInfo = reference.getPackageManager().getPackageInfo("com.nokia.payment.iapenabler", 0);
String iap_versioncode = Integer.toString(iapInfo.versionCode);
String iap_version = iapInfo.versionName.concat(".").concat(iap_versioncode);
reference.setTitle(APPTITLE.concat(" 1.0.").concat(version_code).concat(" / ").concat(iap_version));
} catch (NameNotFoundException ignored) {
}
}
}

Просмотреть файл

@ -0,0 +1,320 @@
/**
* Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
* See the license text file delivered with this project for more information.
*/
package com.nokia.example.pepperfarm.product;
import android.content.Context;
import android.content.res.Resources;
import com.nokia.example.pepperfarm.client.R;
import com.nokia.example.pepperfarm.client.util.Purchase;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Class used to represent a collection of Nokia Store IAP items.
* If you wanted to further improve upon the idea of having an object representing in app purchasable content, you could consider
* extending Inventory.java in order to not have to manually merge information between your own content objects and the ones
* provided by Nokia IAP.
*/
public class Content {
public static boolean products_initialized = false;
/**
* An array of items.
*/
public static List<Product> ITEMS = new ArrayList<Product>();
/**
* A map of items, by ID.
*/
public static Map<String, Product> ITEM_MAP = new HashMap<String, Product>();
public static void initializeProducts(Resources res) {
//The first item is already paid for and non-consumable for the time being.
Product pepper_farm = new Product(Config.PEPPER_FARM_PRODUCTID, res.getString(R.string.pepper_farm), res.getString(R.string.pepper_farm_description));
pepper_farm.setProductType(Product.PRODUCT_TYPE.CONSUMABLE);
Product pepper_seeds = new Product(Config.PEPPER_SEEDS_PRODUCTID, res.getString(R.string.pepper_seeds), res.getString(R.string.pepper_seeds_description));
Product jalapeno = new Product(Config.JALAPENO_PRODUCTID, res.getString(R.string.jalapeno), res.getString(R.string.jalapeno_description));
Product sweet_bell = new Product(Config.SWEET_BELL_PRODUCTID, res.getString(R.string.sweet_bell), res.getString(R.string.sweet_bell_description));
Product habenero = new Product(Config.HABENERO_PRODUCTID, res.getString(R.string.habenero), res.getString(R.string.habenero_description));
Product pepper_spray = new Product(Config.PEPPER_SPRAY_PRODUCTID, res.getString(R.string.pepper_spray), res.getString(R.string.pepper_spray_description));
//Content.addItem(pepper_farm);
Content.addItem(pepper_seeds);
Content.addItem(jalapeno);
Content.addItem(sweet_bell);
Content.addItem(habenero);
Content.addItem(pepper_spray);
products_initialized = true;
}
/**
* Adds a product to both the item map and item list.
* We also check for duplicates.
*
* @param item
*/
public static void addItem(Product item) {
if (ITEM_MAP.get(item.productId) == null) {
ITEMS.add(item);
ITEM_MAP.put(item.productId, item);
}
}
/**
* Returns a list containing all of the products where product.isPurchased() is true.
*
* @return A list of Products containing all purchased content.
*/
public static List<Product> getPurchasedItems() {
List<Product> purchasedItems = new ArrayList<Product>();
for (Product product : ITEMS) {
if (product.isPurchased()) {
purchasedItems.add(product);
}
}
return purchasedItems;
}
/**
* An item representing a piece of content.
*/
public static class Product {
/**
* The product type represents whether a Product is consumable or non-consumable.
* A non-consumable product is bought once and kept permanently.
* A consumable product can be consumed and then bought again. (Think coins or power ups)
* The default is consumable.
*/
public static enum PRODUCT_TYPE {
/**
* A durable product is bought once and kept permanently.
*/
NON_CONSUMABLE,
/**
* A consumable product can be consumed and then re-purchased.
*/
CONSUMABLE
}
/**
* The product type. Either Consumable or Durable.
*/
public PRODUCT_TYPE productType;
/**
* True if the item has already been purchased, false otherwise.
*/
public boolean purchased;
/**
* @return The Product Type (DURABLE or CONSUMABLE)
*/
public PRODUCT_TYPE getProductType() {
return productType;
}
/**
* @param productType The Product Type (DURABLE or CONSUMABLE)
*/
public void setProductType(PRODUCT_TYPE productType) {
this.productType = productType;
}
/**
* The ID of the IAP product. Sometimes referred to as the resource ID.
*/
public String productId;
/**
* The name of the product
*/
public String title;
public int count;
/**
* @param id The product's ID.
* @param title The name of the product
* @param description The description of the product
*/
public Product(String id, String title, String description) {
productId = id;
this.title = title;
purchased = false;
productType = PRODUCT_TYPE.CONSUMABLE;
this.description = description;
price = "";
}
/**
* @param id The product's ID.
* @param title The name of the product
* @param description The description of the product
* @param productType Enumeration whose value is either DURABLE or CONSUMANBLE.
* @param parent The ID of the parent associated with this product.
*/
public Product(String id, String title, String description, PRODUCT_TYPE productType) {
this(id, title, description);
this.productType = productType;
}
/**
* @return The product id
*/
public String getProductId() {
return productId;
}
/**
* @param productId
*/
public void setProductId(String productId) {
this.productId = productId;
}
/**
* @return The product's title
*/
public String getTitle() {
return title;
}
/**
* @param title
*/
public void setTitle(String title) {
this.title = title;
}
/**
* @return The description
*/
public String getDescription() {
return description;
}
/**
* @param description
*/
public void setDescription(String description) {
this.description = description;
}
/**
* @return The price of the product.
*/
public String getPrice() {
return price;
}
/**
* @param price The price of the product, without units. (No $)
*/
public void setPrice(String price) {
this.price = price;
}
/**
* The description of the content.
*/
public String description;
/**
* A string representing the price of the content.
* Set by the Enabler after the first getProductData() request.
*/
public String price;
/**
* A record of the item's purchase, assuming it has been purchased.
* If the item has not been purchased, then this value will be null.
*/
private Purchase purchase = null;
/**
* @return An object representing the items purchase, or null if the item was never purchased.
*/
public Purchase getPurchase() {
return purchase;
}
/**
* Returns the title of the Content
*/
@Override
public String toString() {
return title;
}
/**
* @return True if the item has been purchased, false otherwise.
*/
public boolean isPurchased() {
return purchased;
}
/**
* Tells the content that the item has been purchased.
*
* @param thePurchase An object representing all the purchase details.
*/
public void setPurchased(Purchase thePurchase) {
this.purchased = true;
this.purchase = thePurchase;
//count++;
}
/**
* Consumes the purchase by setting purchased = false and nulling out the Purchase records.
* If you call this on an item that was not purchased or was already consumed, the item will just be
* marked as consumed without any error checking performed. (There is no real harm in doing this though.)
*/
public void consumeItem() {
purchased = false;
purchase = null;
}
/**
* @return Returns the id of an image resource representing the full resolution available.
*/
public int getFullImage(Context ctx) {
int imageResource = R.drawable.farm;
String title = getTitle();
if (ctx.getString(R.string.sweet_bell).equals(title)) {
imageResource = R.drawable.bellpepper;
} else if (ctx.getString(R.string.pepper_spray).equals(title)) {
imageResource = R.drawable.pepperspray;
} else if (ctx.getString(R.string.pepper_farm).equals(title)) {
imageResource = R.drawable.farm;
} else if (ctx.getString(R.string.jalapeno).equals(title)) {
imageResource = R.drawable.jalapeno;
} else if (ctx.getString(R.string.habenero).equals(title)) {
imageResource = R.drawable.habenero;
} else if (ctx.getString(R.string.pepper_seeds).equals(title)) {
imageResource = R.drawable.pepperseed;
}
return imageResource;
}
}
}

Просмотреть файл

@ -0,0 +1,200 @@
/**
* Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
* See the license text file delivered with this project for more information.
*/
package com.nokia.example.pepperfarm.product.adapters;
import android.app.AlertDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;
import com.nokia.example.pepperfarm.client.MainScreenPepperListFragment;
import com.nokia.example.pepperfarm.client.PepperFarmMainScreenActivity;
import com.nokia.example.pepperfarm.client.ProductListFragment;
import com.nokia.example.pepperfarm.client.R;
import com.nokia.example.pepperfarm.product.Content;
import com.nokia.example.pepperfarm.product.Content.Product;
import java.util.List;
/**
* An adapter used to show a list of Peppers you currently own.
* Used for the MainScreenPepeprListFragment and by association, PepperFarmMainScreenActivity.
*/
public class ContentListAdapter extends ArrayAdapter<Product> {
/**
* Constructor used to take in a context, resource, and a List of products.
*
* @param context A context
* @param resource The resource id of the caller
* @param objects A list of products to be displayed
*/
public ContentListAdapter(Context context,
int resource, List<Product> objects) {
super(context, resource, objects);
this.context = context;
}
/**
* The context to use
*/
Context context;
/**
* For the Content List Adapter, all items are considered enabled.
*
* @param position
* @return Always returns true
*/
public boolean isEnabled(int position) {
return true;
}
/**
* Returns true as all items are considered enabled in the list of peppers purchased.
*
* @return true
*/
public boolean areAllItemsEnabled() {
return true;
}
/**
* Generates the view representing a pepper that the user owns.
* <p/>
* The view will have:
* 1. An image or placeholder image representing the pepper
* 2. The name of the pepper
* 3. A description of the pepper
* 4. If the pepper is consumable, it will also have a button the user can press to consume it.
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = View.inflate(this.getContext(), R.layout.pepper_list_row_view, null);
final Product currentProduct = Content.getPurchasedItems().get(position);
//Set the image
ImageView image = (ImageView) convertView.findViewById(R.id.list_image);
image.setImageResource(currentProduct.getFullImage(context));
image.setVisibility(View.GONE);
//Set the name
TextView text = (TextView) convertView.findViewById(R.id.pepperName);
text.setText(currentProduct.getTitle());
//Set the description
TextView description = (TextView) convertView.findViewById(R.id.pepper_description);
description.setText(currentProduct.getDescription());
description.setVisibility(View.GONE);
final Button consumeButton = (Button) convertView.findViewById(R.id.eat_pepper);
//Listener for the Purchase Requisition button
consumeButton.setOnClickListener(
new Button.OnClickListener() {
public void onClick(final View v) {
final String text = consumeButton.getText().toString();
consumebuttonLoad(consumeButton);
AsyncTask<Void, String, Void> consumeTask = new AsyncTask<Void, String, Void>() {
@Override
protected void onProgressUpdate(String... values) {
if (values[0] != null) {
if (values[0].equals("0")) {
notifyDataSetChanged();
successAlert();
} else {
consumebuttonFail(consumeButton, text);
if (MainScreenPepperListFragment.reference.adapter != null) {
MainScreenPepperListFragment.reference.adapter.notifyDataSetChanged();
}
}
}
}
@Override
protected Void doInBackground(Void... params) {
boolean consumeOperation = PepperFarmMainScreenActivity.purchaseHandler.consumeProduct(currentProduct.getPurchase().getProductId(), currentProduct.getPurchase().getToken());
System.out.println("Consume response: " + consumeOperation);
if (consumeOperation) {
Product consumedProduct = Content.ITEM_MAP.get(currentProduct.getPurchase().getProductId());
consumedProduct.consumeItem();
String response[] = new String[1];
response[0] = "0";
this.publishProgress(response);
return null;
}
String response[] = new String[1];
response[0] = "1";
this.publishProgress(response);
return null;
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
if (ProductListFragment.purchaseListAdapter != null) {
ProductListFragment.purchaseListAdapter.notifyDataSetChanged();
}
}
};
consumeTask.execute();
}
}
);
if (currentProduct.getProductType().equals(Product.PRODUCT_TYPE.NON_CONSUMABLE)) {
//Non-consumable products should not have a consume button
consumeButton.setVisibility(View.INVISIBLE);
}
return convertView;
}
public void successAlert() {
new AlertDialog.Builder(context).setMessage("We hope you enjoyed your peppers.").setNeutralButton("Ok", null).show();
}
public void consumebuttonFail(Button button, String text) {
button.setText(text);
button.setClickable(true);
button.setEnabled(true);
new AlertDialog.Builder(context).setTitle("Error").setMessage("Unable to consume item.").setNeutralButton("Close", null).show();
}
public void consumebuttonLoad(Button button) {
button.setText("Loading...");
button.setClickable(false);
button.setEnabled(false);
}
/**
* No filter available for the ContentListAdapter, so this will always return null.
*
* @return Always returns null
*/
public Filter getFilter() {
return null;
}
/**
* @return The number of items in the list.
*/
@Override
public int getCount() {
return Content.getPurchasedItems().size();
}
}

Просмотреть файл

@ -0,0 +1,133 @@
/**
* Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
* See the license text file delivered with this project for more information.
*/
package com.nokia.example.pepperfarm.product.adapters;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.nokia.example.pepperfarm.client.ProductListActivity;
import com.nokia.example.pepperfarm.client.R;
import com.nokia.example.pepperfarm.product.Content;
import com.nokia.example.pepperfarm.product.Content.Product;
import java.util.List;
/**
* The Content Purchase Adapter is used to display a list of Products that can be purchased.
* If the item is already purchased, it will appear on the list but will be greyed out and unclickable.
*/
public class ContentPurchaseAdapter extends ArrayAdapter<Product> {
/**
* Constructor used to set up the ContentPurchaseAdapter
*
* @param context The context
* @param resource The resource
* @param objects The list of Products the ContentPurchaseAdapter will display
*/
public ContentPurchaseAdapter(Context context,
int resource, List<Product> objects) {
super(context, resource, objects);
}
/**
* Returns true if the specific content item is enabled. Otherwise returns false.
*
* @param position The position in the list of the item to check if enabled
* @return True if the content item at the supplied position is enabled. False otherwise.
*/
public boolean isEnabled(int position) {
if (Content.ITEMS.get(position).isPurchased()) {
return false;
} else {
return true;
}
}
/**
* Lets Android know that not all items in the list will always be enabled.
*
* @return Always returns false.
*/
public boolean areAllItemsEnabled() {
return false;
}
/**
* Does the primary work of setting up the UI for one specific item in the list.
* An item will have:
* 1. An image representing the item.
* 2. A name, as determined by Product.getTitle()
* 3. A price, which is assumed to have been previously queried through use of a
* getProductData call to the Nokia In App Payment Library.
* <p/>
* If the item has already been purchased, the item will be greyed out and will not be clickable.
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = View.inflate(this.getContext(), R.layout.activity_product_list_row_view, null);
final Product currentProduct = Content.ITEMS.get(position);
//Set the image
ImageView image = (ImageView) convertView.findViewById(R.id.list_image);
image.setVisibility(View.GONE);
//image.setImageResource(currentProduct.getFullImage());
//Set the name
TextView text = (TextView) convertView.findViewById(R.id.iapName);
text.setText(currentProduct.getTitle());
//Set the price
TextView price = (TextView) convertView.findViewById(R.id.price);
price.setText(currentProduct.getPrice());
//Set the description
TextView description = (TextView) convertView.findViewById(R.id.product_description);
description.setText(currentProduct.getDescription());
Button buyPepperButton = (Button) convertView.findViewById(R.id.start_purchase);
buyPepperButton.setOnClickListener
(new Button.OnClickListener() {
public void onClick(View v) {
System.out.println("CLICK " + currentProduct.getProductId());
try {
ProductListActivity.purchaseHandler.startPayment(ProductListActivity.reference, currentProduct.getProductId());
} catch (Exception e) {
System.out.println("Exception while starting payment: " + e.getMessage());
e.printStackTrace();
}
}
}
);
if (currentProduct.isPurchased()) {
buyPepperButton.setVisibility(View.INVISIBLE);
price.setVisibility(View.INVISIBLE);
/*
* A purchased item:
* 1. Will not have the arrow
* 2. Will have a slightly different background color
* 3. Will have greyed out text
*/
// text.setTextColor(Color.GRAY);
// price.setTextColor(Color.GRAY);
// convertView.setBackgroundColor(Color.parseColor("#EEEEEE"));
}
return convertView;
}
}

Просмотреть файл

@ -0,0 +1,141 @@
/**
* Copyright (c) 2014 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
*
* 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.
*/
package com.nokia.payment.iap.aidl;
import android.os.Bundle;
/**
* All calls will give a response code with the following possible values<br/><br/>
* RESULT_OK = 0 - success<br/>
* RESULT_USER_CANCELED = 1 - user pressed back or canceled a dialog<br/>
* RESULT_BILLING_UNAVAILABLE = 3 - this billing API version is not supported for the type requested or billing is otherwise impossible<br/>
* RESULT_ITEM_UNAVAILABLE = 4 - requested ProductID is not available for purchase<br/>
* RESULT_DEVELOPER_ERROR = 5 - invalid arguments provided to the API<br/>
* RESULT_ERROR = 6 - Fatal error during the API action<br/>
* RESULT_ITEM_ALREADY_OWNED = 7 - Failure to purchase since item is already owned<br/>
* RESULT_ITEM_NOT_OWNED = 8 - Failure to consume since item is not owned<br/>
* RESULT_NO_SIM = 9 - Billing is not available because there is no SIM card inserted<br/>
*<br/>
* Only supported itemtype, other values result in RESULT_DEVELOPER_ERROR<br/>
* ITEM_TYPE_INAPP = "inapp";<br/>
*/
interface INokiaIAPService {
/**
* Checks support for the requested billing API version, package and in-app type.
* @param apiVersion the billing version which the app is using
* @param packageName the package name of the calling app
@param type must always be "inapp"
* @return RESULT_OK(0) on success, corresponding result code on failures
*/
int isBillingSupported(int apiVersion, String packageName, String type );
/**
* Provides details of a list of products<br/>
* Given a list of Productids of a valid type in the productBundle, this returns a bundle
* with a list JSON strings containing the productId, price, title and description.
* This API can be called with a maximum of 20 Productids.
* @param apiVersion billing API version that the Third-party is using
* @param packageName the package name of the calling app
* @param type must always be "inapp"
* @param productBundle bundle containing a StringArrayList of Productids with key "ITEM_ID_LIST", when setProductMappings has been called this parameter can be null
* @return Bundle containing the following key-value pairs<br/>
* "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
* failure as listed above.<br/>
* "DETAILS_LIST" with a StringArrayList containing purchase information
* in JSON format similar to:<br/>
<br/>
* '{ "productId" : "1264321", "isvalid", true, "title" : "Product title",<br/>
* "shortdescription" : "Short description of the product", <br/>
* "description" : "Longer description of the product", "priceValue" : "3.00",<br/>
* "price" : "$3.00", "currency", "USD",<br/>
* "purchaseToken" : "ZXlKMlpYSWlPaUl4TGpBaUxDSjBlRzVKWkNJNklrNVFRVmxmVkVWVFZGOVVXRTVmTVRFeE1TSXNJbkJ5YjJSSlpDSTZJakV3TWpNMk1qUWlmUT09",<br/>
* "taxesincluded": true, "restorable" : true, "type" : "inapp" }'<br/><br/>
* or if requested productId is not valid then<br/>
* ''{ "productId" : "invalidproductid", "isvalid", false }'<br/>
*/
Bundle getProductDetails(int apiVersion, String packageName, String type, in Bundle productBundle);
/**
* Returns a pending intent to launch the purchase flow for an in-app item by providing a ProductID,
* the type, a unique purchase token and an optional developer payload.
* @param apiVersion billing API version that the app is using
* @param packageName package name of the calling app
* @param productId the ProductID of the in-app item as published in the developer console or as mapped through setProductMappings
* @param type must always be "inapp"
* @param developerPayload optional argument to be sent back with the purchase information
* @return Bundle containing the following key-value pairs<br/><br/>
* "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
* failure as listed above.<br/>
* "BUY_INTENT" - PendingIntent to start the purchase flow
*
* The Pending intent should be launched with startIntentSenderForResult. When purchase flow
* has completed, the onActivityResult() will give a resultCode of OK or CANCELED.<br/><br/>
* If the purchase is successful, the result data will contain the following key-value pairs<br/><br/>
* "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
* failure as listed above.<br/>
* "INAPP_PURCHASE_DATA" - String in JSON format similar to<br/><br/>
* '{"orderId":"X393XDAFFDAFAD",<br/>
* "packageName":"com.your.app",<br/>
* "productId":"1264321",<br/>
* "purchaseToken" : "ZXlKMlpYSWlPaUl4TGpBaUxDSjBlRzVKWkNJNklrNVFRVmxmVkVWVFZGOVVXRTVmTVRFeE1TSXNJbkJ5YjJSSlpDSTZJakV3TWpNMk1qUWlmUT09",<br/>
* "developerPayload":"" }'<br/><br/>
* "INAPP_DATA_SIGNATURE" - currently empty string<br/>
*/
Bundle getBuyIntent(int apiVersion, String packageName, String productID, String type,
String developerPayload);
/**
* Returns the current products associated with current imei
* @param apiVersion billing API version that the app is using
* @param packageName package name of the calling app
* @param type must always be "inapp"
* @param productBundle bundle containing a StringArrayList of Productids with key "ITEM_ID_LIST", when setProductMappings has been called this parameter can be null
* @param continuationToken - currently ignored
* @return Bundle containing the following key-value pairs<br/>
* "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
* failure as listed above.<br/>
* "INAPP_PURCHASE_ITEM_LIST" - StringArrayList containing the list of owned products<br/>
* "INAPP_PURCHASE_DATA_LIST" - StringArrayList containing for each owned product json string
* similar to following (please note that delveloperPayload field is currently empty):<br/><br/>
* { "productId":"1264321",<br/>
* "purchaseToken" : "ZXlKMlpYSWlPaUl4TGpBaUxDSjBlRzVKWkNJNklrNVFRVmxmVkVWVFZGOVVXRTVmTVRFeE1TSXNJbkJ5YjJSSlpDSTZJakV3TWpNMk1qUWlmUT09",<br/>
* "developerPayload":"" }<br/>
*/
Bundle getPurchases(int apiVersion, String packageName, String type, in Bundle productBundle, String continuationToken );
/**
* Consume the last purchase of the given product. This will result in this item being removed
* from all subsequent responses to getPurchases() and allow re-purchase of this item.
* @param apiVersion billing API version that the app is using
* @param packageName package name of the calling app
* @param productId productId of purchase to be consumed, this argument can be empty or null
* @param purchaseToken token in the purchase information JSON that identifies the purchase
* to be consumed
* @return 0 if consumption succeeded. Appropriate error values for failures.
*/
int consumePurchase(int apiVersion, String packageName, String productId, String purchaseToken);
/**
* Set mapping between nokia productid-s and application internal productid-s
* @param apiVersion billing API version that the app is using
* @param packageName package name of the calling app
* @param mappingsBundle - bundle containing mapping as key, value pairs where key is Nokia productid and value is calling applications internal id
*/
int setProductMappings( int apiVersion, String packageName, in Bundle mappingsBundle );
}

Просмотреть файл

@ -1,4 +1,20 @@
nokia-x-in-app-payment-samples
==============================
Nokia In-App Payment API samples for Nokia X
============================================
Placeholder
This project contains the simple examples demonstrating how to implement and
port an application to utilise Nokia In-App Payment on Nokia X software
platform.
What are the samples all about:
* **Payment One APK**: Demonstrates how to utilise both Nokia In-App Payment and
Google In-App Billing in the same application. The resulting APK will run in
both Nokia X and Google Android devices.
* **Pepper Farm Simulator**: Demonstrates how to implement the support for
Nokia In-App Payment enabler.
See the sample specific README and license files, located in the root folder of
each sample, for more details.
Learn more about Nokia In-App Payment API in
[Nokia X Developer's Library](http://developer.nokia.com/resources/library/nokia-x).