diff --git a/examples/java/hello_world/BUILD b/examples/java/hello_world/BUILD index 3a23b6f5cc..e9097d1f9a 100644 --- a/examples/java/hello_world/BUILD +++ b/examples/java/hello_world/BUILD @@ -4,15 +4,16 @@ android_binary( name = "hello_envoy", srcs = [ "MainActivity.java", - "Response.java", - "ResponseRecyclerViewAdapter.java", - "ResponseViewHolder.java", ], custom_package = "io.envoyproxy.envoymobile.helloenvoy", manifest = "AndroidManifest.xml", - resource_files = glob(["res/**"]), + resource_files = [ + "res/layout/activity_main.xml", + "res/raw/config.yaml", + ], deps = [ "//dist:envoy_mobile_android", + "//examples/kotlin/shared:hello_envoy_shared_lib", "@androidsdk//com.android.support:appcompat-v7-25.0.0", "@androidsdk//com.android.support:recyclerview-v7-25.0.0", ], diff --git a/examples/java/hello_world/MainActivity.java b/examples/java/hello_world/MainActivity.java index 8951d2efb3..14ce145a99 100644 --- a/examples/java/hello_world/MainActivity.java +++ b/examples/java/hello_world/MainActivity.java @@ -9,6 +9,11 @@ import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; +import io.envoyproxy.envoymobile.Envoy; +import io.envoyproxy.envoymobile.shared.Failure; +import io.envoyproxy.envoymobile.shared.Response; +import io.envoyproxy.envoymobile.shared.ResponseRecyclerViewAdapter; +import io.envoyproxy.envoymobile.shared.Success; import java.io.BufferedReader; import java.io.IOException; @@ -19,8 +24,6 @@ import java.util.List; import java.util.concurrent.TimeUnit; -import io.envoyproxy.envoymobile.Envoy; - public class MainActivity extends Activity { private static final String ENDPOINT = "http://0.0.0.0:9001/api.lyft.com/static/demo/hello_world.txt"; @@ -29,12 +32,11 @@ public class MainActivity extends Activity { private static final String REQUEST_HANDLER_THREAD_NAME = "hello_envoy_java"; + private Envoy envoy; private RecyclerView recyclerView; private HandlerThread thread = new HandlerThread(REQUEST_HANDLER_THREAD_NAME); - private Envoy envoy; - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -44,7 +46,7 @@ protected void onCreate(Bundle savedInstanceState) { Envoy.load(context); // Create envoy instance with config. - String config = null; + String config; try { config = loadEnvoyConfig(getBaseContext(), R.raw.config); } catch (RuntimeException e) { @@ -68,12 +70,8 @@ protected void onCreate(Bundle savedInstanceState) { handler.postDelayed(new Runnable() { @Override public void run() { - try { - final Response response = makeRequest(); - recyclerView.post((Runnable)() -> adapter.add(response)); - } catch (IOException e) { - Log.d("MainActivity", "exception making request.", e); - } + final Response response = makeRequest(); + recyclerView.post((Runnable)() -> adapter.add(response)); // Make a call again handler.postDelayed(this, TimeUnit.SECONDS.toMillis(1)); @@ -86,21 +84,25 @@ protected void onDestroy() { thread.quit(); } - private Response makeRequest() throws IOException { - URL url = new URL(ENDPOINT); - // Open connection to the envoy thread listening locally on port 9001. - HttpURLConnection connection = (HttpURLConnection)url.openConnection(); - int status = connection.getResponseCode(); - if (status != 200) { - throw new IOException("non 200 status: " + status); + private Response makeRequest() { + try { + URL url = new URL(ENDPOINT); + // Open connection to the envoy thread listening locally on port 9001. + HttpURLConnection connection = (HttpURLConnection)url.openConnection(); + int status = connection.getResponseCode(); + if (status == 200) { + List serverHeaderField = connection.getHeaderFields().get(ENVOY_SERVER_HEADER); + InputStream inputStream = connection.getInputStream(); + String body = deserialize(inputStream); + inputStream.close(); + return new Success(body, + serverHeaderField != null ? String.join(", ", serverHeaderField) : ""); + } else { + return new Failure("failed with status " + status); + } + } catch (Exception e) { + return new Failure(e.getMessage()); } - - List serverHeaderField = connection.getHeaderFields().get(ENVOY_SERVER_HEADER); - InputStream inputStream = connection.getInputStream(); - String body = deserialize(inputStream); - inputStream.close(); - return new Response(body, - serverHeaderField != null ? String.join(", ", serverHeaderField) : ""); } private String deserialize(InputStream inputStream) throws IOException { diff --git a/examples/java/hello_world/Response.java b/examples/java/hello_world/Response.java deleted file mode 100644 index 2db0e79942..0000000000 --- a/examples/java/hello_world/Response.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.envoyproxy.envoymobile.helloenvoy; - -// Response is a class to handle HTTP responses. -public class Response { - public final String title; - public final String header; - - public Response(String title, String header) { - this.title = title; - this.header = header; - } -} diff --git a/examples/java/hello_world/ResponseRecyclerViewAdapter.java b/examples/java/hello_world/ResponseRecyclerViewAdapter.java deleted file mode 100644 index 76ae3d4ac5..0000000000 --- a/examples/java/hello_world/ResponseRecyclerViewAdapter.java +++ /dev/null @@ -1,37 +0,0 @@ -package io.envoyproxy.envoymobile.helloenvoy; - -import android.content.Context; -import android.support.v7.widget.RecyclerView; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import java.util.ArrayList; -import java.util.List; - -public class ResponseRecyclerViewAdapter extends RecyclerView.Adapter { - private final List data = new ArrayList<>(); - - @Override - public ResponseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - Context context = parent.getContext(); - LayoutInflater inflater = LayoutInflater.from(context); - View view = inflater.inflate(R.layout.item, parent, false); - return new ResponseViewHolder(view); - } - - @Override - public void onBindViewHolder(ResponseViewHolder holder, int position) { - holder.setResult(data.get(position)); - } - - @Override - public int getItemCount() { - return data.size(); - } - - public void add(Response response) { - data.add(0, response); - notifyItemInserted(0); - } -} diff --git a/examples/java/hello_world/ResponseViewHolder.java b/examples/java/hello_world/ResponseViewHolder.java deleted file mode 100644 index a6650241b0..0000000000 --- a/examples/java/hello_world/ResponseViewHolder.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.envoyproxy.envoymobile.helloenvoy; - -import android.support.v7.widget.RecyclerView; -import android.view.View; -import android.widget.TextView; - -public class ResponseViewHolder extends RecyclerView.ViewHolder { - private final TextView responseTextView; - private final TextView headerTextView; - - public ResponseViewHolder(View itemView) { - super(itemView); - this.responseTextView = (TextView)itemView.findViewById(R.id.response_text_view); - this.headerTextView = (TextView)itemView.findViewById(R.id.header_text_view); - } - - public void setResult(Response response) { - responseTextView.setText( - responseTextView.getResources().getString(R.string.title_string, response.title)); - headerTextView.setText( - headerTextView.getResources().getString(R.string.header_string, response.header)); - } -} diff --git a/examples/java/hello_world/res/layout/item.xml b/examples/java/hello_world/res/layout/item.xml deleted file mode 100644 index 5746718d45..0000000000 --- a/examples/java/hello_world/res/layout/item.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - diff --git a/examples/kotlin/hello_world/BUILD b/examples/kotlin/hello_world/BUILD index 8c512b48b5..a7a3e32a35 100644 --- a/examples/kotlin/hello_world/BUILD +++ b/examples/kotlin/hello_world/BUILD @@ -18,18 +18,16 @@ kt_android_library( name = "hello_envoy_kt_lib", srcs = [ "MainActivity.kt", - "Response.kt", - "ResponseRecyclerViewAdapter.kt", - "ResponseViewHolder.kt", ], custom_package = "io.envoyproxy.envoymobile.helloenvoykotlin", manifest = "AndroidManifest.xml", - resource_files = glob([ - "res/**/*.xml", - "res/**/*.yaml", - ]), + resource_files = [ + "res/layout/activity_main.xml", + "res/raw/config.yaml", + ], deps = [ "//dist:envoy_mobile_android", + "//examples/kotlin/shared:hello_envoy_shared_lib", "@androidsdk//com.android.support:appcompat-v7-25.0.0", "@androidsdk//com.android.support:recyclerview-v7-25.0.0", ], diff --git a/examples/kotlin/hello_world/MainActivity.kt b/examples/kotlin/hello_world/MainActivity.kt index 1f5ed4a099..37d134a4ec 100644 --- a/examples/kotlin/hello_world/MainActivity.kt +++ b/examples/kotlin/hello_world/MainActivity.kt @@ -9,15 +9,17 @@ import android.support.v7.widget.DividerItemDecoration import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.RecyclerView import android.util.Log - +import io.envoyproxy.envoymobile.Envoy +import io.envoyproxy.envoymobile.shared.Failure +import io.envoyproxy.envoymobile.shared.Response +import io.envoyproxy.envoymobile.shared.ResponseRecyclerViewAdapter +import io.envoyproxy.envoymobile.shared.Success import java.io.IOException import java.io.InputStream import java.net.HttpURLConnection import java.net.URL import java.util.concurrent.TimeUnit -import io.envoyproxy.envoymobile.Envoy - private const val REQUEST_HANDLER_THREAD_NAME = "hello_envoy_kt" private const val ENDPOINT = "http://0.0.0.0:9001/api.lyft.com/static/demo/hello_world.txt" private const val ENVOY_SERVER_HEADER = "server" @@ -32,7 +34,7 @@ class MainActivity : Activity() { setContentView(R.layout.activity_main) Envoy.load(baseContext) - + // Create Envoy instance with config. envoy = Envoy(baseContext, loadEnvoyConfig(baseContext, R.raw.config)) @@ -51,7 +53,7 @@ class MainActivity : Activity() { override fun run() { try { val response = makeRequest() - recyclerView.post({ adapter.add(response) }) + recyclerView.post { adapter.add(response) } } catch (e: IOException) { Log.d("MainActivity", "exception making request.", e) } @@ -68,19 +70,23 @@ class MainActivity : Activity() { } private fun makeRequest(): Response { - val url = URL(ENDPOINT) - // Open connection to the envoy thread listening locally on port 9001 - val connection = url.openConnection() as HttpURLConnection - val status = connection.responseCode - if (status != 200) { - throw IOException("non 200 status: $status") + return try { + val url = URL(ENDPOINT) + // Open connection to the envoy thread listening locally on port 9001 + val connection = url.openConnection() as HttpURLConnection + val status = connection.responseCode + if (status == 200) { + val serverHeaderField = connection.headerFields[ENVOY_SERVER_HEADER] + val inputStream = connection.inputStream + val body = deserialize(inputStream) + inputStream.close() + Success(body, serverHeaderField?.joinToString(separator = ", ") ?: "") + } else { + Failure("failed with status: $status") + } + } catch (e: IOException) { + Failure(e.message ?: "failed with exception") } - - val serverHeaderField = connection.headerFields[ENVOY_SERVER_HEADER] - val inputStream = connection.inputStream - val body = deserialize(inputStream) - inputStream.close() - return Response(body, serverHeaderField?.joinToString(separator = ", ") ?: "") } private fun deserialize(inputStream: InputStream): String { diff --git a/examples/kotlin/hello_world/Response.kt b/examples/kotlin/hello_world/Response.kt deleted file mode 100644 index 1e57fd6401..0000000000 --- a/examples/kotlin/hello_world/Response.kt +++ /dev/null @@ -1,4 +0,0 @@ -package io.envoyproxy.envoymobile.helloenvoykotlin - -// Response is a class to handle HTTP responses. -class Response(val title: String, val header: String) diff --git a/examples/kotlin/hello_world/ResponseViewHolder.kt b/examples/kotlin/hello_world/ResponseViewHolder.kt deleted file mode 100644 index f50d4a5118..0000000000 --- a/examples/kotlin/hello_world/ResponseViewHolder.kt +++ /dev/null @@ -1,15 +0,0 @@ -package io.envoyproxy.envoymobile.helloenvoykotlin - -import android.support.v7.widget.RecyclerView -import android.view.View -import android.widget.TextView - -class ResponseViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - private val responseTextView: TextView = itemView.findViewById(R.id.response_text_view) as TextView - private val headerTextView: TextView = itemView.findViewById(R.id.header_text_view) as TextView - - fun setResult(response: Response) { - responseTextView.text = responseTextView.resources.getString(R.string.title_string, response.title) - headerTextView.text = headerTextView.resources.getString(R.string.header_string, response.header) - } -} diff --git a/examples/kotlin/hello_world/res/values/strings.xml b/examples/kotlin/hello_world/res/values/strings.xml deleted file mode 100644 index 77cc7a52c9..0000000000 --- a/examples/kotlin/hello_world/res/values/strings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - Response: %s - \'Server\' header: %s - diff --git a/examples/kotlin/shared/AndroidManifest.xml b/examples/kotlin/shared/AndroidManifest.xml new file mode 100644 index 0000000000..9fe115fcd0 --- /dev/null +++ b/examples/kotlin/shared/AndroidManifest.xml @@ -0,0 +1,5 @@ + + diff --git a/examples/kotlin/shared/BUILD b/examples/kotlin/shared/BUILD new file mode 100644 index 0000000000..5e54e4b78f --- /dev/null +++ b/examples/kotlin/shared/BUILD @@ -0,0 +1,25 @@ +licenses(["notice"]) # Apache 2 + +load("@envoy//bazel:envoy_build_system.bzl", "envoy_package") +load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_android_library") + +envoy_package() + +kt_android_library( + name = "hello_envoy_shared_lib", + srcs = [ + "Response.kt", + "ResponseRecyclerViewAdapter.kt", + "ResponseViewHolder.kt", + ], + custom_package = "io.envoyproxy.envoymobile.shared", + manifest = "AndroidManifest.xml", + resource_files = glob([ + "res/layout/item.xml", + "res/values/colors.xml", + "res/values/strings.xml", + ]), + deps = [ + "@androidsdk//com.android.support:recyclerview-v7-25.0.0", + ], +) diff --git a/examples/kotlin/shared/Response.kt b/examples/kotlin/shared/Response.kt new file mode 100644 index 0000000000..f3fb29c8c2 --- /dev/null +++ b/examples/kotlin/shared/Response.kt @@ -0,0 +1,16 @@ +package io.envoyproxy.envoymobile.shared + +// Response is a class to handle HTTP responses. +sealed class Response { + fun fold(success: (Success) -> Unit, failure: (Failure) -> Unit) = when (this) { + is Success -> success(this) + is Failure -> failure(this) + } +} + +data class Success(val title: String, val header: String) : Response() + +data class Failure(val message: String) : Response() + + + diff --git a/examples/kotlin/hello_world/ResponseRecyclerViewAdapter.kt b/examples/kotlin/shared/ResponseRecyclerViewAdapter.kt similarity index 87% rename from examples/kotlin/hello_world/ResponseRecyclerViewAdapter.kt rename to examples/kotlin/shared/ResponseRecyclerViewAdapter.kt index 56cd9b7d2c..8241d00e3a 100644 --- a/examples/kotlin/hello_world/ResponseRecyclerViewAdapter.kt +++ b/examples/kotlin/shared/ResponseRecyclerViewAdapter.kt @@ -1,4 +1,4 @@ -package io.envoyproxy.envoymobile.helloenvoykotlin +package io.envoyproxy.envoymobile.shared import android.support.v7.widget.RecyclerView import android.view.LayoutInflater @@ -6,6 +6,7 @@ import android.view.ViewGroup class ResponseRecyclerViewAdapter : RecyclerView.Adapter() { private val data = mutableListOf() + private var count = 1 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ResponseViewHolder { val context = parent.context @@ -15,7 +16,7 @@ class ResponseRecyclerViewAdapter : RecyclerView.Adapter() { } override fun onBindViewHolder(holder: ResponseViewHolder, position: Int) { - holder.setResult(data[position]) + holder.setResult(count++, data[position]) } override fun getItemCount(): Int { diff --git a/examples/kotlin/shared/ResponseViewHolder.kt b/examples/kotlin/shared/ResponseViewHolder.kt new file mode 100644 index 0000000000..e8f59839d7 --- /dev/null +++ b/examples/kotlin/shared/ResponseViewHolder.kt @@ -0,0 +1,25 @@ +package io.envoyproxy.envoymobile.shared + +import android.support.v7.widget.RecyclerView +import android.view.View +import android.widget.TextView + +class ResponseViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + private val countTextView: TextView = itemView.findViewById(R.id.response_text_view_count) as TextView + private val responseTextView: TextView = itemView.findViewById(R.id.response_text_view) as TextView + private val headerTextView: TextView = itemView.findViewById(R.id.header_text_view) as TextView + + fun setResult(count: Int, response: Response) { + countTextView.text = count.toString() + response.fold( + { success -> + responseTextView.text = responseTextView.resources.getString(R.string.title_string, success.title) + headerTextView.text = headerTextView.resources.getString(R.string.header_string, success.header) + }, + { failure -> + responseTextView.text = responseTextView.resources.getString(R.string.title_string, failure.message) + headerTextView.visibility = View.GONE + itemView.setBackgroundResource(R.color.failed_color) + }) + } +} diff --git a/examples/kotlin/hello_world/res/layout/item.xml b/examples/kotlin/shared/res/layout/item.xml similarity index 78% rename from examples/kotlin/hello_world/res/layout/item.xml rename to examples/kotlin/shared/res/layout/item.xml index 5746718d45..d554c2c348 100644 --- a/examples/kotlin/hello_world/res/layout/item.xml +++ b/examples/kotlin/shared/res/layout/item.xml @@ -6,6 +6,13 @@ android:padding="10dp" android:orientation="vertical"> + + + + #ff3651 + diff --git a/examples/java/hello_world/res/values/strings.xml b/examples/kotlin/shared/res/values/strings.xml similarity index 100% rename from examples/java/hello_world/res/values/strings.xml rename to examples/kotlin/shared/res/values/strings.xml