Add original project.
42
.gitignore
vendored
@ -33,3 +33,45 @@ google-services.json
|
|||||||
# Android Profiling
|
# Android Profiling
|
||||||
*.hprof
|
*.hprof
|
||||||
|
|
||||||
|
## Suggested ^^
|
||||||
|
|
||||||
|
## From TicTacToe project for good measure. vv
|
||||||
|
|
||||||
|
# Gradle files
|
||||||
|
.gradle/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# Local configuration file (sdk path, etc)
|
||||||
|
local.properties
|
||||||
|
|
||||||
|
# Log/OS Files
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Android Studio generated files and folders
|
||||||
|
captures/
|
||||||
|
.externalNativeBuild/
|
||||||
|
.cxx/
|
||||||
|
*.apk
|
||||||
|
output.json
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
*.iml
|
||||||
|
.idea/
|
||||||
|
misc.xml
|
||||||
|
deploymentTargetDropDown.xml
|
||||||
|
render.experimental.xml
|
||||||
|
|
||||||
|
# Keystore files
|
||||||
|
*.jks
|
||||||
|
*.keystore
|
||||||
|
|
||||||
|
# Google Services (e.g. APIs or Firebase)
|
||||||
|
google-services.json
|
||||||
|
|
||||||
|
# Android Profiling
|
||||||
|
*.hprof
|
||||||
|
/app/debug/output-metadata.json
|
||||||
|
|
||||||
|
# Ha!
|
||||||
|
keystore/*
|
||||||
|
release
|
||||||
|
1
app/.gitignore
vendored
Executable file
@ -0,0 +1 @@
|
|||||||
|
/build
|
33
app/build.gradle
Executable file
@ -0,0 +1,33 @@
|
|||||||
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 24
|
||||||
|
buildToolsVersion "24.0.2"
|
||||||
|
defaultConfig {
|
||||||
|
applicationId "com.hyperling.apps.wheretheriverfrowns"
|
||||||
|
minSdkVersion 15
|
||||||
|
targetSdkVersion 24
|
||||||
|
versionCode 3
|
||||||
|
versionName "1.02"
|
||||||
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
|
vectorDrawables.useSupportLibrary = true
|
||||||
|
}
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
|
||||||
|
exclude group: 'com.android.support', module: 'support-annotations'
|
||||||
|
})
|
||||||
|
compile 'com.android.support:appcompat-v7:24.2.1'
|
||||||
|
compile 'com.android.support:support-v4:24.2.1'
|
||||||
|
compile 'com.android.support:support-vector-drawable:24.2.1'
|
||||||
|
testCompile 'junit:junit:4.12'
|
||||||
|
compile 'com.google.android.gms:play-services-appindexing:8.4.0'
|
||||||
|
}
|
17
app/proguard-rules.pro
vendored
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# By default, the flags in this file are appended to flags specified
|
||||||
|
# in /home/ling/Android/Sdk/tools/proguard/proguard-android.txt
|
||||||
|
# You can edit the include path and order by changing the proguardFiles
|
||||||
|
# directive in build.gradle.
|
||||||
|
#
|
||||||
|
# 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,26 @@
|
|||||||
|
package com.hyperling.apps.wheretheriverfrowns;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.test.InstrumentationRegistry;
|
||||||
|
import android.support.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instrumentation test, which will execute on an Android device.
|
||||||
|
*
|
||||||
|
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||||
|
*/
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class ExampleInstrumentedTest {
|
||||||
|
@Test
|
||||||
|
public void useAppContext() throws Exception {
|
||||||
|
// Context of the app under test.
|
||||||
|
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||||
|
|
||||||
|
assertEquals("com.hyperling.apps.wheretheriverfrowns", appContext.getPackageName());
|
||||||
|
}
|
||||||
|
}
|
49
app/src/main/AndroidManifest.xml
Executable file
@ -0,0 +1,49 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.hyperling.apps.wheretheriverfrowns">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:fullBackupContent="false"
|
||||||
|
android:icon="@drawable/wtrf"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:supportsRtl="true"
|
||||||
|
android:theme="@style/wtrf">
|
||||||
|
<activity android:name=".MainActivity">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<service android:name=".MyService" />
|
||||||
|
|
||||||
|
<receiver android:name=".ServiceReceiver">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="com.hyperling.wheretheriverfrowns.ALARM_STARTED" />
|
||||||
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
||||||
|
|
||||||
|
<data android:scheme="package" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
<activity android:name=".DebugActivity"/>
|
||||||
|
<!-- ATTENTION: This was auto-generated to add Google Play services to your project for
|
||||||
|
App Indexing. See https://g.co/AppIndexing/AndroidStudio for more information. -->
|
||||||
|
<meta-data
|
||||||
|
android:name="com.google.android.gms.version"
|
||||||
|
android:value="@integer/google_play_services_version" />
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
158
app/src/main/java/com/hyperling/apps/wheretheriverfrowns/DebugActivity.java
Executable file
@ -0,0 +1,158 @@
|
|||||||
|
package com.hyperling.apps.wheretheriverfrowns;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Message;
|
||||||
|
import android.support.v7.app.ActionBar;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
public class DebugActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
private ActionBar actionBar;
|
||||||
|
|
||||||
|
private SharedPreferences sharedPreferences;
|
||||||
|
|
||||||
|
private String sharedPreferencesKey, debugKey,
|
||||||
|
TAG;
|
||||||
|
|
||||||
|
private LinearLayout debugLayout;
|
||||||
|
|
||||||
|
private Button btnDebug, btnResetPreferences;
|
||||||
|
|
||||||
|
private boolean DEBUG;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_debug);
|
||||||
|
|
||||||
|
// Load Strings
|
||||||
|
sharedPreferencesKey = getString(R.string.sharedPreferencesKey);
|
||||||
|
debugKey = getString(R.string.debugKey);
|
||||||
|
|
||||||
|
TAG = getString(R.string.TAG);
|
||||||
|
|
||||||
|
// Get Preferences
|
||||||
|
sharedPreferences = getSharedPreferences(sharedPreferencesKey, MODE_PRIVATE);
|
||||||
|
DEBUG = sharedPreferences.getBoolean(debugKey, false);
|
||||||
|
|
||||||
|
Map<String, ?> sharedPreferencesAll = sharedPreferences.getAll();
|
||||||
|
|
||||||
|
// Initialize UI
|
||||||
|
actionBar = DebugActivity.this.getSupportActionBar();
|
||||||
|
actionBar.setTitle(getString(R.string.debugActivityTitle));
|
||||||
|
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||||
|
|
||||||
|
btnDebug = (Button) findViewById(R.id.btnDebugExit);
|
||||||
|
btnResetPreferences = (Button) findViewById(R.id.btnResetPreferences);
|
||||||
|
|
||||||
|
// Disable buttons so they aren't accidentally clicked
|
||||||
|
setButtonsEnabled(false);
|
||||||
|
|
||||||
|
if (DEBUG){
|
||||||
|
btnDebug.setBackgroundColor(Color.GREEN);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
btnDebug.setBackgroundColor(Color.RED);
|
||||||
|
}
|
||||||
|
btnDebug.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||||
|
editor.putBoolean(debugKey, !DEBUG);
|
||||||
|
editor.apply();
|
||||||
|
|
||||||
|
resetScreen();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
btnResetPreferences.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||||
|
editor.clear();
|
||||||
|
editor.apply();
|
||||||
|
|
||||||
|
resetScreen();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
debugLayout = (LinearLayout) findViewById(R.id.debugLayout);
|
||||||
|
|
||||||
|
for (String key : sharedPreferencesAll.keySet()){
|
||||||
|
if (DEBUG){
|
||||||
|
Log.d(TAG, "DebugActivity: key=" + key + " value=" + sharedPreferencesAll.get(key));
|
||||||
|
}
|
||||||
|
TextView textView = new TextView(btnDebug.getContext());
|
||||||
|
textView.setText(key + "=" + sharedPreferencesAll.get(key));
|
||||||
|
|
||||||
|
debugLayout.addView(textView);
|
||||||
|
}
|
||||||
|
|
||||||
|
Runnable runnable = new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (DEBUG) Log.d(TAG, "DebugActivity: Waiting 2 seconds to enable buttons.");
|
||||||
|
synchronized (this){
|
||||||
|
try{
|
||||||
|
wait(2000);
|
||||||
|
if (DEBUG) Log.d(TAG, "DebugActivity: Done waiting.");
|
||||||
|
}
|
||||||
|
catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
if (DEBUG) Log.d(TAG, "DebugActivity: Failed to wait.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enableButtonsHandler.sendEmptyMessage(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Thread thread = new Thread(runnable);
|
||||||
|
thread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
|
||||||
|
int id = item.getItemId();
|
||||||
|
|
||||||
|
switch (id){
|
||||||
|
case android.R.id.home:
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetScreen(){
|
||||||
|
finish();
|
||||||
|
Intent refreshDebugActivity = new Intent(DebugActivity.this, DebugActivity.class);
|
||||||
|
startActivity(refreshDebugActivity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setButtonsEnabled(boolean enabled){
|
||||||
|
btnDebug.setEnabled(enabled);
|
||||||
|
btnResetPreferences.setEnabled(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Handler enableButtonsHandler = new Handler() {
|
||||||
|
@Override
|
||||||
|
public void handleMessage(Message msg) {
|
||||||
|
super.handleMessage(msg);
|
||||||
|
|
||||||
|
setButtonsEnabled(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
394
app/src/main/java/com/hyperling/apps/wheretheriverfrowns/MainActivity.java
Executable file
@ -0,0 +1,394 @@
|
|||||||
|
package com.hyperling.apps.wheretheriverfrowns;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
|
import android.net.NetworkInfo;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Message;
|
||||||
|
import android.os.StrictMode;
|
||||||
|
import android.support.v7.app.ActionBar;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.google.android.gms.appindexing.Action;
|
||||||
|
import com.google.android.gms.appindexing.AppIndex;
|
||||||
|
import com.google.android.gms.appindexing.Thing;
|
||||||
|
import com.google.android.gms.common.api.GoogleApiClient;
|
||||||
|
|
||||||
|
public class MainActivity extends AppCompatActivity {
|
||||||
|
private SharedPreferences sharedPreferences;
|
||||||
|
|
||||||
|
private String sharedPreferencesKey, topArticleKey, externalBrowserKey, checkForNewArticlesKey, debugKey,
|
||||||
|
networkConnected, networkRoaming, networkDisconnected,
|
||||||
|
TAG,
|
||||||
|
action, url;
|
||||||
|
|
||||||
|
private ActionBar actionBar;
|
||||||
|
|
||||||
|
private ProgressBar progressBar;
|
||||||
|
|
||||||
|
private LinearLayout layout;
|
||||||
|
private Button btnExample;
|
||||||
|
|
||||||
|
private boolean homePage, externalBrowser;
|
||||||
|
|
||||||
|
private boolean DEBUG;
|
||||||
|
|
||||||
|
private WebPage webPage;
|
||||||
|
|
||||||
|
private int debugCount, debugMax = 13;
|
||||||
|
/**
|
||||||
|
* ATTENTION: This was auto-generated to implement the App Indexing API.
|
||||||
|
* See https://g.co/AppIndexing/AndroidStudio for more information.
|
||||||
|
*/
|
||||||
|
private GoogleApiClient client;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_main);
|
||||||
|
|
||||||
|
/*** Initialize Strings ***/
|
||||||
|
// Keys
|
||||||
|
sharedPreferencesKey = getResources().getString(R.string.sharedPreferencesKey);
|
||||||
|
topArticleKey = getResources().getString(R.string.topArticleKey);
|
||||||
|
externalBrowserKey = getResources().getString(R.string.externalBrowserKey);
|
||||||
|
checkForNewArticlesKey = getResources().getString(R.string.checkForNewArticlesKey);
|
||||||
|
debugKey = getString(R.string.debugKey);
|
||||||
|
|
||||||
|
// Strings
|
||||||
|
networkConnected = getResources().getString(R.string.networkConnected);
|
||||||
|
networkRoaming = getResources().getString(R.string.networkRoaming);
|
||||||
|
networkDisconnected = getResources().getString(R.string.networkDisconnected);
|
||||||
|
TAG = getResources().getString(R.string.TAG);
|
||||||
|
|
||||||
|
/*** Get Preferences ***/
|
||||||
|
sharedPreferences = getSharedPreferences(sharedPreferencesKey, MODE_PRIVATE);
|
||||||
|
externalBrowser = sharedPreferences.getBoolean(externalBrowserKey, true);
|
||||||
|
DEBUG = sharedPreferences.getBoolean(debugKey, false);
|
||||||
|
|
||||||
|
/*** Initialize UI Objects ***/
|
||||||
|
actionBar = MainActivity.this.getSupportActionBar();
|
||||||
|
actionBar.setTitle(getString(R.string.app_title));
|
||||||
|
actionBar.setHomeButtonEnabled(true);
|
||||||
|
|
||||||
|
progressBar = (ProgressBar) findViewById(R.id.progressBar);
|
||||||
|
|
||||||
|
layout = (LinearLayout) findViewById(R.id.layout);
|
||||||
|
layout.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
debugCount++;
|
||||||
|
if (debugCount >= debugMax) {
|
||||||
|
Intent debugIntent = new Intent(MainActivity.this, DebugActivity.class);
|
||||||
|
startActivity(debugIntent);
|
||||||
|
}
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "MainActivity: debugCount=" + debugCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
btnExample = (Button) findViewById(R.id.btnExample);
|
||||||
|
|
||||||
|
// Data checks
|
||||||
|
action = MainActivity.this.getIntent().getAction();
|
||||||
|
if (action.isEmpty() || !action.contains("http")) {
|
||||||
|
url = getResources().getString(R.string.allStories);
|
||||||
|
homePage = true;
|
||||||
|
} else {
|
||||||
|
url = action;
|
||||||
|
homePage = false;
|
||||||
|
}
|
||||||
|
if (DEBUG) Log.d(TAG, "MainActivity: action=" + action + " url=" + url);
|
||||||
|
|
||||||
|
// Allow webpage download
|
||||||
|
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
|
||||||
|
StrictMode.setThreadPolicy(policy);
|
||||||
|
|
||||||
|
// Start the fun
|
||||||
|
this.refreshWebPage();
|
||||||
|
|
||||||
|
// ATTENTION: This was auto-generated to implement the App Indexing API.
|
||||||
|
// See https://g.co/AppIndexing/AndroidStudio for more information.
|
||||||
|
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String isNetworkAvailable() {
|
||||||
|
NetworkInfo info = ((ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (info.isConnected()) {
|
||||||
|
return networkConnected;
|
||||||
|
} else if (info.isRoaming()) {
|
||||||
|
return networkRoaming;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return networkDisconnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshWebPage() {
|
||||||
|
String status = isNetworkAvailable();
|
||||||
|
|
||||||
|
if (status.equals(networkConnected)) {
|
||||||
|
Runnable getWebsiteData = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
webPage = new WebPage(getBaseContext(), url);
|
||||||
|
loadArticles.sendEmptyMessage(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Thread t = new Thread(getWebsiteData);
|
||||||
|
progressBar.setIndeterminate(true);
|
||||||
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
|
t.start();
|
||||||
|
} else if (status.equals(networkRoaming)) {
|
||||||
|
Toast.makeText(this, "Currently Roaming -- Not Updating", Toast.LENGTH_LONG).show();
|
||||||
|
} else if (status.equals(networkDisconnected)) {
|
||||||
|
Toast.makeText(this, "Network Connection Not Found", Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Handler loadArticles = new Handler() {
|
||||||
|
@Override
|
||||||
|
public void handleMessage(Message msg) {
|
||||||
|
|
||||||
|
layout.removeAllViews();
|
||||||
|
|
||||||
|
progressBar.setMax(webPage.getTitles().size());
|
||||||
|
|
||||||
|
int index;
|
||||||
|
|
||||||
|
for (String title : webPage.getTitles()) {
|
||||||
|
index = webPage.getTitles().indexOf(title);
|
||||||
|
|
||||||
|
progressBar.setProgress(index);
|
||||||
|
progressBar.invalidate();
|
||||||
|
|
||||||
|
String date = webPage.getDates().get(index);
|
||||||
|
if (DEBUG) Log.d(TAG, "MainActivity: date=" + date + " title=" + title);
|
||||||
|
String text = date + '\n' + title;
|
||||||
|
|
||||||
|
// If we are on all-stories and on the first article
|
||||||
|
if (homePage && webPage.getTitles().indexOf(title) == 0) {
|
||||||
|
// Only update the Top Article if necessary
|
||||||
|
String oldTitle = sharedPreferences.getString(topArticleKey, "");
|
||||||
|
if (!oldTitle.equals(title)) {
|
||||||
|
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||||
|
editor.putString(topArticleKey, title);
|
||||||
|
editor.apply();
|
||||||
|
if (DEBUG) Log.d(TAG, "MainActivity: Top Article updated.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "MainActivity: title=" + title);
|
||||||
|
Log.d(TAG, "MainActivity: oldTitle=" + oldTitle);
|
||||||
|
Log.d(TAG, "MainActivity: sharedPreferences.TopArticle=" + sharedPreferences.getString(topArticleKey, ""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display all articles
|
||||||
|
if (!action.equals(url)) {
|
||||||
|
TextView spacer = new TextView(btnExample.getContext());
|
||||||
|
Button btn = new Button(btnExample.getContext());
|
||||||
|
btn.setText(text);
|
||||||
|
if (sharedPreferences.getBoolean(title, false)) {
|
||||||
|
btn.setBackgroundColor(getResources().getColor(R.color.articleRead));
|
||||||
|
} else {
|
||||||
|
btn.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
|
||||||
|
}
|
||||||
|
btn.setTextColor(Color.WHITE);
|
||||||
|
btn.setVisibility(View.VISIBLE);
|
||||||
|
btn.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Button b = (Button) v;
|
||||||
|
|
||||||
|
String text = b.getText().toString();
|
||||||
|
int newline = text.indexOf('\n');
|
||||||
|
|
||||||
|
String articleTitle = text.substring(newline + 1);
|
||||||
|
String articleLink = webPage.getLinks().get(webPage.getTitles().indexOf(articleTitle));
|
||||||
|
|
||||||
|
if (externalBrowser) {
|
||||||
|
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(articleLink));
|
||||||
|
startActivity(browserIntent);
|
||||||
|
} else {
|
||||||
|
Intent openArticle = new Intent(MainActivity.this, MainActivity.class);
|
||||||
|
openArticle.setAction(articleLink);
|
||||||
|
MainActivity.this.startActivity(openArticle);
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||||
|
editor.putBoolean(articleTitle, true);
|
||||||
|
editor.apply();
|
||||||
|
|
||||||
|
b.setBackgroundColor(getResources().getColor(R.color.articleRead));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
layout.addView(spacer);
|
||||||
|
layout.addView(btn);
|
||||||
|
}
|
||||||
|
// Internal browser
|
||||||
|
else {
|
||||||
|
TextView btn = new TextView(btnExample.getContext());
|
||||||
|
btn.setText(date + '\n' + title);
|
||||||
|
btn.setTextColor(getResources().getColor(R.color.colorPrimary));
|
||||||
|
btn.setTextSize(20);
|
||||||
|
btn.setVisibility(View.VISIBLE);
|
||||||
|
btn.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
TextView b = (TextView) v;
|
||||||
|
|
||||||
|
String text = b.getText().toString();
|
||||||
|
int newline = text.indexOf('\n');
|
||||||
|
|
||||||
|
String articleTitle = text.substring(newline + 1);
|
||||||
|
String articleLink = webPage.getLinks().get(webPage.getTitles().indexOf(articleTitle));
|
||||||
|
|
||||||
|
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(articleLink));
|
||||||
|
startActivity(browserIntent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
layout.addView(btn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (webPage.getTitles().size() == 1) {
|
||||||
|
layout.addView(webPage.getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
progressBar.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
// Reschedule the service
|
||||||
|
Intent restartService = new Intent(MainActivity.this, MyService.class);
|
||||||
|
startService(restartService);
|
||||||
|
|
||||||
|
super.handleMessage(msg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
getMenuInflater().inflate(R.menu.menu_main, menu);
|
||||||
|
|
||||||
|
MenuItem refresh = menu.findItem(R.id.refresh);
|
||||||
|
refresh.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemClick(MenuItem item) {
|
||||||
|
refreshWebPage();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
MenuItem checkForNewArticles = menu.findItem(R.id.checkForNewArticles);
|
||||||
|
checkForNewArticles.setChecked(sharedPreferences.getBoolean(checkForNewArticlesKey, true));
|
||||||
|
|
||||||
|
MenuItem externalBrowser = menu.findItem(R.id.externalBrowser);
|
||||||
|
externalBrowser.setChecked(sharedPreferences.getBoolean(externalBrowserKey, true));
|
||||||
|
|
||||||
|
return super.onCreateOptionsMenu(menu);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
@Override
|
||||||
|
public void onOptionsMenuClosed(Menu menu) {
|
||||||
|
super.onOptionsMenuClosed(menu);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
|
||||||
|
int id = item.getItemId();
|
||||||
|
|
||||||
|
String menuItemKey;
|
||||||
|
|
||||||
|
switch (id) {
|
||||||
|
case R.id.externalBrowser:
|
||||||
|
menuItemKey = externalBrowserKey;
|
||||||
|
break;
|
||||||
|
case R.id.checkForNewArticles:
|
||||||
|
menuItemKey = checkForNewArticlesKey;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean newValue = !sharedPreferences.getBoolean(menuItemKey, true);
|
||||||
|
|
||||||
|
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||||
|
editor.putBoolean(menuItemKey, newValue);
|
||||||
|
editor.apply();
|
||||||
|
|
||||||
|
if (id == R.id.externalBrowser) {
|
||||||
|
finish();
|
||||||
|
startActivity(this.getIntent());
|
||||||
|
}
|
||||||
|
|
||||||
|
item.setChecked(newValue);
|
||||||
|
|
||||||
|
Toast.makeText(this, "Settings saved.", Toast.LENGTH_LONG).show();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
debugCount = 0;
|
||||||
|
|
||||||
|
super.onResume();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ATTENTION: This was auto-generated to implement the App Indexing API.
|
||||||
|
* See https://g.co/AppIndexing/AndroidStudio for more information.
|
||||||
|
*/
|
||||||
|
public Action getIndexApiAction() {
|
||||||
|
Thing object = new Thing.Builder()
|
||||||
|
.setName("Main Page") // TODO: Define a title for the content shown.
|
||||||
|
// TODO: Make sure this auto-generated URL is correct.
|
||||||
|
.setUrl(Uri.parse("http://[ENTER-YOUR-URL-HERE]"))
|
||||||
|
.build();
|
||||||
|
return new Action.Builder(Action.TYPE_VIEW)
|
||||||
|
.setObject(object)
|
||||||
|
.setActionStatus(Action.STATUS_TYPE_COMPLETED)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
|
||||||
|
// ATTENTION: This was auto-generated to implement the App Indexing API.
|
||||||
|
// See https://g.co/AppIndexing/AndroidStudio for more information.
|
||||||
|
client.connect();
|
||||||
|
AppIndex.AppIndexApi.start(client, getIndexApiAction());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStop() {
|
||||||
|
super.onStop();
|
||||||
|
|
||||||
|
// ATTENTION: This was auto-generated to implement the App Indexing API.
|
||||||
|
// See https://g.co/AppIndexing/AndroidStudio for more information.
|
||||||
|
AppIndex.AppIndexApi.end(client, getIndexApiAction());
|
||||||
|
client.disconnect();
|
||||||
|
}
|
||||||
|
}
|
164
app/src/main/java/com/hyperling/apps/wheretheriverfrowns/MyService.java
Executable file
@ -0,0 +1,164 @@
|
|||||||
|
package com.hyperling.apps.wheretheriverfrowns;
|
||||||
|
|
||||||
|
import android.app.AlarmManager;
|
||||||
|
import android.app.IntentService;
|
||||||
|
import android.app.NotificationManager;
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
|
import android.net.NetworkInfo;
|
||||||
|
import android.os.PowerManager;
|
||||||
|
import android.support.v4.app.NotificationCompat;
|
||||||
|
import android.support.v4.app.TaskStackBuilder;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by ling on 10/2/16.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class MyService extends IntentService {
|
||||||
|
|
||||||
|
private String sharedPreferencesKey, topArticleKey, checkForNewArticlesKey, debugKey, lastServiceRunKey, nextServiceRunKey,
|
||||||
|
TAG,
|
||||||
|
url;
|
||||||
|
|
||||||
|
private SharedPreferences sharedPreferences;
|
||||||
|
|
||||||
|
private PowerManager.WakeLock wakeLock;
|
||||||
|
|
||||||
|
private AlarmManager alarmManager;
|
||||||
|
private PendingIntent reschedule;
|
||||||
|
|
||||||
|
private boolean DEBUG;
|
||||||
|
|
||||||
|
public MyService(){
|
||||||
|
super("MyService");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onHandleIntent(Intent intent) {
|
||||||
|
// Keys
|
||||||
|
sharedPreferencesKey = getString(R.string.sharedPreferencesKey);
|
||||||
|
topArticleKey = getString(R.string.topArticleKey);
|
||||||
|
checkForNewArticlesKey = getString(R.string.checkForNewArticlesKey);
|
||||||
|
debugKey = getString(R.string.debugKey);
|
||||||
|
lastServiceRunKey = getString(R.string.lastServiceRunKey);
|
||||||
|
nextServiceRunKey = getString(R.string.nextServiceRunKey);
|
||||||
|
|
||||||
|
// Strings
|
||||||
|
TAG = getString(R.string.TAG);
|
||||||
|
url = getString(R.string.allStories);
|
||||||
|
|
||||||
|
// Preferences
|
||||||
|
sharedPreferences = getSharedPreferences(sharedPreferencesKey, MODE_PRIVATE);
|
||||||
|
DEBUG = sharedPreferences.getBoolean(debugKey, false);
|
||||||
|
|
||||||
|
// Wake Lock
|
||||||
|
wakeLock = ((PowerManager) getSystemService(POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
|
||||||
|
wakeLock.acquire();
|
||||||
|
|
||||||
|
if (DEBUG) Log.d(TAG, "MyService: Service started.");
|
||||||
|
|
||||||
|
// Check if we have a connection
|
||||||
|
NetworkInfo info = ((ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
|
||||||
|
if (info == null || !info.isConnected() || info.isRoaming()){
|
||||||
|
if (DEBUG) Log.d(TAG, "MyService: Not polling due to network.");
|
||||||
|
rescheduleService(1);
|
||||||
|
stopSelf();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sharedPreferences.getBoolean(checkForNewArticlesKey, true)) {
|
||||||
|
wakeLock.acquire();
|
||||||
|
WebPage webPage = new WebPage(this, url);
|
||||||
|
if (!webPage.getTitles().isEmpty()) {
|
||||||
|
String newTopArticle = webPage.getTitles().get(0);
|
||||||
|
String newDate = webPage.getDates().get(0);
|
||||||
|
|
||||||
|
String lastTopArticle = sharedPreferences.getString("TopArticle", newTopArticle);
|
||||||
|
|
||||||
|
if (DEBUG){
|
||||||
|
Log.d(TAG, "MyService: lastTopArticle=" + lastTopArticle);
|
||||||
|
Log.d(TAG, "MyService: newTopArticle=" + newTopArticle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!newTopArticle.equals(lastTopArticle)) {
|
||||||
|
createNotification(newDate, newTopArticle);
|
||||||
|
} else {
|
||||||
|
rescheduleService(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release lock and resources
|
||||||
|
wakeLock.release();
|
||||||
|
stopSelf();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createNotification(String articleDate, String articleTitle){
|
||||||
|
if (DEBUG){
|
||||||
|
Log.d(TAG, "MyService: createNotification");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create notification
|
||||||
|
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
|
||||||
|
.setSmallIcon(R.drawable.wtrf_anarchy)
|
||||||
|
.setColor(getResources().getColor(R.color.colorPrimary))
|
||||||
|
.setContentTitle(getResources().getString(R.string.newArticleNotificationTitle) + " - " + articleDate)
|
||||||
|
.setContentText(articleTitle)
|
||||||
|
.setAutoCancel(true);
|
||||||
|
|
||||||
|
// Link so the notification opens WTRF
|
||||||
|
Intent notificationLink = new Intent(this, MainActivity.class);
|
||||||
|
notificationLink.setAction("");
|
||||||
|
|
||||||
|
// Allow using back to leave app
|
||||||
|
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
|
||||||
|
stackBuilder.addParentStack(MainActivity.class);
|
||||||
|
stackBuilder.addNextIntent(notificationLink);
|
||||||
|
PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
|
||||||
|
// Add it all to the notification
|
||||||
|
notificationBuilder.setContentIntent(pendingIntent);
|
||||||
|
|
||||||
|
// Display notification
|
||||||
|
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||||
|
manager.notify(TAG, 0, notificationBuilder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rescheduleService(int hours){
|
||||||
|
// Schedule next run after an hour or so
|
||||||
|
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
|
||||||
|
reschedule = PendingIntent.getBroadcast(this, 0, new Intent("com.hyperling.wheretheriverfrowns.ALARM_STARTED"), 0);
|
||||||
|
|
||||||
|
long convertedHours = 1000*60*60*hours;
|
||||||
|
|
||||||
|
long currentTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
alarmManager.cancel(reschedule);
|
||||||
|
alarmManager.set(AlarmManager.RTC_WAKEUP, currentTime + convertedHours, reschedule);
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "MyService: rescheduleService: Rescheduled for " + hours + " hour(s).");
|
||||||
|
Log.d(TAG, "MyService: rescheduleService: Current time= " + currentTime + ", reschedule time=" + currentTime + convertedHours);
|
||||||
|
|
||||||
|
Date date = new Date();
|
||||||
|
String prettyDate;
|
||||||
|
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||||
|
|
||||||
|
date.setTime(currentTime);
|
||||||
|
prettyDate = date.toString();
|
||||||
|
editor.putString(lastServiceRunKey, prettyDate);
|
||||||
|
|
||||||
|
date.setTime(currentTime + convertedHours);
|
||||||
|
prettyDate = date.toString();
|
||||||
|
editor.putString(nextServiceRunKey, prettyDate);
|
||||||
|
|
||||||
|
editor.apply();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package com.hyperling.apps.wheretheriverfrowns;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.support.v4.content.WakefulBroadcastReceiver;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import static android.content.Context.MODE_PRIVATE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by ling on 10/11/16.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ServiceReceiver extends WakefulBroadcastReceiver {
|
||||||
|
private SharedPreferences sharedPreferences;
|
||||||
|
|
||||||
|
private String sharedPreferencesKey, debugKey, TAG;
|
||||||
|
|
||||||
|
private static boolean DEBUG;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
|
||||||
|
// Keys
|
||||||
|
sharedPreferencesKey = context.getString(R.string.sharedPreferencesKey);
|
||||||
|
debugKey = context.getString(R.string.debugKey);
|
||||||
|
|
||||||
|
// Strings
|
||||||
|
TAG = context.getResources().getString(R.string.TAG);
|
||||||
|
|
||||||
|
// Preferences
|
||||||
|
sharedPreferences = context.getSharedPreferences(sharedPreferencesKey, MODE_PRIVATE);
|
||||||
|
DEBUG = sharedPreferences.getBoolean(debugKey, false);
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "ServiceReceiver: onReceive: intent.getAction()=" + intent.getAction());
|
||||||
|
}
|
||||||
|
|
||||||
|
Intent serviceIntent = new Intent(context, MyService.class);
|
||||||
|
context.startService(serviceIntent);
|
||||||
|
}
|
||||||
|
}
|
234
app/src/main/java/com/hyperling/apps/wheretheriverfrowns/WebPage.java
Executable file
@ -0,0 +1,234 @@
|
|||||||
|
package com.hyperling.apps.wheretheriverfrowns;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by ling on 9/24/16.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class WebPage {
|
||||||
|
private Context context;
|
||||||
|
|
||||||
|
private String link;
|
||||||
|
private String html = "";
|
||||||
|
|
||||||
|
private int index;
|
||||||
|
|
||||||
|
private ArrayList<String> titles;
|
||||||
|
private ArrayList<String> links;
|
||||||
|
private ArrayList<String> dates;
|
||||||
|
|
||||||
|
private LinearLayout content;
|
||||||
|
|
||||||
|
private boolean DEBUG = false;
|
||||||
|
private String TAG;
|
||||||
|
|
||||||
|
public WebPage(Context context, String link) {
|
||||||
|
TAG = context.getResources().getString(R.string.TAG);
|
||||||
|
|
||||||
|
this.context = context;
|
||||||
|
this.link = link;
|
||||||
|
URL url;
|
||||||
|
InputStream is = null;
|
||||||
|
BufferedReader br;
|
||||||
|
String line;
|
||||||
|
|
||||||
|
titles = new ArrayList<>();
|
||||||
|
links = new ArrayList<>();
|
||||||
|
dates = new ArrayList<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
url = new URL(link);
|
||||||
|
is = url.openStream(); // throws an IOException
|
||||||
|
br = new BufferedReader(new InputStreamReader(is));
|
||||||
|
|
||||||
|
while ((line = br.readLine()) != null) {
|
||||||
|
html = html.concat(line);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (is != null) is.close();
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
// nothing to see here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (html.length() > 0) {
|
||||||
|
html = html.replace(""", "\"");
|
||||||
|
|
||||||
|
int nextArticle;
|
||||||
|
index = 0;
|
||||||
|
while (findArticle() > 0) {
|
||||||
|
// Move to the next article
|
||||||
|
nextArticle = findArticle();
|
||||||
|
html = html.substring(nextArticle);
|
||||||
|
|
||||||
|
// Get the url
|
||||||
|
html = html.substring(html.indexOf("href=") + 6);
|
||||||
|
String articleLink = html.substring(0, html.indexOf('\"'));
|
||||||
|
links.add(index, articleLink);
|
||||||
|
|
||||||
|
// Get the title
|
||||||
|
html = html.substring(html.indexOf('>') + 1);
|
||||||
|
String articleTitle = html.substring(0, html.indexOf("</a>"));
|
||||||
|
articleTitle = removeSpaces(articleTitle);
|
||||||
|
titles.add(index, articleTitle);
|
||||||
|
|
||||||
|
// Get the date
|
||||||
|
/* Date looks like:
|
||||||
|
<p class="blog-date">
|
||||||
|
<span class="date-text">9/21/2016</span>
|
||||||
|
</p>
|
||||||
|
*/
|
||||||
|
html = html.substring(html.indexOf("<p class=\"blog-date\">"));
|
||||||
|
html = html.substring(html.indexOf('>') + 1);
|
||||||
|
html = html.substring(html.indexOf('>') + 1);
|
||||||
|
String articleDate = html.substring(0, html.indexOf("</span>"));
|
||||||
|
articleDate = removeSpaces(articleDate);
|
||||||
|
dates.add(index, articleDate);
|
||||||
|
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context != null) {
|
||||||
|
if (index == 1) {
|
||||||
|
// Page is an article, get text
|
||||||
|
/* Text starts at:
|
||||||
|
<div class="blog-content">
|
||||||
|
*/
|
||||||
|
content = new LinearLayout(context);
|
||||||
|
content.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
|
||||||
|
html = html.substring(html.indexOf("<div class=\"blog-content\">"));
|
||||||
|
html = html.substring(html.indexOf('>') + 1);
|
||||||
|
|
||||||
|
if (DEBUG) Log.d(TAG, "DEBUG: WebPage: html=" + html);
|
||||||
|
|
||||||
|
int level = 1;
|
||||||
|
String contentText = "";
|
||||||
|
while (level > 0) {
|
||||||
|
/*
|
||||||
|
Paragraphs looks like:
|
||||||
|
<div class="paragraph">
|
||||||
|
|
||||||
|
New TextViews at:
|
||||||
|
<br></br>
|
||||||
|
|
||||||
|
level += 1 at <
|
||||||
|
level -= 2 at </
|
||||||
|
|
||||||
|
Otherwise just grab everything between ><
|
||||||
|
*/
|
||||||
|
|
||||||
|
while (html.indexOf('&') < html.indexOf('<')) {
|
||||||
|
contentText = contentText.concat(html.substring(0, html.indexOf('&')));
|
||||||
|
html = html.substring(html.indexOf(';') + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
contentText = contentText.concat(html.substring(0, html.indexOf('<')));
|
||||||
|
contentText = removeSpaces(contentText);
|
||||||
|
|
||||||
|
|
||||||
|
html = html.substring(html.indexOf('<'));
|
||||||
|
|
||||||
|
// TODO: Testing only
|
||||||
|
if (level > 0) {
|
||||||
|
//System.out.println("DEBUG: level=" + level + " html=" + html);
|
||||||
|
//System.out.println("DEBUG: contentText=" + contentText);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (html.indexOf("<div class=\"paragraph\">") == 0) {
|
||||||
|
|
||||||
|
TextView newView = new TextView(context);
|
||||||
|
newView.setText(contentText);
|
||||||
|
newView.setTextColor(Color.BLACK);
|
||||||
|
content.addView(newView);
|
||||||
|
|
||||||
|
contentText = "";
|
||||||
|
} else if (html.indexOf("<br>") == 0 || html.indexOf("<br />") == 0) {
|
||||||
|
contentText = contentText.concat("\n");
|
||||||
|
level -= 1;
|
||||||
|
} else if (html.indexOf("<meta ") == 0) {
|
||||||
|
level -= 1;
|
||||||
|
} else if (html.indexOf("<img ") == 0) {
|
||||||
|
level -= 1;
|
||||||
|
} else if (html.indexOf("<!--") == 0) {
|
||||||
|
level -= 1;
|
||||||
|
} else if (html.indexOf("</") == 0) {
|
||||||
|
level -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (html.indexOf("/>") < html.indexOf(">")) {
|
||||||
|
level -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
html = html.substring(html.indexOf('>') + 1);
|
||||||
|
level += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextView newView = new TextView(context);
|
||||||
|
newView.setText(contentText);
|
||||||
|
newView.setTextColor(Color.BLACK);
|
||||||
|
content.addView(newView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int findArticle(){
|
||||||
|
/* Example of an article title:
|
||||||
|
<a class="blog-title-link blog-link" href="http://www.wheretheriverfrowns.com/all-stories/kite-line-september-16-2016-national-prison-strike-updates">Kite Line – September 16, 2016: National Prison Strike Updates</a>
|
||||||
|
*/
|
||||||
|
return html.indexOf("<a class=\"blog-title-link blog-link\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Testing only
|
||||||
|
public String getHTML(){
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
public String getLink(){
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<String> getTitles(){
|
||||||
|
return titles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<String> getLinks(){
|
||||||
|
return links;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<String> getDates(){
|
||||||
|
return dates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LinearLayout getContent(){
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String removeSpaces(String string){
|
||||||
|
while(string.contains(" ")) {
|
||||||
|
string = string.replace(" ", " ");
|
||||||
|
}
|
||||||
|
//string = string.replace("\n", "");
|
||||||
|
string = string.replace("\t", "");
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDEBUG(boolean debug){
|
||||||
|
this.DEBUG = debug;
|
||||||
|
}
|
||||||
|
}
|
9
app/src/main/res/drawable/ic_info_black_24dp.xml
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportHeight="24.0"
|
||||||
|
android:viewportWidth="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zm1,15h-2v-6h2v6zm0,-8h-2V7h2v2z" />
|
||||||
|
</vector>
|
9
app/src/main/res/drawable/ic_notifications_black_24dp.xml
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportHeight="24.0"
|
||||||
|
android:viewportWidth="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M11.5,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.9,2 2,2zm6.5,-6v-5.5c0,-3.07 -2.13,-5.64 -5,-6.32V3.5c0,-0.83 -0.67,-1.5 -1.5,-1.5S10,2.67 10,3.5v0.68c-2.87,0.68 -5,3.25 -5,6.32V16l-2,2v1h17v-1l-2,-2z" />
|
||||||
|
</vector>
|
9
app/src/main/res/drawable/ic_sync_black_24dp.xml
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportHeight="24.0"
|
||||||
|
android:viewportWidth="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01,-.25 1.97,-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0,-4.42,-3.58,-8,-8,-8zm0 14c-3.31 0,-6,-2.69,-6,-6 0,-1.01.25,-1.97.7,-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4,-4,-4,-4v3z" />
|
||||||
|
</vector>
|
BIN
app/src/main/res/drawable/wtrf.png
Executable file
After Width: | Height: | Size: 311 KiB |
BIN
app/src/main/res/drawable/wtrf_anarchy.png
Executable file
After Width: | Height: | Size: 1.8 KiB |
26
app/src/main/res/layout/activity_debug.xml
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/debugLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||||
|
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingTop="@dimen/activity_vertical_margin"
|
||||||
|
tools:context="com.hyperling.apps.wheretheriverfrowns.DebugActivity">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnDebugExit"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/btnDebug"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnResetPreferences"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/btnResetPreferences"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
43
app/src/main/res/layout/activity_main.xml
Executable file
@ -0,0 +1,43 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/activity_main"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||||
|
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||||
|
android:paddingTop="@dimen/activity_vertical_margin"
|
||||||
|
tools:context="com.hyperling.apps.wheretheriverfrowns.MainActivity">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/app_version"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
style="?android:attr/progressBarStyleLarge"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layout"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnExample"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="5dp"/>
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
||||||
|
</LinearLayout>
|
28
app/src/main/res/menu/menu_main.xml
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<group android:id="@+id/functionality">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/refresh"
|
||||||
|
android:enabled="true"
|
||||||
|
android:visible="true"
|
||||||
|
android:title="@string/refresh"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/checkForNewArticles"
|
||||||
|
android:checkable="true"
|
||||||
|
android:enabled="true"
|
||||||
|
android:visible="true"
|
||||||
|
android:title="@string/checkForNewArticles"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/externalBrowser"
|
||||||
|
android:checkable="true"
|
||||||
|
android:enabled="false"
|
||||||
|
android:visible="false"
|
||||||
|
android:title="@string/externalBrowser"/>
|
||||||
|
|
||||||
|
</group>
|
||||||
|
|
||||||
|
</menu>
|
BIN
app/src/main/res/mipmap-hdpi/ic_launcher.png
Executable file
After Width: | Height: | Size: 3.3 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher.png
Executable file
After Width: | Height: | Size: 2.2 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.png
Executable file
After Width: | Height: | Size: 4.7 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Executable file
After Width: | Height: | Size: 7.5 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Executable file
After Width: | Height: | Size: 10 KiB |
6
app/src/main/res/values-w820dp/dimens.xml
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
<resources>
|
||||||
|
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
|
||||||
|
(such as screen margins) for screens with more than 820dp of available width. This
|
||||||
|
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
|
||||||
|
<dimen name="activity_horizontal_margin">64dp</dimen>
|
||||||
|
</resources>
|
19
app/src/main/res/values/colors.xml
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<!-- DEFAULTS
|
||||||
|
<color name="colorPrimary">#3F51B5</color>
|
||||||
|
<color name="colorPrimaryDark">#303F9F</color>
|
||||||
|
<color name="colorAccent">#FF4081</color>
|
||||||
|
-->
|
||||||
|
<!-- Facebook icon + website
|
||||||
|
<color name="colorPrimary">#BBC4CB</color>
|
||||||
|
<color name="colorPrimaryDark">#223E90</color>
|
||||||
|
<color name="colorAccent">#564A37</color>
|
||||||
|
-->
|
||||||
|
<!-- Website Only. if need white, use FDFDFE-->
|
||||||
|
<color name="colorPrimary">#68A2C1</color>
|
||||||
|
<color name="colorPrimaryDark">#000000</color>
|
||||||
|
<color name="colorAccent">#68A2C1</color>
|
||||||
|
|
||||||
|
<color name="articleRead">#999999</color>
|
||||||
|
</resources>
|
5
app/src/main/res/values/dimens.xml
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
<resources>
|
||||||
|
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||||
|
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||||
|
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||||
|
</resources>
|
39
app/src/main/res/values/strings.xml
Executable file
@ -0,0 +1,39 @@
|
|||||||
|
<resources>
|
||||||
|
<string name="app_name">WtRF News</string>
|
||||||
|
<string name="app_title">Where the River Frowns</string>
|
||||||
|
<string name="app_version">v201611121043</string>
|
||||||
|
<string name="title_activity_settings">Settings</string>
|
||||||
|
<string name="TAG">com.hyperling.apps.wheretheriverfrowns</string>
|
||||||
|
|
||||||
|
<!-- WTRF URL of where all the stories are -->
|
||||||
|
<string name="allStories">http://www.wheretheriverfrowns.com/all-stories</string>
|
||||||
|
|
||||||
|
<!-- Shared Preference Key -->
|
||||||
|
<string name="sharedPreferencesKey">wtrf</string>
|
||||||
|
|
||||||
|
<!-- Shared preference entries -->
|
||||||
|
<string name="topArticleKey">TopArticle</string>
|
||||||
|
<string name="externalBrowserKey">ExternalBrowser</string>
|
||||||
|
<string name="checkForNewArticlesKey">CheckForNewArticles</string>
|
||||||
|
<string name="debugKey">DEBUG</string>
|
||||||
|
<string name="lastServiceRunKey">LastServiceRun</string>
|
||||||
|
<string name="nextServiceRunKey">NextServiceRun</string>
|
||||||
|
|
||||||
|
<!-- Connection types -->
|
||||||
|
<string name="networkConnected">c</string>
|
||||||
|
<string name="networkRoaming">r</string>
|
||||||
|
<string name="networkDisconnected">d</string>
|
||||||
|
|
||||||
|
<!-- Strings related to Action Menu -->
|
||||||
|
<string name="refresh">Refresh</string>
|
||||||
|
<string name="checkForNewArticles">Notify on New Articles?</string>
|
||||||
|
<string name="externalBrowser">Use External Browser?</string>
|
||||||
|
|
||||||
|
<!-- Notification Title -->
|
||||||
|
<string name="newArticleNotificationTitle">New WtRF Article</string>
|
||||||
|
|
||||||
|
<!-- Debug Activity -->
|
||||||
|
<string name="debugActivityTitle">Debug Menu</string>
|
||||||
|
<string name="btnDebug">DEBUG MODE</string>
|
||||||
|
<string name="btnResetPreferences">Reset Preferences</string>
|
||||||
|
</resources>
|
12
app/src/main/res/values/styles.xml
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
<resources>
|
||||||
|
|
||||||
|
<!-- Base application theme. -->
|
||||||
|
<style name="wtrf" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||||
|
<!-- Customize your theme here. -->
|
||||||
|
<item name="colorPrimary">@color/colorPrimary</item>
|
||||||
|
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||||
|
<item name="colorAccent">@color/colorAccent</item>
|
||||||
|
<item name="android:textAllCaps">false</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</resources>
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.hyperling.apps.wheretheriverfrowns;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example local unit test, which will execute on the development machine (host).
|
||||||
|
*
|
||||||
|
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||||
|
*/
|
||||||
|
public class ExampleUnitTest {
|
||||||
|
@Test
|
||||||
|
public void addition_isCorrect() throws Exception {
|
||||||
|
assertEquals(4, 2 + 2);
|
||||||
|
}
|
||||||
|
}
|
24
build.gradle
Executable file
@ -0,0 +1,24 @@
|
|||||||
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
jcenter()
|
||||||
|
google()
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.android.tools.build:gradle:3.1.3'
|
||||||
|
|
||||||
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
|
// in the individual module build.gradle files
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
repositories {
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task clean(type: Delete) {
|
||||||
|
delete rootProject.buildDir
|
||||||
|
}
|
BIN
gimp/banner.png
Executable file
After Width: | Height: | Size: 828 KiB |
BIN
gimp/banner.xcf
Executable file
BIN
gimp/map.jpg
Executable file
After Width: | Height: | Size: 606 KiB |
BIN
gimp/wtrf.png
Executable file
After Width: | Height: | Size: 311 KiB |
BIN
gimp/wtrf_anarchy.png
Executable file
After Width: | Height: | Size: 1.8 KiB |
17
gradle.properties
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
# Project-wide Gradle settings.
|
||||||
|
|
||||||
|
# IDE (e.g. Android Studio) users:
|
||||||
|
# Gradle settings configured through the IDE *will override*
|
||||||
|
# any settings specified in this file.
|
||||||
|
|
||||||
|
# For more details on how to configure your build environment visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||||
|
|
||||||
|
# Specifies the JVM arguments used for the daemon process.
|
||||||
|
# The setting is particularly useful for tweaking memory settings.
|
||||||
|
org.gradle.jvmargs=-Xmx1536m
|
||||||
|
|
||||||
|
# When configured, Gradle will run in incubating parallel mode.
|
||||||
|
# This option should only be used with decoupled projects. More details, visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||||
|
# org.gradle.parallel=true
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Executable file
6
gradle/wrapper/gradle-wrapper.properties
vendored
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#Sat Jun 16 09:49:57 CDT 2018
|
||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
|
160
gradlew
vendored
Executable file
@ -0,0 +1,160 @@
|
|||||||
|
#!/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
|
||||||
|
|
||||||
|
# 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\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
|
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"`
|
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
|
# 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
gradlew.bat
vendored
Executable 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
|
1
settings.gradle
Executable file
@ -0,0 +1 @@
|
|||||||
|
include ':app'
|