├── .gitignore ├── HttpClientLib-demo ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── naver │ │ └── httpclienttest │ │ ├── DefaultTimeout.java │ │ ├── DemoApplication.java │ │ ├── HttpClientConfigFragment.java │ │ ├── HttpMethod.java │ │ ├── HttpService.java │ │ ├── LogFragment.java │ │ ├── MainActivity.java │ │ ├── MainFragment.java │ │ └── data │ │ └── Post.java │ └── res │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ └── ic_launcher_background.xml │ ├── layout │ ├── activity_main.xml │ ├── fragment_httpclient_config.xml │ ├── fragment_log.xml │ └── fragment_main.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── HttpClientLib ├── .gitignore ├── build.gradle └── src │ ├── main │ └── java │ │ └── com │ │ └── naver │ │ └── httpclientlib │ │ ├── CallBack.java │ │ ├── CallTask.java │ │ ├── Converter.java │ │ ├── GsonConverter.java │ │ ├── GsonConverterFactory.java │ │ ├── HttpClient.java │ │ ├── HttpInvocationHandler.java │ │ ├── HttpMethod.java │ │ ├── Interceptor.java │ │ ├── InterceptorChain.java │ │ ├── ParamManager.java │ │ ├── RealCallTask.java │ │ ├── Request.java │ │ ├── RequestFactory.java │ │ ├── RequestMethod.java │ │ ├── Response.java │ │ ├── Utils.java │ │ └── annotation │ │ ├── Default.java │ │ ├── DynamicURL.java │ │ ├── Field.java │ │ ├── FieldMap.java │ │ ├── FormUrlEncoded.java │ │ ├── Header.java │ │ ├── HeaderMap.java │ │ ├── Headers.java │ │ ├── PathParam.java │ │ ├── Queries.java │ │ ├── Query.java │ │ ├── QueryMap.java │ │ ├── RequestBody.java │ │ ├── RequestMapping.java │ │ └── URL.java │ └── test │ └── java │ └── com │ └── naver │ └── httpclientlib │ ├── AsyncTest.java │ ├── HttpClientTest.java │ ├── InterceptorTest.java │ ├── InvalidServiceTest.java │ ├── ParamManagerTest.java │ ├── ResponseTest.java │ ├── ValidServiceTest.java │ ├── mock │ ├── Address.java │ ├── Comment.java │ ├── Company.java │ ├── Geo.java │ ├── Post.java │ ├── SkipPost.java │ └── User.java │ └── mockInterface │ ├── InvalidHttpService.java │ └── ValidHttpService.java ├── README.md ├── build.gradle ├── gradle.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/ 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | /app/ 10 | /HttpClientLib/local.properties 11 | /HttpClientLib/deploy.settings 12 | -------------------------------------------------------------------------------- /HttpClientLib-demo/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /HttpClientLib-demo/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | buildToolsVersion "29.0.0" 6 | defaultConfig { 7 | applicationId "com.naver.httpclienttest" 8 | minSdkVersion 16 9 | targetSdkVersion 28 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | compileOptions { 20 | sourceCompatibility JavaVersion.VERSION_1_7 21 | targetCompatibility JavaVersion.VERSION_1_7 22 | } 23 | } 24 | 25 | dependencies { 26 | implementation fileTree(dir: 'libs', include: ['*.jar']) 27 | implementation 'androidx.appcompat:appcompat:1.0.2' 28 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 29 | implementation project(":HttpClientLib") 30 | implementation 'com.naver.ers:ErrorReportingSdk:0.1.3' 31 | } 32 | -------------------------------------------------------------------------------- /HttpClientLib-demo/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /HttpClientLib-demo/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /HttpClientLib-demo/src/main/java/com/naver/httpclienttest/DefaultTimeout.java: -------------------------------------------------------------------------------- 1 | package com.naver.httpclienttest; 2 | 3 | class DefaultTimeout { 4 | private DefaultTimeout(){} 5 | 6 | static final long CALL_TIMEOUT = 0L; 7 | static final long CONNECT_TIMEOUT = 10000L; 8 | static final long READ_TIMEOUT = 10000L; 9 | static final long WRITE_TIMEOUT = 10000L; 10 | } 11 | -------------------------------------------------------------------------------- /HttpClientLib-demo/src/main/java/com/naver/httpclienttest/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.naver.httpclienttest; 2 | 3 | import android.app.Application; 4 | 5 | import com.naver.ers.CustomData; 6 | import com.naver.ers.Reporter; 7 | 8 | import java.util.Date; 9 | 10 | public class DemoApplication extends Application { 11 | @Override 12 | public void onCreate() { 13 | super.onCreate(); 14 | 15 | CustomData.Builder customDataBuilder = new CustomData.Builder() 16 | .putData("App Start time", new Date().toString()); 17 | Reporter.setCustomData(customDataBuilder.build()); 18 | Reporter.register(this); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /HttpClientLib-demo/src/main/java/com/naver/httpclienttest/HttpClientConfigFragment.java: -------------------------------------------------------------------------------- 1 | package com.naver.httpclienttest; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | import android.os.Bundle; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.Button; 10 | import android.widget.EditText; 11 | 12 | import androidx.annotation.NonNull; 13 | import androidx.annotation.Nullable; 14 | import androidx.fragment.app.Fragment; 15 | import androidx.fragment.app.FragmentManager; 16 | import androidx.fragment.app.FragmentTransaction; 17 | 18 | import com.naver.httpclientsdk.R; 19 | 20 | import static com.naver.httpclienttest.DefaultTimeout.*; 21 | 22 | public class HttpClientConfigFragment extends Fragment { 23 | 24 | private EditText baseUrlText; 25 | private EditText callTimeoutText; 26 | private EditText connectTimeoutText; 27 | private EditText readTimeoutText; 28 | private EditText writeTimeoutText; 29 | private SharedPreferences sharedPreferences; 30 | 31 | @Override 32 | public void onCreate(@Nullable Bundle savedInstanceState) { 33 | super.onCreate(savedInstanceState); 34 | 35 | sharedPreferences = getContext().getSharedPreferences( 36 | getContext().getResources().getString(R.string.config_file), 37 | Context.MODE_PRIVATE 38 | ); 39 | } 40 | 41 | @Nullable 42 | @Override 43 | public View onCreateView(@NonNull LayoutInflater inflater, 44 | @Nullable ViewGroup container, 45 | @Nullable Bundle savedInstanceState) { 46 | View view = inflater.inflate(R.layout.fragment_httpclient_config, container, false); 47 | 48 | baseUrlText = view.findViewById(R.id.base_url); 49 | baseUrlText.setText(sharedPreferences.getString( 50 | getContext().getResources().getString(R.string.base_url), 51 | getContext().getResources().getString(R.string.default_URL))); 52 | 53 | callTimeoutText = view.findViewById(R.id.call_time); 54 | callTimeoutText.setText(String.valueOf( 55 | sharedPreferences.getLong( 56 | getContext().getResources().getString(R.string.call_timeout), 57 | CALL_TIMEOUT))); 58 | 59 | connectTimeoutText = view.findViewById(R.id.connect_time); 60 | connectTimeoutText.setText(String.valueOf( 61 | sharedPreferences.getLong( 62 | getContext().getResources().getString(R.string.connect_timeout), 63 | CONNECT_TIMEOUT))); 64 | 65 | readTimeoutText = view.findViewById(R.id.read_time); 66 | readTimeoutText.setText(String.valueOf( 67 | sharedPreferences.getLong( 68 | getContext().getResources().getString(R.string.read_timeout), 69 | READ_TIMEOUT))); 70 | 71 | writeTimeoutText = view.findViewById(R.id.write_time); 72 | writeTimeoutText.setText(String.valueOf( 73 | sharedPreferences.getLong( 74 | getContext().getResources().getString(R.string.write_timeout), 75 | WRITE_TIMEOUT))); 76 | 77 | Button saveBtn = view.findViewById(R.id.save_btn); 78 | saveBtn.setOnClickListener(new Button.OnClickListener(){ 79 | @Override 80 | public void onClick(View v) { 81 | SharedPreferences.Editor editor = sharedPreferences.edit(); 82 | 83 | CharSequence baseUrlSeq = baseUrlText.getText(); 84 | if(baseUrlSeq != null) { 85 | editor.putString( 86 | getContext().getResources().getString(R.string.base_url), 87 | baseUrlSeq.toString()); 88 | } 89 | 90 | CharSequence callSeq = callTimeoutText.getText(); 91 | if(callSeq.length() > 0) { 92 | editor.putLong( 93 | getContext().getResources().getString(R.string.call_timeout), 94 | Long.valueOf(callSeq.toString())); 95 | } 96 | 97 | CharSequence connectSeq = connectTimeoutText.getText(); 98 | if(connectSeq.length() > 0) { 99 | editor.putLong( 100 | getContext().getResources().getString(R.string.connect_timeout), 101 | Long.valueOf(connectSeq.toString())); } 102 | 103 | CharSequence readSeq = readTimeoutText.getText(); 104 | if(readSeq.length() > 0) { 105 | editor.putLong( 106 | getContext().getResources().getString(R.string.read_timeout), 107 | Long.valueOf(readSeq.toString())); 108 | } 109 | 110 | CharSequence writeSeq = writeTimeoutText.getText(); 111 | if(writeSeq.length() > 0) { 112 | editor.putLong( 113 | getContext().getResources().getString(R.string.write_timeout), 114 | Long.valueOf(writeSeq.toString())); 115 | } 116 | 117 | editor.apply(); 118 | 119 | replaceFragment(new MainFragment()); 120 | } 121 | }); 122 | 123 | Button crashBtn = view.findViewById(R.id.crash_btn); 124 | crashBtn.setOnClickListener(new Button.OnClickListener() { 125 | @Override 126 | public void onClick(View v) { 127 | throw new AssertionError("Crash!"); 128 | } 129 | }); 130 | return view; 131 | } 132 | 133 | private void replaceFragment(Fragment newFragment) { 134 | FragmentManager fragmentManager = getFragmentManager(); 135 | FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 136 | 137 | fragmentTransaction.replace(R.id.fragment_container, newFragment); 138 | fragmentTransaction.commit(); 139 | } 140 | 141 | } 142 | -------------------------------------------------------------------------------- /HttpClientLib-demo/src/main/java/com/naver/httpclienttest/HttpMethod.java: -------------------------------------------------------------------------------- 1 | package com.naver.httpclienttest; 2 | 3 | enum HttpMethod { 4 | GET("GET"), 5 | POST("POST"), 6 | PUT("PUT"), 7 | DELETE("DELETE"), 8 | HEAD("HEAD"); 9 | 10 | String name; 11 | 12 | HttpMethod(String method) { 13 | name = method; 14 | } 15 | 16 | String getName() { 17 | return name; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /HttpClientLib-demo/src/main/java/com/naver/httpclienttest/HttpService.java: -------------------------------------------------------------------------------- 1 | package com.naver.httpclienttest; 2 | 3 | import com.naver.httpclientlib.CallTask; 4 | import com.naver.httpclientlib.RequestMethod; 5 | import com.naver.httpclientlib.annotation.DynamicURL; 6 | import com.naver.httpclientlib.annotation.HeaderMap; 7 | import com.naver.httpclientlib.annotation.PathParam; 8 | import com.naver.httpclientlib.annotation.QueryMap; 9 | import com.naver.httpclientlib.annotation.RequestBody; 10 | import com.naver.httpclientlib.annotation.RequestMapping; 11 | import com.naver.httpclientlib.annotation.URL; 12 | import com.naver.httpclienttest.data.Post; 13 | 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | public interface HttpService { 18 | @RequestMapping(value="/posts", method= RequestMethod.GET) 19 | CallTask> getPostsByQuery(@HeaderMap Map headerMap, @QueryMap Map queryMap); 20 | 21 | @RequestMapping(value="/posts/{id}", method= RequestMethod.GET) 22 | CallTask getPostsByPathParam(@HeaderMap Map headerMap, @PathParam("id") Integer id); 23 | 24 | @RequestMapping(value="/posts", method= RequestMethod.POST) 25 | CallTask postPosts(@HeaderMap Map headerMap, @RequestBody Post post); 26 | 27 | @RequestMapping(value="/posts/{id}", method= RequestMethod.PUT) 28 | CallTask putPostsById(@HeaderMap Map headerMap, @PathParam("id") Integer id, @RequestBody Post newPost); 29 | 30 | @RequestMapping(value="/posts/{id}", method= RequestMethod.DELETE) 31 | CallTask deletePostById(@HeaderMap Map headerMap, @PathParam("id") Integer id); 32 | 33 | @RequestMapping(value="/posts", method= RequestMethod.HEAD) 34 | CallTask getPostsForHeadMethod(@HeaderMap Map headerMap); 35 | 36 | @DynamicURL(method= RequestMethod.GET) 37 | CallTask> getPostsByDynamicURLWithQuery(@HeaderMap Map headerMap, @URL String url, @QueryMap Map queryMap); 38 | 39 | @DynamicURL(method= RequestMethod.POST) 40 | CallTask postPostsByDynamicURL(@HeaderMap Map headerMap, @URL String url, @RequestBody Post post); 41 | 42 | @DynamicURL(method= RequestMethod.PUT) 43 | CallTask putPostsByDynamicURL(@HeaderMap Map headerMap, @URL String url, @RequestBody Post newPost); 44 | 45 | @DynamicURL(method= RequestMethod.DELETE) 46 | CallTask deletePostByDynamicURL(@HeaderMap Map headerMap, @URL String url); 47 | 48 | @DynamicURL(method= RequestMethod.HEAD) 49 | CallTask getPostsForHeadMethodByDynamicURL(@HeaderMap Map headerMap, @URL String url); 50 | 51 | } 52 | -------------------------------------------------------------------------------- /HttpClientLib-demo/src/main/java/com/naver/httpclienttest/LogFragment.java: -------------------------------------------------------------------------------- 1 | package com.naver.httpclienttest; 2 | 3 | import android.os.Bundle; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.Button; 8 | import android.widget.EditText; 9 | 10 | import androidx.annotation.NonNull; 11 | import androidx.annotation.Nullable; 12 | import androidx.fragment.app.Fragment; 13 | import androidx.fragment.app.FragmentManager; 14 | import androidx.fragment.app.FragmentTransaction; 15 | 16 | import com.naver.httpclientlib.Request; 17 | import com.naver.httpclientlib.Response; 18 | import com.naver.httpclientsdk.R; 19 | 20 | public class LogFragment extends Fragment { 21 | private Response response; 22 | private String errorMessage; 23 | 24 | private EditText requestLog; 25 | private EditText responseLog; 26 | 27 | private boolean isAsync; 28 | 29 | LogFragment(Response response, boolean isAsync) { 30 | this.response = response; 31 | this.isAsync = isAsync; 32 | } 33 | 34 | LogFragment(String errorMessage, boolean isAsync) { 35 | this.errorMessage = errorMessage; 36 | this.isAsync = isAsync; 37 | } 38 | 39 | @Nullable 40 | @Override 41 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 42 | View view = inflater.inflate(R.layout.fragment_log, container, false); 43 | 44 | Button backBtn = view.findViewById(R.id.back_btn); 45 | backBtn.setOnClickListener(new Button.OnClickListener(){ 46 | @Override 47 | public void onClick(View v) { 48 | replaceFragment(new MainFragment()); 49 | } 50 | }); 51 | 52 | requestLog = view.findViewById(R.id.request_log); 53 | loggingRequest(); 54 | 55 | responseLog = view.findViewById(R.id.response_log); 56 | loggingResponse(); 57 | 58 | return view; 59 | } 60 | 61 | private void loggingRequest() { 62 | requestLog.append("Call : " + (!isAsync ? "Synchronous Call\n" : "Asynchronous Call\n")); 63 | if(response != null) { 64 | Request request = response.request(); 65 | requestLog.append("URL : " + request.getUrl() + "\n"); 66 | requestLog.append("Method : " + request.getMethod() + "\n"); 67 | requestLog.append("Headers : " + request.getHeaders() + "\n"); 68 | if(request.getContentType() != null) { 69 | requestLog.append("Content-type : " + request.getContentType() + "\n"); 70 | } 71 | requestLog.setSelection(0); 72 | } 73 | } 74 | 75 | private void loggingResponse() { 76 | if(response != null) { 77 | responseLog.append("code : " + response.code() + "\n"); 78 | responseLog.append("date : " + response.header("Date") + "\n"); 79 | responseLog.append("content-type : " + response.header("Content-Type") + "\n"); 80 | if(response.body() != null) { 81 | responseLog.append("body : " + response.body().toString()); 82 | } 83 | responseLog.setSelection(0); 84 | } else { 85 | responseLog.append("Failed to Response : " + errorMessage); 86 | } 87 | } 88 | 89 | private void replaceFragment(Fragment newFragment) { 90 | FragmentManager fragmentManager = getFragmentManager(); 91 | FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 92 | 93 | fragmentTransaction.replace(R.id.fragment_container, newFragment); 94 | fragmentTransaction.commit(); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /HttpClientLib-demo/src/main/java/com/naver/httpclienttest/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.naver.httpclienttest; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | import androidx.fragment.app.FragmentManager; 5 | import androidx.fragment.app.FragmentTransaction; 6 | 7 | import android.os.Bundle; 8 | 9 | import com.naver.httpclientsdk.R; 10 | 11 | public class MainActivity extends AppCompatActivity { 12 | 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | setContentView(R.layout.activity_main); 17 | 18 | FragmentManager fragmentManager = getSupportFragmentManager(); 19 | FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 20 | 21 | MainFragment mainFragment = new MainFragment(); 22 | fragmentTransaction.add(R.id.fragment_container, mainFragment); 23 | fragmentTransaction.commit(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /HttpClientLib-demo/src/main/java/com/naver/httpclienttest/MainFragment.java: -------------------------------------------------------------------------------- 1 | package com.naver.httpclienttest; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | import android.os.Bundle; 6 | import android.util.Log; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.AdapterView; 11 | import android.widget.ArrayAdapter; 12 | import android.widget.Button; 13 | import android.widget.EditText; 14 | import android.widget.LinearLayout; 15 | import android.widget.RadioButton; 16 | import android.widget.RadioGroup; 17 | import android.widget.Spinner; 18 | 19 | import androidx.annotation.NonNull; 20 | import androidx.annotation.Nullable; 21 | import androidx.fragment.app.Fragment; 22 | import androidx.fragment.app.FragmentManager; 23 | import androidx.fragment.app.FragmentTransaction; 24 | 25 | import com.naver.httpclientlib.CallBack; 26 | import com.naver.httpclientlib.CallTask; 27 | import com.naver.httpclientlib.HttpClient; 28 | import com.naver.httpclientlib.Response; 29 | import com.naver.httpclientsdk.R; 30 | import com.naver.httpclienttest.data.Post; 31 | 32 | import java.io.IOException; 33 | import java.util.HashMap; 34 | import java.util.Map; 35 | import java.util.concurrent.TimeUnit; 36 | 37 | import static com.naver.httpclienttest.DefaultTimeout.*; 38 | 39 | public class MainFragment extends Fragment { 40 | private static final String LOG_TAG = MainFragment.class.getSimpleName(); 41 | 42 | private LinearLayout pathParamLayout; 43 | private LinearLayout queryLayout; 44 | private LinearLayout requestBodyLayout; 45 | 46 | private Spinner httpMethodSpinner; 47 | private EditText headerNameText1; 48 | private EditText headerNameText2; 49 | private EditText headerValueText1; 50 | private EditText headerValueText2; 51 | private EditText pathparamText; 52 | private EditText queryNameText1; 53 | private EditText queryNameText2; 54 | private EditText queryValueText1; 55 | private EditText queryValueText2; 56 | private EditText userIdText; 57 | private EditText idText; 58 | private EditText titleText; 59 | private EditText bodyText; 60 | private EditText dynamicUrlText; 61 | private RadioGroup syncAsyncGroup; 62 | private RadioButton syncBtn; 63 | private RadioButton asyncBtn; 64 | private Button dynamicCallBtn; 65 | 66 | private HttpService httpService; 67 | 68 | @Override 69 | public void onCreate(@Nullable Bundle savedInstanceState) { 70 | super.onCreate(savedInstanceState); 71 | SharedPreferences sharedPreferences = getContext().getSharedPreferences( 72 | getContext().getResources().getString(R.string.config_file), 73 | Context.MODE_PRIVATE); 74 | 75 | String baseUrl = sharedPreferences.getString( 76 | getContext().getResources().getString(R.string.base_url), 77 | getContext().getResources().getString(R.string.default_URL)); 78 | long callTimeout = sharedPreferences.getLong( 79 | getContext().getResources().getString(R.string.call_timeout), 80 | CALL_TIMEOUT); 81 | long connectTimeout = sharedPreferences.getLong( 82 | getContext().getResources().getString(R.string.connect_timeout), 83 | CONNECT_TIMEOUT); 84 | long readTimeout = sharedPreferences.getLong( 85 | getContext().getResources().getString(R.string.read_timeout), 86 | READ_TIMEOUT); 87 | long writeTimeout = sharedPreferences.getLong( 88 | getContext().getResources().getString(R.string.write_timeout), 89 | WRITE_TIMEOUT); 90 | 91 | HttpClient httpClient = new HttpClient.Builder() 92 | .baseUrl(baseUrl) 93 | .callTimeout(callTimeout, TimeUnit.MILLISECONDS) 94 | .connectTimeout(connectTimeout, TimeUnit.MILLISECONDS) 95 | .readTimeout(readTimeout, TimeUnit.MILLISECONDS) 96 | .writeTimeout(writeTimeout, TimeUnit.MILLISECONDS) 97 | .build(); 98 | 99 | httpService = httpClient.create(HttpService.class); 100 | } 101 | 102 | @Nullable 103 | @Override 104 | public View onCreateView(@NonNull LayoutInflater inflater, 105 | @Nullable ViewGroup container, 106 | @Nullable Bundle savedInstanceState) { 107 | View view = inflater.inflate(R.layout.fragment_main, container, false); 108 | 109 | pathParamLayout = view.findViewById(R.id.path_param_layout); 110 | queryLayout = view.findViewById(R.id.query_layout); 111 | requestBodyLayout = view.findViewById(R.id.request_body_layout); 112 | 113 | Button baseUrlBtn = view.findViewById(R.id.base_url_btn); 114 | baseUrlBtn.setOnClickListener(new Button.OnClickListener() { 115 | @Override 116 | public void onClick(View v) { 117 | replaceFragment(new HttpClientConfigFragment()); 118 | } 119 | }); 120 | 121 | headerNameText1 = view.findViewById(R.id.header_name1); 122 | headerValueText1 = view.findViewById(R.id.header_value1); 123 | headerNameText2 = view.findViewById(R.id.header_name2); 124 | headerValueText2 = view.findViewById(R.id.header_value2); 125 | 126 | httpMethodSpinner = view.findViewById(R.id.http_method_spinner); 127 | httpMethodSpinner.setAdapter(makeAdapter(R.array.http_method_list)); 128 | httpMethodSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 129 | @Override 130 | public void onItemSelected(AdapterView parent, View view, int position, long id) { 131 | HttpMethod method = HttpMethod.valueOf(httpMethodSpinner.getItemAtPosition(position).toString()); 132 | switch (method) { 133 | case GET: 134 | case HEAD: 135 | pathParamLayout.setVisibility(View.VISIBLE); 136 | queryLayout.setVisibility(View.VISIBLE); 137 | requestBodyLayout.setVisibility(View.GONE); 138 | break; 139 | case POST: 140 | pathParamLayout.setVisibility(View.GONE); 141 | queryLayout.setVisibility(View.GONE); 142 | requestBodyLayout.setVisibility(View.VISIBLE); 143 | break; 144 | case PUT: 145 | pathParamLayout.setVisibility(View.VISIBLE); 146 | queryLayout.setVisibility(View.GONE); 147 | requestBodyLayout.setVisibility(View.VISIBLE); 148 | break; 149 | case DELETE: 150 | pathParamLayout.setVisibility(View.VISIBLE); 151 | queryLayout.setVisibility(View.GONE); 152 | requestBodyLayout.setVisibility(View.GONE); 153 | break; 154 | } 155 | } 156 | 157 | @Override 158 | public void onNothingSelected(AdapterView parent) { 159 | Log.e(LOG_TAG, "Nothing Selected on Method Spinner."); 160 | } 161 | }); 162 | 163 | pathparamText = view.findViewById(R.id.path_param_text); 164 | 165 | queryNameText1 = view.findViewById(R.id.query_name1); 166 | queryValueText1 = view.findViewById(R.id.query_value1); 167 | 168 | queryNameText2 = view.findViewById(R.id.query_name2); 169 | queryValueText2 = view.findViewById(R.id.query_value2); 170 | 171 | userIdText = view.findViewById(R.id.user_id_text); 172 | idText = view.findViewById(R.id.id_text); 173 | titleText = view.findViewById(R.id.title_text); 174 | bodyText = view.findViewById(R.id.body_text); 175 | 176 | dynamicUrlText = view.findViewById(R.id.dynamic_url); 177 | 178 | syncAsyncGroup = view.findViewById(R.id.sync_async_group); 179 | syncBtn = view.findViewById(R.id.sync_btn); 180 | asyncBtn = view.findViewById(R.id.async_btn); 181 | syncBtn.toggle(); 182 | 183 | Button callBtn = view.findViewById(R.id.call_btn); 184 | callBtn.setOnClickListener(callBtnListener); 185 | dynamicCallBtn = view.findViewById(R.id.dynamic_call_btn); 186 | dynamicCallBtn.setOnClickListener(callBtnListener); 187 | 188 | return view; 189 | } 190 | 191 | /** 192 | * Spinner Adapter 193 | */ 194 | private ArrayAdapter makeAdapter(int items) { 195 | ArrayAdapter adapter = ArrayAdapter.createFromResource( 196 | getContext(), 197 | items, 198 | android.R.layout.simple_spinner_item); 199 | adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 200 | 201 | return adapter; 202 | } 203 | 204 | /** 205 | * ClickListener for Call/DynamicCall Button 206 | */ 207 | private final Button.OnClickListener callBtnListener = new View.OnClickListener() { 208 | @Override 209 | public void onClick(View v) { 210 | boolean isDynamicUrl = (v.getId() == dynamicCallBtn.getId()); 211 | String dynamicUrl = dynamicUrlText.getText().toString(); 212 | String pathParam; 213 | 214 | Map headerMap = new HashMap<>(); 215 | String headerName1 = headerNameText1.getText().toString(); 216 | String headerValue1 = headerValueText1.getText().toString(); 217 | String headerName2 = headerNameText2.getText().toString(); 218 | String headerValue2 = headerValueText2.getText().toString(); 219 | 220 | if (!headerName1.isEmpty() && !headerValue1.isEmpty()) { 221 | headerMap.put(headerName1, headerValue1); 222 | } 223 | if (!headerName2.isEmpty() && !headerValue2.isEmpty()) { 224 | headerMap.put(headerName2, headerValue2); 225 | } 226 | 227 | HttpMethod method = HttpMethod.valueOf(String.valueOf(httpMethodSpinner.getSelectedItem())); 228 | try { 229 | switch (method) { 230 | case GET: 231 | pathParam = pathparamText.getText().toString(); 232 | if (!isDynamicUrl && !pathParam.isEmpty()) { 233 | executeCallTask(httpService.getPostsByPathParam(headerMap, Integer.parseInt(pathParam))); 234 | } else { 235 | Map queryMap = new HashMap<>(); 236 | String queryName1 = queryNameText1.getText().toString(); 237 | String queryValue1 = queryValueText1.getText().toString(); 238 | String queryName2 = queryNameText2.getText().toString(); 239 | String queryValue2 = queryValueText2.getText().toString(); 240 | 241 | if (!queryName1.isEmpty() && !queryValue1.isEmpty()) { 242 | queryMap.put(queryName1, queryValue1); 243 | } 244 | if (!queryName2.isEmpty() && !queryValue2.isEmpty()) { 245 | queryMap.put(queryName2, queryValue2); 246 | } 247 | 248 | if (isDynamicUrl) { 249 | executeCallTask(httpService.getPostsByDynamicURLWithQuery(headerMap, dynamicUrl, queryMap)); 250 | } else { 251 | executeCallTask(httpService.getPostsByQuery(headerMap, queryMap)); 252 | } 253 | } 254 | break; 255 | case POST: 256 | if (isDynamicUrl) { 257 | executeCallTask(httpService.postPostsByDynamicURL(headerMap, dynamicUrl, parseRequestBody())); 258 | } else { 259 | executeCallTask(httpService.postPosts(headerMap, parseRequestBody())); 260 | } 261 | break; 262 | case PUT: 263 | pathParam = pathparamText.getText().toString(); 264 | if (!isDynamicUrl && !pathParam.isEmpty()) { 265 | executeCallTask(httpService.putPostsById(headerMap, Integer.parseInt(pathParam), parseRequestBody())); 266 | } else if (isDynamicUrl) { 267 | executeCallTask(httpService.putPostsByDynamicURL(headerMap, dynamicUrl, parseRequestBody())); 268 | } else { 269 | replaceFragment(new LogFragment("You should use PathParam with PUT Method.", false)); 270 | } 271 | break; 272 | case DELETE: 273 | pathParam = pathparamText.getText().toString(); 274 | if (!isDynamicUrl && !pathParam.isEmpty()) { 275 | executeCallTask(httpService.deletePostById(headerMap, Integer.parseInt(pathParam))); 276 | } else if (isDynamicUrl) { 277 | executeCallTask(httpService.deletePostByDynamicURL(headerMap, dynamicUrl)); 278 | } else { 279 | replaceFragment(new LogFragment("You should use PathParam with DELETE Method.", false)); 280 | } 281 | break; 282 | case HEAD: 283 | if (isDynamicUrl) { 284 | executeCallTask(httpService.getPostsForHeadMethodByDynamicURL(headerMap, dynamicUrl)); 285 | } else { 286 | executeCallTask(httpService.getPostsForHeadMethod(headerMap)); 287 | } 288 | break; 289 | } 290 | } catch(Exception e) { // defensive code for unchecked Exception in SDK. 291 | replaceFragment(new LogFragment(e.getMessage(), false)); 292 | } 293 | } 294 | 295 | /** 296 | * execute callTask synchronously or asynchronously. 297 | * and then, start LogFragment with Response received for result 298 | */ 299 | private void executeCallTask(final CallTask callTask) { 300 | if (syncAsyncGroup.getCheckedRadioButtonId() == syncBtn.getId()) { 301 | new Thread(new Runnable() { 302 | @Override 303 | public void run() { 304 | try { 305 | Response response = callTask.execute(); 306 | 307 | replaceFragment(new LogFragment(response, false)); 308 | } catch (IOException e) { 309 | replaceFragment(new LogFragment(e.getMessage(), false)); 310 | } 311 | } 312 | }).start(); 313 | } else if (syncAsyncGroup.getCheckedRadioButtonId() == asyncBtn.getId()) { 314 | callTask.enqueue(new CallBack() { 315 | @Override 316 | public void onResponse(Response response) throws IOException { 317 | LogFragment logFragment = response.isSuccessful() ? 318 | new LogFragment(response, true) 319 | : new LogFragment("Response Fail", true); 320 | replaceFragment(logFragment); 321 | } 322 | 323 | @Override 324 | public void onFailure(IOException e) { 325 | replaceFragment(new LogFragment(e.getMessage(), true)); 326 | } 327 | }); 328 | } 329 | } 330 | 331 | private Post parseRequestBody() { 332 | CharSequence userIdSeq = userIdText.getText(); 333 | int userId = userIdSeq.length() > 0 ? Integer.parseInt(userIdSeq.toString()) : 0; 334 | CharSequence idSeq = idText.getText(); 335 | int id = idSeq.length() > 0 ? Integer.parseInt(idSeq.toString()) : 0; 336 | String title = titleText.getText().toString(); 337 | String body = bodyText.getText().toString(); 338 | 339 | return new Post(userId, id, title, body); 340 | } 341 | }; 342 | 343 | private void replaceFragment(Fragment newFragment) { 344 | FragmentManager fragmentManager = getFragmentManager(); 345 | FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 346 | 347 | fragmentTransaction.replace(R.id.fragment_container, newFragment); 348 | fragmentTransaction.commit(); 349 | } 350 | } 351 | -------------------------------------------------------------------------------- /HttpClientLib-demo/src/main/java/com/naver/httpclienttest/data/Post.java: -------------------------------------------------------------------------------- 1 | package com.naver.httpclienttest.data; 2 | 3 | public class Post { 4 | int userId; 5 | int id; 6 | String title; 7 | String body; 8 | 9 | public Post(int userId, int id, String title, String body) { 10 | this.userId = userId; 11 | this.id = id; 12 | this.title = title; 13 | this.body = body; 14 | } 15 | 16 | public int getUserId() { 17 | return userId; 18 | } 19 | 20 | public void setUserId(int userId) { 21 | this.userId = userId; 22 | } 23 | 24 | public int getId() { 25 | return id; 26 | } 27 | 28 | public void setId(int id) { 29 | this.id = id; 30 | } 31 | 32 | public String getTitle() { 33 | return title; 34 | } 35 | 36 | public void setTitle(String title) { 37 | this.title = title; 38 | } 39 | 40 | public String getBody() { 41 | return body; 42 | } 43 | 44 | public void setBody(String body) { 45 | this.body = body; 46 | } 47 | 48 | @Override 49 | public String toString() { 50 | return "Post{" + 51 | "userId=" + userId + 52 | ", id=" + id + 53 | ", title='" + title + '\'' + 54 | ", body='" + body + '\'' + 55 | '}'; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /HttpClientLib-demo/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /HttpClientLib-demo/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /HttpClientLib-demo/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 18 | 19 | -------------------------------------------------------------------------------- /HttpClientLib-demo/src/main/res/layout/fragment_httpclient_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 16 | 17 | 20 | 21 | 28 | 29 |