• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 The gRPC Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.grpc.strictmodehelloworldexample;
18 
19 import android.app.Activity;
20 import android.app.AlertDialog;
21 import android.content.Context;
22 import android.net.TrafficStats;
23 import android.os.AsyncTask;
24 import android.os.Bundle;
25 import android.os.StrictMode;
26 import android.os.StrictMode.OnVmViolationListener;
27 import android.os.StrictMode.VmPolicy;
28 import android.os.strictmode.Violation;
29 import android.support.v7.app.AppCompatActivity;
30 import android.text.TextUtils;
31 import android.text.method.ScrollingMovementMethod;
32 import android.view.View;
33 import android.view.inputmethod.InputMethodManager;
34 import android.widget.Button;
35 import android.widget.EditText;
36 import android.widget.TextView;
37 import com.google.common.util.concurrent.MoreExecutors;
38 import com.google.common.util.concurrent.ThreadFactoryBuilder;
39 import io.grpc.ManagedChannel;
40 import io.grpc.examples.helloworld.GreeterGrpc;
41 import io.grpc.examples.helloworld.HelloReply;
42 import io.grpc.examples.helloworld.HelloRequest;
43 import io.grpc.okhttp.OkHttpChannelBuilder;
44 import java.io.PrintWriter;
45 import java.io.StringWriter;
46 import java.lang.ref.WeakReference;
47 import java.util.concurrent.SynchronousQueue;
48 import java.util.concurrent.ThreadPoolExecutor;
49 import java.util.concurrent.TimeUnit;
50 
51 public class StrictModeHelloworldActivity extends AppCompatActivity {
52   private Button sendButton;
53   private EditText hostEdit;
54   private EditText portEdit;
55   private EditText messageEdit;
56   private TextView resultText;
57 
58   @Override
onCreate(Bundle savedInstanceState)59   protected void onCreate(Bundle savedInstanceState) {
60     super.onCreate(savedInstanceState);
61     VmPolicy policy =
62         new StrictMode.VmPolicy.Builder()
63             .detectCleartextNetwork()
64             .penaltyListener(
65                 MoreExecutors.directExecutor(),
66                 new OnVmViolationListener() {
67                   @Override
68                   public void onVmViolation(final Violation v) {
69                     runOnUiThread(
70                         new Runnable() {
71                           @Override
72                           public void run() {
73                             new AlertDialog.Builder(StrictModeHelloworldActivity.this)
74                                 .setTitle("StrictMode VM Violation")
75                                 .setMessage(v.getLocalizedMessage())
76                                 .show();
77                           }
78                         });
79                   }
80                 })
81             .penaltyLog()
82             .build();
83     StrictMode.setVmPolicy(policy);
84     setContentView(R.layout.activity_strictmodehelloworld);
85     sendButton = (Button) findViewById(R.id.send_button);
86     hostEdit = (EditText) findViewById(R.id.host_edit_text);
87     portEdit = (EditText) findViewById(R.id.port_edit_text);
88     messageEdit = (EditText) findViewById(R.id.message_edit_text);
89     resultText = (TextView) findViewById(R.id.grpc_response_text);
90     resultText.setMovementMethod(new ScrollingMovementMethod());
91   }
92 
sendMessage(View view)93   public void sendMessage(View view) {
94     ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE))
95         .hideSoftInputFromWindow(hostEdit.getWindowToken(), 0);
96     sendButton.setEnabled(false);
97     resultText.setText("");
98     new GrpcTask(this)
99         .execute(
100             hostEdit.getText().toString(),
101             messageEdit.getText().toString(),
102             portEdit.getText().toString());
103   }
104 
105   private static class GrpcTask extends AsyncTask<String, Void, String> {
106     private final WeakReference<Activity> activityReference;
107     private ManagedChannel channel;
108 
GrpcTask(Activity activity)109     private GrpcTask(Activity activity) {
110       this.activityReference = new WeakReference<Activity>(activity);
111     }
112 
113     @Override
doInBackground(String... params)114     protected String doInBackground(String... params) {
115       String host = params[0];
116       String message = params[1];
117       String portStr = params[2];
118       int port = TextUtils.isEmpty(portStr) ? 0 : Integer.valueOf(portStr);
119       try {
120         channel =
121             OkHttpChannelBuilder.forAddress(host, port)
122                 .transportExecutor(new NetworkTaggingExecutor(0xFDD))
123                 .usePlaintext()
124                 .build();
125         GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(channel);
126         HelloRequest request = HelloRequest.newBuilder().setName(message).build();
127         HelloReply reply = stub.sayHello(request);
128         return reply.getMessage();
129       } catch (Exception e) {
130         StringWriter sw = new StringWriter();
131         PrintWriter pw = new PrintWriter(sw);
132         e.printStackTrace(pw);
133         pw.flush();
134         return String.format("Failed... : %n%s", sw);
135       }
136     }
137 
138     @Override
onPostExecute(String result)139     protected void onPostExecute(String result) {
140       try {
141         channel.shutdown().awaitTermination(1, TimeUnit.SECONDS);
142       } catch (InterruptedException e) {
143         Thread.currentThread().interrupt();
144       }
145       Activity activity = activityReference.get();
146       if (activity == null) {
147         return;
148       }
149       TextView resultText = (TextView) activity.findViewById(R.id.grpc_response_text);
150       Button sendButton = (Button) activity.findViewById(R.id.send_button);
151       resultText.setText(result);
152       sendButton.setEnabled(true);
153     }
154   }
155 
156   private static class NetworkTaggingExecutor extends ThreadPoolExecutor {
157 
158     private int trafficStatsTag;
159 
NetworkTaggingExecutor(int tag)160     NetworkTaggingExecutor(int tag) {
161       super(
162           0,
163           Integer.MAX_VALUE,
164           60L,
165           TimeUnit.SECONDS,
166           new SynchronousQueue<Runnable>(),
167           new ThreadFactoryBuilder().setDaemon(true).setNameFormat("grpc-android-%d").build());
168       trafficStatsTag = tag;
169     }
170 
171     @Override
beforeExecute(Thread t, Runnable r)172     protected void beforeExecute(Thread t, Runnable r) {
173       TrafficStats.setThreadStatsTag(trafficStatsTag);
174       super.beforeExecute(t, r);
175     }
176 
177     @Override
afterExecute(Runnable r, Throwable t)178     protected void afterExecute(Runnable r, Throwable t) {
179       TrafficStats.clearThreadStatsTag();
180       super.afterExecute(r, t);
181     }
182   }
183 }
184