├── .gitignore ├── README.md ├── build.gradle ├── example ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── io │ │ └── eisner │ │ └── bannerads │ │ └── MainActivity.java │ └── res │ ├── layout │ ├── activity_main.xml │ └── content_main.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── values-v21 │ └── styles.xml │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── build.gradle ├── libs │ ├── okhttp-2.5.0.jar │ └── okio-1.6.0.jar ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── io │ │ └── eisner │ │ └── ads │ │ ├── Ad.java │ │ ├── AdCache.java │ │ ├── AdParser.java │ │ ├── AdProvider.java │ │ ├── GetResponse.java │ │ └── HeaderFields.java │ └── res │ ├── drawable │ └── placeholder.png │ └── values │ └── values.xml └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Android template 3 | # Built application files 4 | *.apk 5 | *.ap_ 6 | 7 | # Files for the Dalvik VM 8 | *.dex 9 | 10 | # Java class files 11 | *.class 12 | 13 | # Generated files 14 | bin/ 15 | gen/ 16 | 17 | # Gradle files 18 | .gradle/ 19 | build/ 20 | 21 | # Local configuration file (sdk path, etc) 22 | local.properties 23 | 24 | # Proguard folder generated by Eclipse 25 | proguard/ 26 | 27 | # Log Files 28 | *.log 29 | 30 | # Android Studio Navigation editor temp files 31 | .navigation/ 32 | /example/src/main/res/values/keyinfo.xml 33 | 34 | .DS_Store 35 | *.iml 36 | /.idea 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AndroidAds (Beta) 2 | A simple Android library that allows an ad slideshow to be added into any view in your app. This allows you to host and control your own ads. Your server sends out a XML response and the `AdProvider` parses that XML, looking for urls located in the set `.parseTag`. 3 | 4 | # Start Here 5 | 6 | [![Release](https://img.shields.io/github/release/nateisner/android-ads.svg?label=JitPack)](https://jitpack.io/#nateisner/android-ads/) 7 | 8 | You must first add JitPack.io to the repositories list in your app's build.gradle file: 9 | 10 | ```gradle 11 | repositories { 12 | maven { url "https://jitpack.io" } 13 | } 14 | ``` 15 | 16 | Then, add this to the list of dependencies: 17 | 18 | ```gradle 19 | dependencies { 20 | compile 'com.github.nateisner:android-ads:0.1.1' 21 | } 22 | ``` 23 | ## Usage 24 | 25 | Add a `ViewGroup` to your layout that will act as the root for the images. This can be a `RelativeLayout`, `LinearLayout`, `CoordinatorLayout` ...etc. The sizes of this view will be the size of the ads shown. 26 | 27 | Example: 28 | 29 | 30 | ``` 31 | 36 | ``` 37 | 38 | 39 | Then, you can build your `AdProvider`. Using supported features. 40 | 41 | ``` 42 | new AdProvider.Builder(context) 43 | .imageServer(serverStringURL) 44 | .parseTag("imagefilename") 45 | .attachTo(rootView) 46 | .imageTime(5000) //in ms 47 | .useAPIKey(keyserver, keyheaders, keyHeaderName) 48 | .start(); 49 | ``` 50 | 51 | 52 | Features include: 53 | 54 | * Additional HeaderFields can be added for use when making the XML request. 55 | 56 | `HeaderFields` object is used to add fields to any HTTP request made by your `AdProvider` Example: 57 | 58 | ``` 59 | HeaderFields moreheaders = new HeaderFields(); 60 | moreheaders.add("X-FieldName1","value"); 61 | moreheaders.add("X-FieldName2","valueofanother"); 62 | ``` 63 | 64 | `.requestHeader(HeaderField moreheaders)` 65 | 66 | * A Placeholder for when images are loading or cannot be found. 67 | 68 | `.placeholder(Drawable)` 69 | 70 | 71 | * The disk cache size can be increased or decreased. The default is set to 6 images if the xml has more than the amount set, it will attempt to load from server once it reaches the max on disk. 72 | 73 | `.cacheSize(int size)` 74 | 75 | * Offline mode will enable your app to use what ever images it has cached on disk if there is no connection with the server. The images that will be shown are the last images that were cached and hopefully not cleared by the system or user. (This feature is not fully implemented yet) 76 | 77 | `.offlineUse(true)` 78 | 79 | ## How It Works 80 | 81 | #### Your Ad Server 82 | 83 | * You must have a backend server that hosts all of your images and generates a list of the images in a XML ~~or JSON~~ response 84 | * The response is structured something like this: 85 | 86 | ``` 87 | 88 | 89 | 11 90 | Title 91 | This is an album full of ... 92 | 93 | 94 | 26 95 | Desc of image 96 | Title 97 | http://yourserver.com/561c3c48293d09.81340072/561c3daca3c06.png 98 | 99 | 100 | 27 101 | Desc of image 102 | Title 103 | http://yourserver.com/561c3c48293d09.81340072/561c3dc5c1413.png 104 | 105 | 106 | 107 | ``` 108 | The internal parser parses through the XML for a `.parseTag` that is set when building your `AdProvider`. In this example you would set `.parseTag` to "imagefilename". 109 | 110 | * API Key - Sometimes you may want to limit your server's access by using an API key in your HTTP request header. The `AdProvider` can be built with `.useAPIKey()`. Such as: 111 | 112 | ``` 113 | //HeaderFields object that maybe needed to get the response 114 | HeaderFields keyheaders = new HeaderFields(); 115 | keyheaders.add("X-FIELD-NAME", "value"); 116 | 117 | //String of the url that will repond with the key 118 | String keyserver = "http://www.apikeyserver.com"; 119 | 120 | //String name of the HeaderField the key is used in the XML request. 121 | String keyHeaderField = "X-API-KEY"; 122 | 123 | .useAPIKey(keyserver, keyheaders, keyHeaderField); 124 | ``` 125 | The server should respond with ` 126 | 127 | keyvaluehere 128 | ` and that key value will be used for the rest of the session. 129 | 130 | #### Your App 131 | 132 | * The main purpose of this library is to simplify a way to insert ads into your app. By using `.attachTo` to insert ads in a `ViewGroup`. This will be a set `View` that you can either programmatically implement or add into your layout's XML. In the example, I have attached the ads in a `RelativeLayout` and set the parameters to specify location and size. The images will crop and fit inside of that view. 133 | * The `AdProvider` has a `stop()` and `restart()` methods that can be used in your activity's `onStop()` or `onResume()` if you don't want the AdProvider to continue to (attempt) run in the background. 134 | * The file cache holds images until cleared by the system or the user. (or overwritten by new instance of this library) This will allow displaying ads with no network connectivity and saving battery by bulk loading. The file cache can be limited if space is an issue but that will mean if `AdProvider` runs into an un-cached image in its list, it will attempt to load that image from the network and delete one from the cache to hold true to the cache limit. 135 | * ~~Image limit can be set for how many images you would like to grab from the list of images given by the server~~ Not yet... 136 | 137 | ## Future 138 | 139 | * Features in the works 140 | * Total image limit - limit amount grabbed from the server's list response. 141 | * JSON support 142 | * Performance enhancements 143 | * Different animation types for image slideshow 144 | * ??? 145 | 146 | ## Developed By 147 | 148 | * Nate Eisner - nate@eisner.io 149 | 150 | ## License 151 | 152 | ``` 153 | Copyright 2015 Nathan Eisner 154 | 155 | Licensed under the Apache License, Version 2.0 (the "License"); 156 | you may not use this file except in compliance with the License. 157 | You may obtain a copy of the License at 158 | 159 | http://www.apache.org/licenses/LICENSE-2.0 160 | 161 | Unless required by applicable law or agreed to in writing, software 162 | distributed under the License is distributed on an "AS IS" BASIS, 163 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 164 | See the License for the specific language governing permissions and 165 | limitations under the License. 166 | ``` 167 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.2.3' 9 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' 10 | } 11 | } 12 | 13 | allprojects { 14 | repositories { 15 | jcenter() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | /src/main/res/values/keyinfo.xml 2 | /build 3 | -------------------------------------------------------------------------------- /example/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.1" 6 | 7 | defaultConfig { 8 | applicationId "io.eisner.bannerads" 9 | minSdkVersion 17 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:23.1.0' 26 | compile 'com.android.support:design:23.1.0' 27 | compile project(':library') 28 | } 29 | -------------------------------------------------------------------------------- /example/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Volumes/Storage/android/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /example/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 13 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/src/main/java/io/eisner/bannerads/MainActivity.java: -------------------------------------------------------------------------------- 1 | package io.eisner.bannerads; 2 | 3 | import android.os.Bundle; 4 | import android.support.design.widget.FloatingActionButton; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.support.v7.widget.Toolbar; 7 | import android.view.View; 8 | import android.widget.Toast; 9 | 10 | import io.eisner.ads.AdProvider; 11 | import io.eisner.ads.HeaderFields; 12 | 13 | public class MainActivity extends AppCompatActivity { 14 | private FloatingActionButton fab; 15 | AdProvider myAdProvider; 16 | 17 | @Override 18 | protected void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.activity_main); 21 | 22 | String keyserver = getResources().getString(R.string.server); 23 | String key = getResources().getString(R.string.key); 24 | String secret = getResources().getString(R.string.secret); 25 | 26 | HeaderFields keyheaders = new HeaderFields(); 27 | keyheaders.add("X-API-KEY",key); 28 | keyheaders.add("X-SHHH-ITS-A-SECRET",secret); 29 | String keyHeaderName = "X-API-KEY"; 30 | 31 | View rootView = findViewById(R.id.adContainer); 32 | 33 | final String server = getResources().getString(R.string.xmlserver); 34 | 35 | myAdProvider = new AdProvider.Builder(this) 36 | .imageServer(server) //the location of the xml 37 | .attachTo(rootView) //root to attach to, the height 38 | .imageTime(5000) //in ms 39 | .parseTag("imagefilename") //tag in the xml where the images are wrapped in 40 | .offlineUse(true) //if there is no connectivity the device will used the local ads 41 | .useAPIKey(keyserver, keyheaders, keyHeaderName) //setup if an api key is needed 42 | // in xml request 43 | .start(); 44 | 45 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 46 | setSupportActionBar(toolbar); 47 | 48 | fab = (FloatingActionButton) findViewById(R.id.fab); 49 | fab.setOnClickListener(new View.OnClickListener() { 50 | @Override 51 | public void onClick(View view) { 52 | Toast.makeText(getApplicationContext(),"Button Pressed",Toast.LENGTH_SHORT).show(); 53 | } 54 | }); 55 | } 56 | 57 | private void hideFab() { 58 | fab.animate() 59 | .setDuration(1200) 60 | .translationY(500) 61 | .start(); 62 | } 63 | 64 | @Override 65 | protected void onStop() { 66 | super.onStop(); 67 | // myAdProvider.stop(); 68 | } 69 | 70 | @Override 71 | protected void onPause() { 72 | super.onPause(); 73 | // myAdProvider.stop(); 74 | } 75 | 76 | @Override 77 | protected void onResume() { 78 | super.onResume(); 79 | // myAdProvider.restart(); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /example/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 22 | 23 | 24 | 25 | 26 | 27 | 32 | 33 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /example/src/main/res/layout/content_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /example/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nate-eisner/android-ads/f751a5eda55a44104e9c66765f4e0089a9e56a19/example/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nate-eisner/android-ads/f751a5eda55a44104e9c66765f4e0089a9e56a19/example/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nate-eisner/android-ads/f751a5eda55a44104e9c66765f4e0089a9e56a19/example/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nate-eisner/android-ads/f751a5eda55a44104e9c66765f4e0089a9e56a19/example/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nate-eisner/android-ads/f751a5eda55a44104e9c66765f4e0089a9e56a19/example/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | > 2 | 8 | 9 | -------------------------------------------------------------------------------- /example/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /example/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /example/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 16dp 6 | 7 | -------------------------------------------------------------------------------- /example/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | BannerAds 3 | MainActivity 4 | 5 | -------------------------------------------------------------------------------- /example/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 14 |