├── app ├── .gitignore ├── src │ ├── main │ │ ├── assets │ │ │ └── fonts │ │ │ │ ├── IRANSansMobile.ttf │ │ │ │ └── FontLicense.txt │ │ ├── res │ │ │ ├── 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 │ │ │ │ ├── dimens.xml │ │ │ │ ├── colors.xml │ │ │ │ ├── styles.xml │ │ │ │ └── strings.xml │ │ │ ├── values-w820dp │ │ │ │ └── dimens.xml │ │ │ ├── menu │ │ │ │ └── menu_main.xml │ │ │ └── layout │ │ │ │ ├── item_theme.xml │ │ │ │ ├── content_main.xml │ │ │ │ ├── activity_main.xml │ │ │ │ └── activity_about.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── github │ │ │ │ └── bkhezry │ │ │ │ └── demo │ │ │ │ ├── MyApplication.java │ │ │ │ ├── model │ │ │ │ ├── SampleData.java │ │ │ │ └── DataGenerator.java │ │ │ │ ├── adapter │ │ │ │ ├── RecyclerItemClickListener.java │ │ │ │ └── ThemesAdapter.java │ │ │ │ ├── AboutActivity.java │ │ │ │ └── MainActivity.java │ │ └── AndroidManifest.xml │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── github │ │ │ └── bkhezry │ │ │ └── demo │ │ │ └── ExampleUnitTest.java │ └── androidTest │ │ └── java │ │ └── com │ │ └── github │ │ └── bkhezry │ │ └── demo │ │ └── ExampleInstrumentedTest.java ├── proguard-rules.pro └── build.gradle ├── library ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── drawable-hdpi │ │ │ ├── bg_drawer_dark.png │ │ │ └── bg_drawer_light.png │ │ ├── drawable-mdpi │ │ │ ├── bg_drawer_dark.png │ │ │ └── bg_drawer_light.png │ │ ├── drawable-xhdpi │ │ │ ├── bg_drawer_dark.png │ │ │ └── bg_drawer_light.png │ │ ├── drawable-xxhdpi │ │ │ ├── bg_drawer_dark.png │ │ │ └── bg_drawer_light.png │ │ ├── drawable-xxxhdpi │ │ │ ├── bg_drawer_dark.png │ │ │ └── bg_drawer_light.png │ │ ├── values-v14 │ │ │ └── dimens.xml │ │ ├── values-w820dp │ │ │ └── dimens.xml │ │ ├── values │ │ │ ├── bools.xml │ │ │ ├── integers.xml │ │ │ ├── arrays.xml │ │ │ ├── non_translatable.xml │ │ │ ├── preference_keys.xml │ │ │ ├── attrs.xml │ │ │ ├── strings.xml │ │ │ ├── dimens.xml │ │ │ ├── colors.xml │ │ │ ├── styles.xml │ │ │ └── themes.xml │ │ ├── values-w820dp-land │ │ │ ├── bools.xml │ │ │ └── dimens.xml │ │ ├── drawable │ │ │ ├── ic_expand_more_white_24dp.xml │ │ │ ├── ic_reply_white_24dp.xml │ │ │ ├── ic_arrow_back_white_24dp.xml │ │ │ ├── ic_arrow_forward_white_24dp.xml │ │ │ ├── ic_save_white_48dp.xml │ │ │ ├── ic_clear_white_24dp.xml │ │ │ ├── ic_local_library_white_48dp.xml │ │ │ ├── ic_bookmark_white_24dp.xml │ │ │ ├── ic_open_in_browser_white_24dp.xml │ │ │ ├── ic_more_vert_white_24dp.xml │ │ │ ├── ic_bookmark_border_white_24dp.xml │ │ │ ├── progress.xml │ │ │ ├── ic_refresh_white_24dp.xml │ │ │ ├── ic_zoom_out_map_white_24dp.xml │ │ │ ├── ic_search_white_24dp.xml │ │ │ ├── ic_thumb_up_border_white_24dp.xml │ │ │ ├── ic_thumb_up_white_24dp.xml │ │ │ └── ic_share_white_24dp.xml │ │ ├── layout │ │ │ ├── button_reply.xml │ │ │ ├── button_more.xml │ │ │ ├── activity_item.xml │ │ │ ├── fragment_web.xml │ │ │ ├── item_header.xml │ │ │ └── toolbar_web.xml │ │ ├── menu │ │ │ ├── menu_search.xml │ │ │ └── menu_item.xml │ │ └── anim │ │ │ ├── slide_in_up.xml │ │ │ └── slide_out_down.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── github │ │ └── bkhezry │ │ └── extrawebview │ │ ├── widget │ │ ├── ViewPager.java │ │ ├── IconButton.java │ │ ├── CacheableWebView.java │ │ ├── ItemPagerAdapter.java │ │ └── PopupMenu.java │ │ ├── Injectable.java │ │ ├── Scrollable.java │ │ ├── UiModule.java │ │ ├── WebFragment.java │ │ ├── Application.java │ │ ├── InjectableActivity.java │ │ ├── MenuTintDelegate.java │ │ ├── data │ │ ├── IntentServiceResult.java │ │ ├── ThemePreference.java │ │ ├── ViewOption.java │ │ ├── DataModel.java │ │ └── DataModelBuilder.java │ │ ├── ScrollAwareFABBehavior.java │ │ ├── BaseFragment.java │ │ ├── LazyLoadFragment.java │ │ ├── Preferences.java │ │ ├── ExtraWebViewCreator.java │ │ └── CustomTabsDelegate.java ├── proguard-support.pro ├── proguard-rules.pro └── build.gradle ├── settings.gradle ├── assets ├── screenshot_1.png ├── screenshot_2.png ├── screenshot_3.png └── DemoExtraWebView-last.apk ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .idea ├── encodings.xml ├── vcs.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── checkstyle-idea.xml ├── .travis.yml ├── gradle.properties ├── .gitignore ├── gradlew.bat ├── gradlew └── README.md /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /library/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':library' 2 | -------------------------------------------------------------------------------- /assets/screenshot_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bkhezry/ExtraWebView/HEAD/assets/screenshot_1.png -------------------------------------------------------------------------------- /assets/screenshot_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bkhezry/ExtraWebView/HEAD/assets/screenshot_2.png -------------------------------------------------------------------------------- /assets/screenshot_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bkhezry/ExtraWebView/HEAD/assets/screenshot_3.png -------------------------------------------------------------------------------- /assets/DemoExtraWebView-last.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bkhezry/ExtraWebView/HEAD/assets/DemoExtraWebView-last.apk -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bkhezry/ExtraWebView/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/assets/fonts/IRANSansMobile.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bkhezry/ExtraWebView/HEAD/app/src/main/assets/fonts/IRANSansMobile.ttf -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bkhezry/ExtraWebView/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bkhezry/ExtraWebView/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bkhezry/ExtraWebView/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bkhezry/ExtraWebView/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bkhezry/ExtraWebView/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-hdpi/bg_drawer_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bkhezry/ExtraWebView/HEAD/library/src/main/res/drawable-hdpi/bg_drawer_dark.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-mdpi/bg_drawer_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bkhezry/ExtraWebView/HEAD/library/src/main/res/drawable-mdpi/bg_drawer_dark.png -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /library/src/main/res/drawable-hdpi/bg_drawer_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bkhezry/ExtraWebView/HEAD/library/src/main/res/drawable-hdpi/bg_drawer_light.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-mdpi/bg_drawer_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bkhezry/ExtraWebView/HEAD/library/src/main/res/drawable-mdpi/bg_drawer_light.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xhdpi/bg_drawer_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bkhezry/ExtraWebView/HEAD/library/src/main/res/drawable-xhdpi/bg_drawer_dark.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xhdpi/bg_drawer_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bkhezry/ExtraWebView/HEAD/library/src/main/res/drawable-xhdpi/bg_drawer_light.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxhdpi/bg_drawer_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bkhezry/ExtraWebView/HEAD/library/src/main/res/drawable-xxhdpi/bg_drawer_dark.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxhdpi/bg_drawer_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bkhezry/ExtraWebView/HEAD/library/src/main/res/drawable-xxhdpi/bg_drawer_light.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxxhdpi/bg_drawer_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bkhezry/ExtraWebView/HEAD/library/src/main/res/drawable-xxxhdpi/bg_drawer_dark.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxxhdpi/bg_drawer_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bkhezry/ExtraWebView/HEAD/library/src/main/res/drawable-xxxhdpi/bg_drawer_light.png -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Nov 09 19:32:50 IRST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.0-milestone-1-all.zip 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | #FFFFFF 7 | 8 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /library/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 28 | 29 | 34 | 35 | 36 | 37 | 38 | 44 | 45 | 50 | 51 | 52 | 53 | 54 | 59 | 60 | 61 | 62 | 63 | 72 | 73 | 78 | 79 | 80 | 85 | 86 | 91 | 92 | 97 | 98 | 103 | 104 | 109 | 110 | 115 | 116 | 117 | 118 | 119 | 120 | 126 | 127 | 132 | 139 | 142 | 143 | -------------------------------------------------------------------------------- /app/src/main/java/com/github/bkhezry/demo/MainActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016. Behrouz Khezry 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | * License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | 16 | package com.github.bkhezry.demo; 17 | 18 | import android.content.Context; 19 | import android.content.Intent; 20 | import android.os.Bundle; 21 | import android.view.Menu; 22 | import android.view.MenuItem; 23 | import android.view.View; 24 | import android.widget.Toast; 25 | 26 | import com.github.bkhezry.demo.adapter.RecyclerItemClickListener; 27 | import com.github.bkhezry.demo.adapter.ThemesAdapter; 28 | import com.github.bkhezry.demo.model.DataGenerator; 29 | import com.github.bkhezry.demo.model.SampleData; 30 | import com.github.bkhezry.extrawebview.ExtraWebViewCreator; 31 | import com.github.bkhezry.extrawebview.data.DataModel; 32 | import com.github.bkhezry.extrawebview.data.DataModelBuilder; 33 | import com.github.bkhezry.extrawebview.data.IntentServiceResult; 34 | import com.github.bkhezry.extrawebview.data.ThemePreference; 35 | 36 | import org.greenrobot.eventbus.EventBus; 37 | import org.greenrobot.eventbus.Subscribe; 38 | import org.greenrobot.eventbus.ThreadMode; 39 | 40 | import java.util.ArrayList; 41 | 42 | import androidx.appcompat.app.AppCompatActivity; 43 | import androidx.appcompat.widget.Toolbar; 44 | import androidx.recyclerview.widget.LinearLayoutManager; 45 | import androidx.recyclerview.widget.RecyclerView; 46 | import uk.co.chrisjenx.calligraphy.CalligraphyContextWrapper; 47 | 48 | public class MainActivity extends AppCompatActivity { 49 | private DataModel dataModel; 50 | private ArrayList dataGenerators; 51 | 52 | @Override 53 | protected void onCreate(Bundle savedInstanceState) { 54 | super.onCreate(savedInstanceState); 55 | setContentView(R.layout.activity_main); 56 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 57 | setSupportActionBar(toolbar); 58 | EventBus.getDefault().register(this); 59 | RecyclerView rvThemes = (RecyclerView) findViewById(R.id.rvThemes); 60 | rvThemes.setHasFixedSize(true); 61 | DataGenerator dataGenerator = new DataGenerator(MainActivity.this); 62 | dataGenerators = dataGenerator.createThemeList(); 63 | ThemesAdapter adapter = new ThemesAdapter(this, dataGenerators); 64 | rvThemes.setAdapter(adapter); 65 | LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false); 66 | rvThemes.setLayoutManager(layoutManager); 67 | rvThemes.addOnItemTouchListener( 68 | new RecyclerItemClickListener(MainActivity.this, rvThemes, new RecyclerItemClickListener.OnItemClickListener() { 69 | @Override 70 | public void onItemClick(View view, int position) { 71 | generateWebView(ThemePreference.THEME_NAMES.get(position), position); 72 | } 73 | 74 | @Override 75 | public void onLongItemClick(View view, int position) { 76 | // do whatever 77 | } 78 | }) 79 | ); 80 | } 81 | 82 | private void generateWebView(String themeName, int position) { 83 | SampleData sampleData = dataGenerators.get(position); 84 | Long tsLong = System.currentTimeMillis(); 85 | dataModel = new DataModelBuilder() 86 | .withId(Long.valueOf(position)) 87 | .withType("blog") 88 | .withBy(sampleData.getAuthor()) 89 | .withTime(tsLong) 90 | .withUrl(sampleData.getUrl()) 91 | .withDescription(sampleData.getDescription()) 92 | .withBookmark(true) 93 | .withViewed(false) 94 | .withRank(0) 95 | .withVoted(true) 96 | .withPageTitle(sampleData.getTitle()) 97 | .build(); 98 | new ExtraWebViewCreator() 99 | .withContext(MainActivity.this) 100 | .withBookmarkIcon(true) 101 | .withVoteIcon(true) 102 | .withCustomFont("fonts/IRANSansMobile.ttf") 103 | .withThemeName(themeName) 104 | .withDataModel(dataModel) 105 | .show(); 106 | } 107 | 108 | @Subscribe(threadMode = ThreadMode.MAIN) 109 | public void doThis(IntentServiceResult intentServiceResult) { 110 | if (intentServiceResult.isChecked()) { 111 | Toast.makeText(this, "Record Id: " + intentServiceResult.getId() + " - " + intentServiceResult.getTypeEvent() + " Checked", Toast.LENGTH_SHORT).show(); 112 | } else { 113 | Toast.makeText(this, "Record Id: " + intentServiceResult.getId() + " - " + intentServiceResult.getTypeEvent() + " UnChecked", Toast.LENGTH_SHORT).show(); 114 | } 115 | } 116 | 117 | @Override 118 | public boolean onCreateOptionsMenu(Menu menu) { 119 | // Inflate the menu; this adds items to the action bar if it is present. 120 | getMenuInflater().inflate(R.menu.menu_main, menu); 121 | return true; 122 | } 123 | 124 | @Override 125 | public boolean onOptionsItemSelected(MenuItem item) { 126 | // Handle action bar item clicks here. The action bar will 127 | // automatically handle clicks on the Home/Up button, so long 128 | // as you specify a parent activity in AndroidManifest.xml. 129 | int id = item.getItemId(); 130 | 131 | //noinspection SimplifiableIfStatement 132 | if (id == R.id.action_about) { 133 | Intent intent = new Intent(MainActivity.this, AboutActivity.class); 134 | startActivity(intent); 135 | return true; 136 | } 137 | 138 | return super.onOptionsItemSelected(item); 139 | } 140 | 141 | @Override 142 | protected void onDestroy() { 143 | EventBus.getDefault().unregister(this); 144 | super.onDestroy(); 145 | 146 | } 147 | 148 | @Override 149 | protected void attachBaseContext(Context newBase) { 150 | super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase)); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /library/src/main/java/com/github/bkhezry/extrawebview/CustomTabsDelegate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 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 | package com.github.bkhezry.extrawebview; 17 | 18 | import android.app.Activity; 19 | import android.content.ComponentName; 20 | import android.content.Context; 21 | import android.content.Intent; 22 | import android.content.pm.PackageManager; 23 | import android.content.pm.ResolveInfo; 24 | import android.net.Uri; 25 | import android.os.Bundle; 26 | import android.text.TextUtils; 27 | 28 | import java.lang.ref.WeakReference; 29 | import java.util.ArrayList; 30 | import java.util.List; 31 | 32 | import androidx.browser.customtabs.CustomTabsClient; 33 | import androidx.browser.customtabs.CustomTabsServiceConnection; 34 | import androidx.browser.customtabs.CustomTabsSession; 35 | 36 | public class CustomTabsDelegate { 37 | private static final String STABLE_PACKAGE = "com.android.chrome"; 38 | private static final String BETA_PACKAGE = "com.chrome.beta"; 39 | private static final String DEV_PACKAGE = "com.chrome.dev"; 40 | private static final String LOCAL_PACKAGE = "com.google.android.apps.chrome"; 41 | private static final String ACTION_CUSTOM_TABS_CONNECTION = 42 | "android.support.customtabs.action.CustomTabsService"; 43 | private static String sPackageNameToUse; 44 | private CustomTabsSession mCustomTabsSession; 45 | private CustomTabsClient mClient; 46 | private CustomTabsServiceConnection mConnection; 47 | 48 | /** 49 | * Binds the Activity to the Custom Tabs Service. 50 | * @param activity the activity to be binded to the service. 51 | */ 52 | public void bindCustomTabsService(Activity activity) { 53 | if (mClient != null) { 54 | return; 55 | } 56 | if (TextUtils.isEmpty(getPackageNameToUse(activity))) { 57 | return; 58 | } 59 | mConnection = new ServiceConnection(this); 60 | CustomTabsClient.bindCustomTabsService(activity, sPackageNameToUse, mConnection); 61 | } 62 | 63 | /** 64 | * Unbinds the Activity from the Custom Tabs Service. 65 | * @param activity the activity that is connected to the service. 66 | */ 67 | public void unbindCustomTabsService(Activity activity) { 68 | if (mConnection == null) { 69 | return; 70 | } 71 | activity.unbindService(mConnection); 72 | mClient = null; 73 | mCustomTabsSession = null; 74 | mConnection = null; 75 | } 76 | 77 | /** 78 | * @see {@link CustomTabsSession#mayLaunchUrl(Uri, Bundle, List)}. 79 | * @return true if call to mayLaunchUrl was accepted. 80 | */ 81 | public boolean mayLaunchUrl(Uri uri, Bundle extras, List otherLikelyBundles) { 82 | if (mClient == null) { 83 | return false; 84 | } 85 | CustomTabsSession session = getSession(); 86 | return session != null && session.mayLaunchUrl(uri, extras, otherLikelyBundles); 87 | } 88 | 89 | /** 90 | * Creates or retrieves an exiting CustomTabsSession. 91 | * 92 | * @return a CustomTabsSession. 93 | */ 94 | public CustomTabsSession getSession() { 95 | if (mClient == null) { 96 | mCustomTabsSession = null; 97 | } else if (mCustomTabsSession == null) { 98 | mCustomTabsSession = mClient.newSession(null); 99 | } 100 | return mCustomTabsSession; 101 | } 102 | 103 | void onServiceConnected(CustomTabsClient client) { 104 | mClient = client; 105 | mClient.warmup(0L); 106 | } 107 | 108 | void onServiceDisconnected() { 109 | mClient = null; 110 | mCustomTabsSession = null; 111 | } 112 | 113 | private static String getPackageNameToUse(Context context) { 114 | if (sPackageNameToUse != null) { 115 | return sPackageNameToUse; 116 | } 117 | // packagesSupportingCustomTabs contains all apps that can handle both VIEW intents 118 | // and service calls. 119 | List packagesSupportingCustomTabs = new ArrayList<>(); 120 | PackageManager pm = context.getPackageManager(); 121 | List resolvedActivityList = pm.queryIntentActivities( 122 | new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com")), 0); 123 | //noinspection Convert2streamapi 124 | for (ResolveInfo info : resolvedActivityList) { 125 | if (pm.resolveService(new Intent() 126 | .setAction(ACTION_CUSTOM_TABS_CONNECTION) 127 | .setPackage(info.activityInfo.packageName), 0) != null) { 128 | packagesSupportingCustomTabs.add(info.activityInfo.packageName); 129 | } 130 | } 131 | if (packagesSupportingCustomTabs.contains(STABLE_PACKAGE)) { 132 | sPackageNameToUse = STABLE_PACKAGE; 133 | } else if (packagesSupportingCustomTabs.contains(BETA_PACKAGE)) { 134 | sPackageNameToUse = BETA_PACKAGE; 135 | } else if (packagesSupportingCustomTabs.contains(DEV_PACKAGE)) { 136 | sPackageNameToUse = DEV_PACKAGE; 137 | } else if (packagesSupportingCustomTabs.contains(LOCAL_PACKAGE)) { 138 | sPackageNameToUse = LOCAL_PACKAGE; 139 | } 140 | return sPackageNameToUse; 141 | } 142 | 143 | static class ServiceConnection extends CustomTabsServiceConnection { 144 | private WeakReference mDelegate; 145 | 146 | public ServiceConnection(CustomTabsDelegate delegate) { 147 | mDelegate = new WeakReference<>(delegate); 148 | } 149 | 150 | @Override 151 | public void onCustomTabsServiceConnected(ComponentName name, CustomTabsClient client) { 152 | CustomTabsDelegate delegate = mDelegate.get(); 153 | if (delegate != null) { 154 | delegate.onServiceConnected(client); 155 | } 156 | } 157 | 158 | @Override 159 | public void onServiceDisconnected(ComponentName name) { 160 | CustomTabsDelegate delegate = mDelegate.get(); 161 | if (delegate != null) { 162 | delegate.onServiceDisconnected(); 163 | } 164 | } 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /library/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 32 | 33 | 60 | 61 | 66 | 67 | 68 | 71 | 72 | 75 | 76 | 81 | 82 | 92 | 93 | 100 | 101 | 109 | 110 | 119 | 120 | 129 | -------------------------------------------------------------------------------- /library/src/main/java/com/github/bkhezry/extrawebview/data/DataModelBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Behrouz Khezry 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 | package com.github.bkhezry.extrawebview.data; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | import androidx.annotation.NonNull; 22 | import androidx.annotation.Nullable; 23 | 24 | /** 25 | * data model Builder. use to generate DataModel class as fluent interface. 26 | */ 27 | public class DataModelBuilder { 28 | private Long _id; 29 | private String _type = "blog"; 30 | private String _by; 31 | private Long _time; 32 | private String _url; 33 | private String _description; 34 | private CharSequence _pageTitle; 35 | private boolean _bookmark = false; 36 | private boolean _viewed = false; 37 | private int _rank = 0; 38 | private boolean _voted = false; 39 | private DataModel dataModel; 40 | 41 | public DataModelBuilder() { 42 | dataModel = new DataModel(); 43 | } 44 | 45 | /** 46 | * set id of blog post 47 | * 48 | * @param id as Long 49 | * @return DataModelBuilder object 50 | */ 51 | public DataModelBuilder withId(@NonNull Long id) { 52 | this._id = id; 53 | return this; 54 | } 55 | 56 | /** 57 | * set type of blog post 58 | * 59 | * @param type as String. default value is "blog" 60 | * @return DataModelBuilder object 61 | */ 62 | public DataModelBuilder withType(@Nullable String type) { 63 | this._type = type; 64 | return this; 65 | } 66 | 67 | /** 68 | * set Author name 69 | * 70 | * @param by as String. author of blog post name 71 | * @return DataModelBuilder object 72 | */ 73 | public DataModelBuilder withBy(@NonNull String by) { 74 | this._by = by; 75 | return this; 76 | } 77 | 78 | /** 79 | * set time of creating post 80 | * 81 | * @param time as Long, timestamp format. 82 | * @return DataModelBuilder object 83 | */ 84 | public DataModelBuilder withTime(@NonNull Long time) { 85 | this._time = time; 86 | return this; 87 | } 88 | 89 | /** 90 | * set url of post 91 | * 92 | * @param url as String, url format 93 | * @return DataModelBuilder object 94 | */ 95 | public DataModelBuilder withUrl(@NonNull String url) { 96 | this._url = url; 97 | return this; 98 | } 99 | 100 | /** 101 | * set description tag of post 102 | * 103 | * @param description as String 104 | * @return DataModelBuilder object 105 | */ 106 | public DataModelBuilder withDescription(@NonNull String description) { 107 | this._description = description; 108 | return this; 109 | } 110 | 111 | /** 112 | * set favorite status of post 113 | * 114 | * @param isBookmark as boolean, default value is false 115 | * @return DataModelBuilder object 116 | */ 117 | public DataModelBuilder withBookmark(@NonNull Boolean isBookmark) { 118 | this._bookmark = isBookmark; 119 | return this; 120 | } 121 | 122 | /** 123 | * set post viewed status 124 | * 125 | * @param isViewed is true post viewed or false post not viewed, default value is false 126 | * @return DataModelBuilder object 127 | */ 128 | 129 | public DataModelBuilder withViewed(@NonNull Boolean isViewed) { 130 | this._viewed = isViewed; 131 | return this; 132 | } 133 | 134 | /** 135 | * set rank of post 136 | * 137 | * @param rank as Integer, default value is 0 138 | * @return DataModelBuilder object 139 | */ 140 | public DataModelBuilder withRank(@NonNull Integer rank) { 141 | this._rank = rank; 142 | return this; 143 | } 144 | 145 | /** 146 | * set status of post vote 147 | * 148 | * @param isVoted as boolean, if true post voted or false post not voted, default value is false 149 | * @return DataModelBuilder object 150 | */ 151 | public DataModelBuilder withVoted(@NonNull Boolean isVoted) { 152 | this._voted = isVoted; 153 | return this; 154 | } 155 | 156 | /** 157 | * set title of post tag 158 | * 159 | * @param pageTitle as String. 160 | * @return DataModelBuilder object 161 | */ 162 | public DataModelBuilder withPageTitle(@NonNull String pageTitle) { 163 | this._pageTitle = pageTitle; 164 | return this; 165 | } 166 | 167 | /** 168 | * return DataModel object or return IllegalStateException in value validation 169 | * 170 | * @return DataModel object 171 | */ 172 | public DataModel build() { 173 | List messageList = new ArrayList<>(); 174 | if (_id == null) { 175 | messageList.add("should be set Id with Long type.\n"); 176 | } else { 177 | dataModel.setId(_id); 178 | } 179 | dataModel.setType(_type); 180 | 181 | if (_by == null) { 182 | messageList.add("should be set By with Author name.\n"); 183 | } else { 184 | dataModel.setBy(_by); 185 | } 186 | if (_time == null) { 187 | messageList.add("should be set time with post create time.\n"); 188 | } else { 189 | dataModel.setTime(_time); 190 | } 191 | if (_url == null) { 192 | messageList.add("should be set url with url of website.\n"); 193 | } else { 194 | dataModel.setUrl(_url); 195 | } 196 | if (_pageTitle == null) { 197 | messageList.add("should be set page title with title of page.\n"); 198 | } else { 199 | dataModel.setPageTitle(_pageTitle); 200 | } 201 | if (_description == null) { 202 | messageList.add("should be set title with description of website.\n"); 203 | } else { 204 | dataModel.setDescription(_description); 205 | } 206 | if (messageList.size() > 0) { 207 | throw new IllegalStateException(getMessage(messageList)); 208 | } 209 | dataModel.setFavorite(_bookmark); 210 | dataModel.setViewed(_viewed); 211 | dataModel.setRank(_rank); 212 | dataModel.setVoted(_voted); 213 | return dataModel; 214 | } 215 | 216 | /** 217 | * @param messageList list of message 218 | * @return joined of messages as one message 219 | */ 220 | private String getMessage(List messageList) { 221 | String messageString = ""; 222 | for (int i = 0; i < messageList.size(); i++) { 223 | if (messageString.equals("")) { 224 | messageString = messageList.get(i); 225 | } else { 226 | messageString += "\n" + messageList.get(i); 227 | } 228 | } 229 | return messageString; 230 | } 231 | } 232 | --------------------------------------------------------------------------------