├── LICENSE.txt ├── README.md ├── app ├── .gitignore ├── build.gradle ├── libs │ └── __copy_sdk_aar_here__.txt ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── jp │ │ └── line │ │ └── android │ │ └── sdk │ │ └── sample │ │ ├── Constants.java │ │ ├── MainActivity.java │ │ └── PostLoginActivity.java │ └── res │ ├── drawable-hdpi │ ├── btn_login_base.9.png │ ├── btn_login_press.9.png │ └── button_press.xml │ ├── drawable-mdpi │ ├── btn_login_base.9.png │ ├── btn_login_press.9.png │ └── button_press.xml │ ├── drawable-tvdpi │ ├── btn_login_base.9.png │ ├── btn_login_press.9.png │ └── button_press.xml │ ├── drawable-xhdpi │ ├── btn_login_base.9.png │ ├── btn_login_press.9.png │ └── button_press.xml │ ├── drawable-xxhdpi │ ├── btn_login_base.9.png │ ├── btn_login_press.9.png │ └── button_press.xml │ ├── layout │ ├── activity_main.xml │ ├── activity_post_login.xml │ └── profile_dialog.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── app_screenshot.png ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2018 LINE Corporation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # line-android-v2-starter 2 | LINE Android SDK V2 starter 3 | 4 | # Introduction 5 | 6 | This is a sample application for LINE Android SDK V2. It demonstrates the following functionality: 7 | 8 | * App-to-app Login 9 | * Web Login 10 | * GetProfile API 11 | * Verify Token API 12 | * Refresh Token API 13 | * Logout API 14 | 15 | # Before Starting 16 | 17 | * You must have [Android Studio](https://developer.android.com/studio/index.html) installed. 18 | * You must create a LINE Login account on the [LINE Business Center](https://business.line.me) that has the application type set to `NATIVE_APP`. You will need the account's Channel ID to set up the SDK. 19 | 20 | # Setup 21 | 22 | 1. Download the SDK aar file (`line-sdk-x.x.x`) from the LINE Developer Console and put it into the `app/libs` folder. 23 | 2. Set the CHANNEL_ID constant in Constants.java to your Channel ID and then open the project in Android Studio and build it as you would with any normal Android application. 24 | 25 | # How to Use 26 | 27 | 28 | 29 | The **Login with LINE** button will use the LINE App to log in and the **Browser Login** button will open a Web Login screen inside of a Chrome custom tab. 30 | 31 | After logging in, the user's profile information and access token will be displayed on the screen in addition four buttons: 32 | 33 | * **GET PROFILE** - Pushing this button will call the LINE SDK's `getProfile()` method. The profile information retrieved from the API will appear in a Popup Dialog. 34 | This information should be the same as the profile information that is initially displayed to the user after they log into this starter application. 35 | * **VERIFY TOKEN** - Pushing this button will call the LINE SDK's `verifyToken()` method. A will appear informing the user if their token is valid or not. 36 | * **REFRESH TOKEN** - Pushing this button will call the LINE SDK's `refreshAccessToken()` method. This will update the access token that is displayed on the starter app's main screen. 37 | * **LOGOUT** - Pushing this button will call the LINE SDK's `logout()` method. This will revoke the access token and return the user to the "Select Login" page. 38 | 39 | # Documentation 40 | 41 | For detailed documentation, please refer to these links: 42 | 43 | * [LINE Developer Center's Android SDK Documentation](https://developers.line.me/android/overview) 44 | * [LINE SDK for Android API Reference](https://devdocs.line.me/en/#line-sdk-for-android-api-reference) 45 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.2" 6 | defaultConfig { 7 | applicationId "jp.line.android.sdk.sample" 8 | minSdkVersion 15 9 | targetSdkVersion 23 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 25 | exclude group: 'com.android.support', module: 'support-annotations' 26 | }) 27 | compile "com.android.support:appcompat-v7:25.4.0" 28 | compile "com.android.support:customtabs:25.4.0" 29 | compile(name:'line-sdk-4.0.6', ext:'aar') 30 | testCompile 'junit:junit:4.12' 31 | compile 'com.android.support.constraint:constraint-layout:1.0.0-beta4' 32 | } 33 | -------------------------------------------------------------------------------- /app/libs/__copy_sdk_aar_here__.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/line/line-sdk-starter-android-v2/b4eda32fd9488150e6c152228fb9cff383f0b63c/app/libs/__copy_sdk_aar_here__.txt -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/JP11686/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 13 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/java/jp/line/android/sdk/sample/Constants.java: -------------------------------------------------------------------------------- 1 | package jp.line.android.sdk.sample; 2 | 3 | public class Constants { 4 | 5 | // Set this value to your Channel ID 6 | public static final String CHANNEL_ID = ""; 7 | } -------------------------------------------------------------------------------- /app/src/main/java/jp/line/android/sdk/sample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package jp.line.android.sdk.sample; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.util.Log; 7 | import android.view.View; 8 | import android.widget.TextView; 9 | 10 | import com.linecorp.linesdk.auth.LineLoginApi; 11 | import com.linecorp.linesdk.auth.LineLoginResult; 12 | 13 | public class MainActivity extends AppCompatActivity { 14 | 15 | private static final int REQUEST_CODE = 1; 16 | 17 | @Override 18 | protected void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.activity_main); 21 | 22 | final TextView a2aButton = (TextView) findViewById(R.id.login_button); 23 | a2aButton.setOnClickListener(new View.OnClickListener() { 24 | 25 | public void onClick(View v) { 26 | 27 | try { 28 | // App to App Login 29 | Intent LoginIntent = LineLoginApi.getLoginIntent(v.getContext(), Constants.CHANNEL_ID); 30 | startActivityForResult(LoginIntent, REQUEST_CODE); 31 | 32 | } catch (Exception e) { 33 | Log.e("ERROR", e.toString()); 34 | } 35 | } 36 | }); 37 | 38 | final TextView browserLoginButton = (TextView) findViewById(R.id.browser_login_button); 39 | browserLoginButton.setOnClickListener(new View.OnClickListener() { 40 | 41 | public void onClick(View v) { 42 | 43 | try { 44 | // Browser Login 45 | Intent LoginIntent = LineLoginApi.getLoginIntentWithoutLineAppAuth(v.getContext(), Constants.CHANNEL_ID); 46 | startActivityForResult(LoginIntent, REQUEST_CODE); 47 | 48 | } catch (Exception e) { 49 | Log.e("ERROR", e.toString()); 50 | } 51 | } 52 | 53 | }); 54 | } 55 | 56 | 57 | public void onActivityResult(int requestCode, int resultCode, Intent data) { 58 | super.onActivityResult(requestCode, resultCode, data); 59 | if (requestCode != REQUEST_CODE) { 60 | Log.e("ERROR", "Unsupported Request"); 61 | return; 62 | } 63 | 64 | LineLoginResult result = LineLoginApi.getLoginResultFromIntent(data); 65 | 66 | switch (result.getResponseCode()) { 67 | 68 | case SUCCESS: 69 | 70 | Intent transitionIntent = new Intent(this, PostLoginActivity.class); 71 | transitionIntent.putExtra("line_profile", result.getLineProfile()); 72 | transitionIntent.putExtra("line_credential", result.getLineCredential()); 73 | startActivity(transitionIntent); 74 | break; 75 | 76 | case CANCEL: 77 | Log.e("ERROR", "LINE Login Canceled by user!!"); 78 | break; 79 | 80 | default: 81 | Log.e("ERROR", "Login FAILED!"); 82 | Log.e("ERROR", result.getErrorData().toString()); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/java/jp/line/android/sdk/sample/PostLoginActivity.java: -------------------------------------------------------------------------------- 1 | package jp.line.android.sdk.sample; 2 | 3 | import android.app.AlertDialog; 4 | import android.app.Dialog; 5 | import android.app.DialogFragment; 6 | import android.content.Intent; 7 | import android.content.pm.ActivityInfo; 8 | import android.content.res.Configuration; 9 | import android.graphics.Bitmap; 10 | import android.graphics.BitmapFactory; 11 | import android.net.Uri; 12 | import android.os.AsyncTask; 13 | import android.os.Bundle; 14 | import android.support.v7.app.AppCompatActivity; 15 | import android.util.Log; 16 | import android.view.LayoutInflater; 17 | import android.view.View; 18 | import android.widget.Button; 19 | import android.widget.ImageView; 20 | import android.widget.TextView; 21 | import android.widget.Toast; 22 | 23 | import com.linecorp.linesdk.LineAccessToken; 24 | import com.linecorp.linesdk.LineApiResponse; 25 | import com.linecorp.linesdk.LineCredential; 26 | import com.linecorp.linesdk.LineProfile; 27 | import com.linecorp.linesdk.api.LineApiClient; 28 | import com.linecorp.linesdk.api.LineApiClientBuilder; 29 | 30 | import java.io.IOException; 31 | import java.io.InputStream; 32 | import java.net.URL; 33 | 34 | 35 | public class PostLoginActivity extends AppCompatActivity { 36 | 37 | private LineApiClient lineApiClient; 38 | 39 | // Method for preventing orientation changes during ASyncTasks 40 | private void lockScreenOrientation(){ 41 | int currentOrientation = getResources().getConfiguration().orientation; 42 | if (currentOrientation == Configuration.ORIENTATION_PORTRAIT){ 43 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 44 | } else { 45 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 46 | } 47 | } 48 | 49 | // This method is used to reenable orientation changes after an ASyncTask is finished. 50 | private void unlockScreenOrientation(){ 51 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); 52 | } 53 | 54 | public static class ProfileDialogFragment extends DialogFragment { 55 | 56 | private LineProfile profileInfo; 57 | 58 | @Override 59 | public Dialog onCreateDialog(Bundle savedInstanceState) { 60 | 61 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 62 | LayoutInflater inflater = getActivity().getLayoutInflater(); 63 | View view = inflater.inflate(R.layout.profile_dialog, null); 64 | 65 | 66 | TextView textview = (TextView) view.findViewById(R.id.profileName); 67 | textview.setText(profileInfo.getDisplayName()); 68 | textview = (TextView) view.findViewById(R.id.profileMessage); 69 | textview.setText(profileInfo.getStatusMessage()); 70 | textview = (TextView) view.findViewById(R.id.profileMid); 71 | textview.setText(profileInfo.getUserId()); 72 | Uri pictureUrl = profileInfo.getPictureUrl(); 73 | textview = (TextView) view.findViewById(R.id.profileImageUrl); 74 | 75 | // If the user's profile picture is not set, the picture url will be null. 76 | if (pictureUrl != null) { 77 | textview.setText(profileInfo.getPictureUrl().toString()); 78 | } else { 79 | textview.setText(view.getContext().getResources().getString(R.string.no_profile_image_set)); 80 | } 81 | 82 | view.findViewById(R.id.loadingPanel).setVisibility(View.GONE); 83 | view.findViewById(R.id.profileContent).setVisibility(View.VISIBLE); 84 | 85 | builder.setView(view); 86 | builder.setPositiveButton("OK", null); 87 | return builder.create(); 88 | } 89 | 90 | public LineProfile getProfileInfo() { 91 | return profileInfo; 92 | } 93 | 94 | public void setProfileInfo(LineProfile profileInfo) { 95 | this.profileInfo = profileInfo; 96 | } 97 | } 98 | 99 | 100 | public class ImageLoaderTask extends AsyncTask { 101 | 102 | final static String TAG = "ImageLoaderTask"; 103 | 104 | protected void onPreExecute(){ 105 | lockScreenOrientation(); 106 | } 107 | 108 | protected Bitmap doInBackground(String... strings) { 109 | Bitmap bitmap = null; 110 | try { 111 | URL url = new URL(strings[0]); 112 | bitmap = BitmapFactory.decodeStream((InputStream) url.getContent()); 113 | } catch (IOException e) { 114 | Log.e(TAG, e.getMessage()); 115 | } 116 | return bitmap; 117 | } 118 | 119 | protected void onPostExecute(Bitmap bitmap) { 120 | ImageView profileImageView = (ImageView) findViewById(R.id.profileImageView); 121 | profileImageView.setImageBitmap(bitmap); 122 | unlockScreenOrientation(); 123 | } 124 | } 125 | 126 | 127 | public class RefreshTokenTask extends AsyncTask> { 128 | 129 | final static String TAG = "RefreshTokenTask"; 130 | 131 | protected void onPreExecute(){ 132 | lockScreenOrientation(); 133 | } 134 | 135 | protected LineApiResponse doInBackground(Void... params) { 136 | 137 | return lineApiClient.refreshAccessToken(); 138 | } 139 | 140 | protected void onPostExecute(LineApiResponse response) { 141 | 142 | if (response.isSuccess()) { 143 | String updatedAccessToken = lineApiClient.getCurrentAccessToken().getResponseData().getAccessToken(); 144 | 145 | // Update the view 146 | TextView accessTokenField = (TextView) findViewById(R.id.accessTokenField); 147 | accessTokenField.setText(updatedAccessToken); 148 | Toast.makeText(getApplicationContext(), "Access Token has been refreshed.", Toast.LENGTH_SHORT).show(); 149 | } else { 150 | Toast.makeText(getApplicationContext(), "Could not refresh the access token.", Toast.LENGTH_SHORT).show(); 151 | Log.e(TAG, response.getErrorData().toString()); 152 | } 153 | 154 | unlockScreenOrientation(); 155 | } 156 | } 157 | 158 | public class VerifyTokenTask extends AsyncTask> { 159 | 160 | final static String TAG = "VerifyTokenTask"; 161 | 162 | protected void onPreExecute(){ 163 | lockScreenOrientation(); 164 | } 165 | 166 | protected LineApiResponse doInBackground(Void... params) { 167 | 168 | return lineApiClient.verifyToken(); 169 | } 170 | 171 | protected void onPostExecute(LineApiResponse response) { 172 | 173 | if (response.isSuccess()) { 174 | StringBuilder toastStringBuilder = new StringBuilder("Access Token is VALID and contains the permissions "); 175 | 176 | for (String temp : response.getResponseData().getPermission()) { 177 | toastStringBuilder.append(temp + ", "); 178 | } 179 | Toast.makeText(getApplicationContext(), toastStringBuilder.toString(), Toast.LENGTH_SHORT).show(); 180 | 181 | } else { 182 | Toast.makeText(getApplicationContext(), "Access Token is NOT VALID", Toast.LENGTH_SHORT).show(); 183 | } 184 | unlockScreenOrientation(); 185 | } 186 | } 187 | 188 | public class GetProfileTask extends AsyncTask> { 189 | 190 | private ProfileDialogFragment fragment; 191 | 192 | final static String TAG = "GetProfileTask"; 193 | 194 | protected void onPreExecute(){ 195 | lockScreenOrientation(); 196 | } 197 | 198 | protected LineApiResponse doInBackground(Void... params) { 199 | return lineApiClient.getProfile(); 200 | } 201 | 202 | protected void onPostExecute(LineApiResponse apiResponse) { 203 | 204 | if(apiResponse.isSuccess()) { 205 | ProfileDialogFragment newFragment = new ProfileDialogFragment(); 206 | newFragment.setProfileInfo(apiResponse.getResponseData()); 207 | newFragment.show(getFragmentManager(), null); 208 | unlockScreenOrientation(); 209 | } else { 210 | Toast.makeText(getApplicationContext(), "Failed to get profile.", Toast.LENGTH_SHORT).show(); 211 | Log.e(TAG, "Failed to get Profile: " + apiResponse.getErrorData().toString()); 212 | } 213 | } 214 | } 215 | 216 | public class LogoutTask extends AsyncTask { 217 | 218 | final static String TAG = "LogoutTask"; 219 | 220 | protected void onPreExecute(){ 221 | lockScreenOrientation(); 222 | } 223 | 224 | protected LineApiResponse doInBackground(Void... params) { 225 | return lineApiClient.logout(); 226 | } 227 | 228 | protected void onPostExecute(LineApiResponse apiResponse){ 229 | 230 | if(apiResponse.isSuccess()){ 231 | Toast.makeText(getApplicationContext(), "Logout Successful", Toast.LENGTH_SHORT).show(); 232 | } else { 233 | Toast.makeText(getApplicationContext(), "Logout Failed", Toast.LENGTH_SHORT).show(); 234 | Log.e(TAG, "Logout Failed: " + apiResponse.getErrorData().toString()); 235 | } 236 | unlockScreenOrientation(); 237 | } 238 | } 239 | 240 | protected void onCreate(Bundle savedInstanceState) { 241 | super.onCreate(savedInstanceState); 242 | setContentView(R.layout.activity_post_login); 243 | 244 | LineApiClientBuilder apiClientBuilder = new LineApiClientBuilder(getApplicationContext(), Constants.CHANNEL_ID); 245 | lineApiClient = apiClientBuilder.build(); 246 | 247 | // Profile Button Click Listener 248 | final Button profileButton = (Button) findViewById(R.id.profileButton); 249 | 250 | profileButton.setOnClickListener(new View.OnClickListener() { 251 | 252 | public void onClick(View v) { 253 | new GetProfileTask().execute(); 254 | } 255 | }); 256 | 257 | 258 | // Refresh Button Click Listener 259 | final Button refreshButton = (Button) findViewById(R.id.refreshButton); 260 | refreshButton.setOnClickListener(new View.OnClickListener() { 261 | 262 | public void onClick(View v) { 263 | 264 | new RefreshTokenTask().execute(); 265 | } 266 | 267 | }); 268 | 269 | // Verify Button Click Listener 270 | final Button verifyButton = (Button) findViewById(R.id.verifyButton); 271 | verifyButton.setOnClickListener(new View.OnClickListener() { 272 | 273 | public void onClick(View v) { 274 | 275 | new VerifyTokenTask().execute(); 276 | } 277 | 278 | }); 279 | 280 | // Logout Button Click Listener 281 | final Button logoutButton = (Button) findViewById(R.id.logoutButton); 282 | logoutButton.setOnClickListener(new View.OnClickListener() { 283 | 284 | public void onClick(View v) { 285 | 286 | new LogoutTask().execute(); 287 | finish(); 288 | } 289 | 290 | }); 291 | 292 | // Get the intent so that we can get information from the previous activity 293 | Intent intent = getIntent(); 294 | LineProfile intentProfile = intent.getParcelableExtra("line_profile"); 295 | LineCredential intentCredential = intent.getParcelableExtra("line_credential"); 296 | 297 | ImageView profileImageView = (ImageView) findViewById(R.id.profileImageView); 298 | Uri pictureUrl = intentProfile.getPictureUrl(); 299 | 300 | if (pictureUrl != null) { 301 | Log.i("PostLoginActivity", "Picture URL: " + pictureUrl.toString()); 302 | new ImageLoaderTask().execute(pictureUrl.toString()); 303 | } 304 | 305 | TextView profileText; 306 | 307 | profileText = (TextView) findViewById(R.id.displayNameField); 308 | profileText.setText(intentProfile.getDisplayName()); 309 | 310 | profileText = (TextView) findViewById(R.id.userIDField); 311 | profileText.setText(intentProfile.getUserId()); 312 | 313 | profileText = (TextView) findViewById(R.id.statusMessageField); 314 | profileText.setText(intentProfile.getStatusMessage()); 315 | 316 | profileText = (TextView) findViewById(R.id.accessTokenField); 317 | profileText.setText(intentCredential.getAccessToken().getAccessToken()); 318 | 319 | } 320 | } 321 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/btn_login_base.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/line/line-sdk-starter-android-v2/b4eda32fd9488150e6c152228fb9cff383f0b63c/app/src/main/res/drawable-hdpi/btn_login_base.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/btn_login_press.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/line/line-sdk-starter-android-v2/b4eda32fd9488150e6c152228fb9cff383f0b63c/app/src/main/res/drawable-hdpi/btn_login_press.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/button_press.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/btn_login_base.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/line/line-sdk-starter-android-v2/b4eda32fd9488150e6c152228fb9cff383f0b63c/app/src/main/res/drawable-mdpi/btn_login_base.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/btn_login_press.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/line/line-sdk-starter-android-v2/b4eda32fd9488150e6c152228fb9cff383f0b63c/app/src/main/res/drawable-mdpi/btn_login_press.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/button_press.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-tvdpi/btn_login_base.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/line/line-sdk-starter-android-v2/b4eda32fd9488150e6c152228fb9cff383f0b63c/app/src/main/res/drawable-tvdpi/btn_login_base.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-tvdpi/btn_login_press.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/line/line-sdk-starter-android-v2/b4eda32fd9488150e6c152228fb9cff383f0b63c/app/src/main/res/drawable-tvdpi/btn_login_press.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-tvdpi/button_press.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/btn_login_base.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/line/line-sdk-starter-android-v2/b4eda32fd9488150e6c152228fb9cff383f0b63c/app/src/main/res/drawable-xhdpi/btn_login_base.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/btn_login_press.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/line/line-sdk-starter-android-v2/b4eda32fd9488150e6c152228fb9cff383f0b63c/app/src/main/res/drawable-xhdpi/btn_login_press.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/button_press.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/btn_login_base.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/line/line-sdk-starter-android-v2/b4eda32fd9488150e6c152228fb9cff383f0b63c/app/src/main/res/drawable-xxhdpi/btn_login_base.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/btn_login_press.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/line/line-sdk-starter-android-v2/b4eda32fd9488150e6c152228fb9cff383f0b63c/app/src/main/res/drawable-xxhdpi/btn_login_press.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/button_press.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 26 | 27 | 36 | 37 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_post_login.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | 16 | 19 | 20 | 23 | 24 | 29 | 30 | 40 | 41 | 42 | 43 | 49 | 50 | 56 | 57 | 58 | 64 | 65 | 66 | 73 | 74 | 79 | 80 | 88 | 89 | 94 | 95 | 102 | 103 | 108 | 109 | 110 | 111 | 117 | 118 |