forked from mirrors/Fedilab
Remove built-in browser
This commit is contained in:
parent
403fb1aba7
commit
95beb7f3c1
18 changed files with 52 additions and 1542 deletions
|
@ -166,9 +166,6 @@
|
||||||
android:scheme="fedilab" />
|
android:scheme="fedilab" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
|
||||||
android:name=".activities.WebviewConnectActivity"
|
|
||||||
android:configChanges="keyboardHidden|orientation|screenSize" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.StatusHistoryActivity"
|
android:name=".activities.StatusHistoryActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||||
|
@ -193,9 +190,6 @@
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.FollowRequestActivity"
|
android:name=".activities.FollowRequestActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|screenSize" />
|
android:configChanges="keyboardHidden|orientation|screenSize" />
|
||||||
<activity
|
|
||||||
android:name=".activities.WebviewActivity"
|
|
||||||
android:configChanges="keyboardHidden|orientation|screenSize" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.ProfileActivity"
|
android:name=".activities.ProfileActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||||
|
|
|
@ -125,7 +125,6 @@ import app.fedilab.android.client.entities.api.Status;
|
||||||
import app.fedilab.android.client.entities.app.Account;
|
import app.fedilab.android.client.entities.app.Account;
|
||||||
import app.fedilab.android.client.entities.app.BaseAccount;
|
import app.fedilab.android.client.entities.app.BaseAccount;
|
||||||
import app.fedilab.android.client.entities.app.BottomMenu;
|
import app.fedilab.android.client.entities.app.BottomMenu;
|
||||||
import app.fedilab.android.client.entities.app.DomainsBlock;
|
|
||||||
import app.fedilab.android.client.entities.app.Pinned;
|
import app.fedilab.android.client.entities.app.Pinned;
|
||||||
import app.fedilab.android.client.entities.app.PinnedTimeline;
|
import app.fedilab.android.client.entities.app.PinnedTimeline;
|
||||||
import app.fedilab.android.client.entities.app.StatusCache;
|
import app.fedilab.android.client.entities.app.StatusCache;
|
||||||
|
@ -749,10 +748,6 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
boolean embedded_browser = sharedpreferences.getBoolean(getString(R.string.SET_EMBEDDED_BROWSER), true);
|
|
||||||
if (embedded_browser) {
|
|
||||||
DomainsBlock.updateDomains(BaseMainActivity.this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void rateThisApp();
|
protected abstract void rateThisApp();
|
||||||
|
|
|
@ -15,11 +15,16 @@ package app.fedilab.android.activities;
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
|
||||||
|
import static app.fedilab.android.helper.Helper.PREF_USER_TOKEN;
|
||||||
import static app.fedilab.android.helper.MastodonHelper.REDIRECT_CONTENT_WEB;
|
import static app.fedilab.android.helper.MastodonHelper.REDIRECT_CONTENT_WEB;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
@ -32,8 +37,10 @@ import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
|
||||||
|
import app.fedilab.android.BaseMainActivity;
|
||||||
import app.fedilab.android.R;
|
import app.fedilab.android.R;
|
||||||
import app.fedilab.android.client.entities.app.Account;
|
import app.fedilab.android.client.entities.app.Account;
|
||||||
|
import app.fedilab.android.exception.DBException;
|
||||||
import app.fedilab.android.helper.Helper;
|
import app.fedilab.android.helper.Helper;
|
||||||
import app.fedilab.android.ui.fragment.login.FragmentLoginMain;
|
import app.fedilab.android.ui.fragment.login.FragmentLoginMain;
|
||||||
import app.fedilab.android.viewmodel.mastodon.AccountsVM;
|
import app.fedilab.android.viewmodel.mastodon.AccountsVM;
|
||||||
|
@ -50,6 +57,33 @@ public class LoginActivity extends BaseActivity {
|
||||||
private final int PICK_IMPORT = 5557;
|
private final int PICK_IMPORT = 5557;
|
||||||
public static boolean requestedAdmin;
|
public static boolean requestedAdmin;
|
||||||
|
|
||||||
|
@SuppressLint("ApplySharedPref")
|
||||||
|
public static void proceedLogin(Activity activity, Account account) {
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
//update the database
|
||||||
|
new Account(activity).insertOrUpdate(account);
|
||||||
|
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||||
|
BaseMainActivity.currentToken = account.token;
|
||||||
|
BaseMainActivity.currentUserID = account.user_id;
|
||||||
|
BaseMainActivity.api = Account.API.MASTODON;
|
||||||
|
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||||
|
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||||
|
editor.putString(PREF_USER_TOKEN, account.token);
|
||||||
|
editor.commit();
|
||||||
|
//The user is now authenticated, it will be redirected to MainActivity
|
||||||
|
Runnable myRunnable = () -> {
|
||||||
|
Intent mainActivity = new Intent(activity, MainActivity.class);
|
||||||
|
activity.startActivity(mainActivity);
|
||||||
|
activity.finish();
|
||||||
|
};
|
||||||
|
mainHandler.post(myRunnable);
|
||||||
|
} catch (DBException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
private void manageItent(Intent intent) {
|
private void manageItent(Intent intent) {
|
||||||
|
|
||||||
if (intent != null && intent.getData() != null && intent.getData().toString().contains(REDIRECT_CONTENT_WEB + "?code=")) {
|
if (intent != null && intent.getData() != null && intent.getData().toString().contains(REDIRECT_CONTENT_WEB + "?code=")) {
|
||||||
|
@ -84,10 +118,10 @@ public class LoginActivity extends BaseActivity {
|
||||||
AdminVM adminVM = new ViewModelProvider(LoginActivity.this).get(AdminVM.class);
|
AdminVM adminVM = new ViewModelProvider(LoginActivity.this).get(AdminVM.class);
|
||||||
adminVM.getAccount(account.instance, account.token, account.user_id).observe(LoginActivity.this, adminAccount -> {
|
adminVM.getAccount(account.instance, account.token, account.user_id).observe(LoginActivity.this, adminAccount -> {
|
||||||
account.admin = adminAccount != null;
|
account.admin = adminAccount != null;
|
||||||
WebviewConnectActivity.proceedLogin(LoginActivity.this, account);
|
proceedLogin(LoginActivity.this, account);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
WebviewConnectActivity.proceedLogin(LoginActivity.this, account);
|
proceedLogin(LoginActivity.this, account);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -98,7 +132,6 @@ public class LoginActivity extends BaseActivity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onNewIntent(Intent intent) {
|
protected void onNewIntent(Intent intent) {
|
||||||
super.onNewIntent(intent);
|
super.onNewIntent(intent);
|
||||||
|
@ -129,9 +162,6 @@ public class LoginActivity extends BaseActivity {
|
||||||
public boolean onCreateOptionsMenu(@NotNull Menu menu) {
|
public boolean onCreateOptionsMenu(@NotNull Menu menu) {
|
||||||
// Inflate the menu; this adds items to the action bar if it is present.
|
// Inflate the menu; this adds items to the action bar if it is present.
|
||||||
getMenuInflater().inflate(R.menu.main_login, menu);
|
getMenuInflater().inflate(R.menu.main_login, menu);
|
||||||
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(LoginActivity.this);
|
|
||||||
boolean embedded_browser = sharedpreferences.getBoolean(getString(R.string.SET_EMBEDDED_BROWSER), true);
|
|
||||||
menu.findItem(R.id.action_custom_tabs).setChecked(!embedded_browser);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,13 +175,6 @@ public class LoginActivity extends BaseActivity {
|
||||||
if (id == R.id.action_proxy) {
|
if (id == R.id.action_proxy) {
|
||||||
Intent intent = new Intent(LoginActivity.this, ProxyActivity.class);
|
Intent intent = new Intent(LoginActivity.this, ProxyActivity.class);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
} else if (id == R.id.action_custom_tabs) {
|
|
||||||
item.setChecked(!item.isChecked());
|
|
||||||
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(LoginActivity.this);
|
|
||||||
SharedPreferences.Editor editor = sharedpreferences.edit();
|
|
||||||
editor.putBoolean(getString(R.string.SET_EMBEDDED_BROWSER), !item.isChecked());
|
|
||||||
editor.apply();
|
|
||||||
return false;
|
|
||||||
} else if (id == R.id.action_request_admin) {
|
} else if (id == R.id.action_request_admin) {
|
||||||
item.setChecked(!item.isChecked());
|
item.setChecked(!item.isChecked());
|
||||||
requestedAdmin = item.isChecked();
|
requestedAdmin = item.isChecked();
|
||||||
|
|
|
@ -1,252 +0,0 @@
|
||||||
package app.fedilab.android.activities;
|
|
||||||
/* Copyright 2021 Thomas Schneider
|
|
||||||
*
|
|
||||||
* This file is a part of Fedilab
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
|
||||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
|
||||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
||||||
* Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
|
||||||
* see <http://www.gnu.org/licenses>. */
|
|
||||||
|
|
||||||
|
|
||||||
import android.Manifest;
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.graphics.drawable.LayerDrawable;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import androidx.appcompat.app.ActionBar;
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.core.app.ActivityCompat;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import app.fedilab.android.R;
|
|
||||||
import app.fedilab.android.databinding.ActivityWebviewBinding;
|
|
||||||
import app.fedilab.android.helper.CountDrawable;
|
|
||||||
import app.fedilab.android.helper.Helper;
|
|
||||||
import app.fedilab.android.webview.CustomWebview;
|
|
||||||
import app.fedilab.android.webview.FedilabWebChromeClient;
|
|
||||||
import app.fedilab.android.webview.FedilabWebViewClient;
|
|
||||||
import es.dmoral.toasty.Toasty;
|
|
||||||
|
|
||||||
|
|
||||||
public class WebviewActivity extends BaseActivity {
|
|
||||||
|
|
||||||
|
|
||||||
private String url;
|
|
||||||
private boolean peertubeLink;
|
|
||||||
private CustomWebview webView;
|
|
||||||
private FedilabWebViewClient FedilabWebViewClient;
|
|
||||||
private ActivityWebviewBinding binding;
|
|
||||||
private Menu defaultMenu;
|
|
||||||
|
|
||||||
@SuppressLint("SetJavaScriptEnabled")
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
|
|
||||||
binding = ActivityWebviewBinding.inflate(getLayoutInflater());
|
|
||||||
View view = binding.getRoot();
|
|
||||||
setContentView(view);
|
|
||||||
setSupportActionBar(binding.toolbar);
|
|
||||||
ActionBar actionBar = getSupportActionBar();
|
|
||||||
if (actionBar != null) {
|
|
||||||
actionBar.setDisplayShowTitleEnabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getSupportActionBar() != null) {
|
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
|
||||||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
|
||||||
}
|
|
||||||
Bundle b = getIntent().getExtras();
|
|
||||||
if (b != null) {
|
|
||||||
url = b.getString("url", null);
|
|
||||||
peertubeLink = b.getBoolean("peertubeLink", false);
|
|
||||||
}
|
|
||||||
if (url == null)
|
|
||||||
finish();
|
|
||||||
if (getSupportActionBar() != null)
|
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
|
||||||
|
|
||||||
webView = Helper.initializeWebview(WebviewActivity.this, R.id.webview, null);
|
|
||||||
setTitle("");
|
|
||||||
|
|
||||||
webView.getSettings().setJavaScriptEnabled(true);
|
|
||||||
|
|
||||||
|
|
||||||
FedilabWebChromeClient FedilabWebChromeClient = new FedilabWebChromeClient(WebviewActivity.this, webView, binding.webviewContainer, binding.videoLayout);
|
|
||||||
FedilabWebChromeClient.setOnToggledFullscreen(fullscreen -> {
|
|
||||||
|
|
||||||
if (fullscreen) {
|
|
||||||
binding.videoLayout.setVisibility(View.VISIBLE);
|
|
||||||
WindowManager.LayoutParams attrs = getWindow().getAttributes();
|
|
||||||
attrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
|
|
||||||
attrs.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
|
|
||||||
getWindow().setAttributes(attrs);
|
|
||||||
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
|
|
||||||
} else {
|
|
||||||
WindowManager.LayoutParams attrs = getWindow().getAttributes();
|
|
||||||
attrs.flags &= ~WindowManager.LayoutParams.FLAG_FULLSCREEN;
|
|
||||||
attrs.flags &= ~WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
|
|
||||||
getWindow().setAttributes(attrs);
|
|
||||||
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
|
|
||||||
binding.videoLayout.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
webView.setWebChromeClient(FedilabWebChromeClient);
|
|
||||||
FedilabWebViewClient = new FedilabWebViewClient(WebviewActivity.this);
|
|
||||||
webView.setWebViewClient(FedilabWebViewClient);
|
|
||||||
webView.setDownloadListener((url, userAgent, contentDisposition, mimetype, contentLength) -> {
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
|
||||||
if (ContextCompat.checkSelfPermission(WebviewActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(WebviewActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
|
||||||
ActivityCompat.requestPermissions(WebviewActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, Helper.EXTERNAL_STORAGE_REQUEST_CODE);
|
|
||||||
} else {
|
|
||||||
Helper.manageDownloads(WebviewActivity.this, url);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Helper.manageDownloads(WebviewActivity.this, url);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (!url.toLowerCase().startsWith("http://") && !url.toLowerCase().startsWith("https://"))
|
|
||||||
url = "http://" + url;
|
|
||||||
webView.loadUrl(url);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setCount(Context context, String count) {
|
|
||||||
if (defaultMenu != null && !peertubeLink) {
|
|
||||||
MenuItem menuItem = defaultMenu.findItem(R.id.action_block);
|
|
||||||
LayerDrawable icon = (LayerDrawable) menuItem.getIcon();
|
|
||||||
|
|
||||||
CountDrawable badge;
|
|
||||||
|
|
||||||
// Reuse drawable if possible
|
|
||||||
Drawable reuse = icon.findDrawableByLayerId(R.id.ic_block_count);
|
|
||||||
if (reuse instanceof CountDrawable) {
|
|
||||||
badge = (CountDrawable) reuse;
|
|
||||||
} else {
|
|
||||||
badge = new CountDrawable(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
badge.setCount(count);
|
|
||||||
icon.mutate();
|
|
||||||
icon.setDrawableByLayerId(R.id.ic_block_count, badge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
|
||||||
if (!peertubeLink)
|
|
||||||
setCount(WebviewActivity.this, "0");
|
|
||||||
defaultMenu = menu;
|
|
||||||
return super.onPrepareOptionsMenu(menu);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onCreateOptionsMenu(@NotNull Menu menu) {
|
|
||||||
getMenuInflater().inflate(R.menu.main_webview, menu);
|
|
||||||
defaultMenu = menu;
|
|
||||||
if (peertubeLink) {
|
|
||||||
menu.findItem(R.id.action_go).setVisible(false);
|
|
||||||
menu.findItem(R.id.action_block).setVisible(false);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
int itemId = item.getItemId();
|
|
||||||
if (itemId == android.R.id.home) {
|
|
||||||
finish();
|
|
||||||
return true;
|
|
||||||
} else if (itemId == R.id.action_block) {
|
|
||||||
|
|
||||||
|
|
||||||
List<String> domains = FedilabWebViewClient.getDomains();
|
|
||||||
|
|
||||||
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(WebviewActivity.this, R.layout.domains_blocked);
|
|
||||||
arrayAdapter.addAll(domains);
|
|
||||||
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(WebviewActivity.this, Helper.dialogStyle());
|
|
||||||
builder.setTitle(R.string.list_of_blocked_domains);
|
|
||||||
|
|
||||||
builder.setNegativeButton(R.string.close, (dialog, which) -> dialog.dismiss());
|
|
||||||
|
|
||||||
builder.setAdapter(arrayAdapter, (dialog, which) -> {
|
|
||||||
String strName = arrayAdapter.getItem(which);
|
|
||||||
assert strName != null;
|
|
||||||
Toasty.info(WebviewActivity.this, strName, Toast.LENGTH_LONG).show();
|
|
||||||
});
|
|
||||||
builder.show();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} else if (itemId == R.id.action_go) {
|
|
||||||
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
|
||||||
try {
|
|
||||||
startActivity(browserIntent);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Toasty.error(WebviewActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUrl(String newUrl) {
|
|
||||||
this.url = newUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
if (webView != null)
|
|
||||||
webView.onPause();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
if (webView != null)
|
|
||||||
webView.onResume();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBackPressed() {
|
|
||||||
if (webView.canGoBack()) {
|
|
||||||
webView.goBack();
|
|
||||||
} else {
|
|
||||||
super.onBackPressed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
if (webView != null)
|
|
||||||
webView.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,325 +0,0 @@
|
||||||
/* Copyright 2021 Thomas Schneider
|
|
||||||
*
|
|
||||||
* This file is a part of Fedilab
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
|
||||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
|
||||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
||||||
* Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
|
||||||
* see <http://www.gnu.org/licenses>. */
|
|
||||||
|
|
||||||
package app.fedilab.android.activities;
|
|
||||||
|
|
||||||
|
|
||||||
import static app.fedilab.android.activities.LoginActivity.apiLogin;
|
|
||||||
import static app.fedilab.android.activities.LoginActivity.client_idLogin;
|
|
||||||
import static app.fedilab.android.activities.LoginActivity.client_secretLogin;
|
|
||||||
import static app.fedilab.android.activities.LoginActivity.currentInstanceLogin;
|
|
||||||
import static app.fedilab.android.activities.LoginActivity.requestedAdmin;
|
|
||||||
import static app.fedilab.android.activities.LoginActivity.softwareLogin;
|
|
||||||
import static app.fedilab.android.helper.Helper.PREF_USER_TOKEN;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.Looper;
|
|
||||||
import android.view.View;
|
|
||||||
import android.webkit.CookieManager;
|
|
||||||
import android.webkit.CookieSyncManager;
|
|
||||||
import android.webkit.WebChromeClient;
|
|
||||||
import android.webkit.WebResourceRequest;
|
|
||||||
import android.webkit.WebResourceResponse;
|
|
||||||
import android.webkit.WebView;
|
|
||||||
import android.webkit.WebViewClient;
|
|
||||||
import android.widget.ProgressBar;
|
|
||||||
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
|
||||||
import androidx.preference.PreferenceManager;
|
|
||||||
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
|
|
||||||
import app.fedilab.android.BaseMainActivity;
|
|
||||||
import app.fedilab.android.R;
|
|
||||||
import app.fedilab.android.client.entities.app.Account;
|
|
||||||
import app.fedilab.android.databinding.ActivityWebviewConnectBinding;
|
|
||||||
import app.fedilab.android.exception.DBException;
|
|
||||||
import app.fedilab.android.helper.Helper;
|
|
||||||
import app.fedilab.android.viewmodel.mastodon.AccountsVM;
|
|
||||||
import app.fedilab.android.viewmodel.mastodon.AdminVM;
|
|
||||||
import app.fedilab.android.viewmodel.mastodon.OauthVM;
|
|
||||||
import es.dmoral.toasty.Toasty;
|
|
||||||
|
|
||||||
|
|
||||||
public class WebviewConnectActivity extends BaseActivity {
|
|
||||||
|
|
||||||
|
|
||||||
private ActivityWebviewConnectBinding binding;
|
|
||||||
private AlertDialog alert;
|
|
||||||
private String login_url;
|
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public static void clearCookies(Context context) {
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
|
|
||||||
CookieManager.getInstance().removeAllCookies(null);
|
|
||||||
CookieManager.getInstance().flush();
|
|
||||||
} else {
|
|
||||||
CookieSyncManager cookieSyncMngr = CookieSyncManager.createInstance(context);
|
|
||||||
cookieSyncMngr.startSync();
|
|
||||||
CookieManager cookieManager = CookieManager.getInstance();
|
|
||||||
cookieManager.removeAllCookie();
|
|
||||||
cookieManager.removeSessionCookie();
|
|
||||||
cookieSyncMngr.stopSync();
|
|
||||||
cookieSyncMngr.sync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("ApplySharedPref")
|
|
||||||
public static void proceedLogin(Activity activity, Account account) {
|
|
||||||
new Thread(() -> {
|
|
||||||
try {
|
|
||||||
//update the database
|
|
||||||
new Account(activity).insertOrUpdate(account);
|
|
||||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
|
||||||
BaseMainActivity.currentToken = account.token;
|
|
||||||
BaseMainActivity.currentUserID = account.user_id;
|
|
||||||
BaseMainActivity.api = Account.API.MASTODON;
|
|
||||||
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(activity);
|
|
||||||
SharedPreferences.Editor editor = sharedpreferences.edit();
|
|
||||||
editor.putString(PREF_USER_TOKEN, account.token);
|
|
||||||
editor.commit();
|
|
||||||
//The user is now authenticated, it will be redirected to MainActivity
|
|
||||||
Runnable myRunnable = () -> {
|
|
||||||
Intent mainActivity = new Intent(activity, MainActivity.class);
|
|
||||||
activity.startActivity(mainActivity);
|
|
||||||
activity.finish();
|
|
||||||
};
|
|
||||||
mainHandler.post(myRunnable);
|
|
||||||
} catch (DBException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("SetJavaScriptEnabled")
|
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
|
|
||||||
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(WebviewConnectActivity.this);
|
|
||||||
|
|
||||||
binding = ActivityWebviewConnectBinding.inflate(getLayoutInflater());
|
|
||||||
View rootView = binding.getRoot();
|
|
||||||
setContentView(rootView);
|
|
||||||
|
|
||||||
Bundle b = getIntent().getExtras();
|
|
||||||
if (b != null) {
|
|
||||||
login_url = b.getString("login_url");
|
|
||||||
requestedAdmin = b.getBoolean("requestedAdmin", false);
|
|
||||||
}
|
|
||||||
if (login_url == null)
|
|
||||||
finish();
|
|
||||||
|
|
||||||
clearCookies(WebviewConnectActivity.this);
|
|
||||||
binding.webviewConnect.getSettings().setJavaScriptEnabled(true);
|
|
||||||
// String user_agent = sharedpreferences.getString(getString(R.string.SET_CUSTOM_USER_AGENT), Helper.USER_AGENT);
|
|
||||||
// binding.webviewConnect.getSettings().setUserAgentString(user_agent);
|
|
||||||
binding.webviewConnect.getSettings().setDomStorageEnabled(true);
|
|
||||||
CookieManager.getInstance().setAcceptThirdPartyCookies(binding.webviewConnect, true);
|
|
||||||
|
|
||||||
|
|
||||||
final ProgressBar pbar = findViewById(R.id.progress_bar);
|
|
||||||
binding.webviewConnect.setWebChromeClient(new WebChromeClient() {
|
|
||||||
@Override
|
|
||||||
public void onProgressChanged(WebView view, int progress) {
|
|
||||||
if (progress < 100 && pbar.getVisibility() == ProgressBar.GONE) {
|
|
||||||
pbar.setVisibility(ProgressBar.VISIBLE);
|
|
||||||
}
|
|
||||||
pbar.setProgress(progress);
|
|
||||||
if (progress == 100) {
|
|
||||||
pbar.setVisibility(ProgressBar.GONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
binding.webviewConnect.setWebViewClient(new WebViewClient() {
|
|
||||||
|
|
||||||
/* @Override
|
|
||||||
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
|
|
||||||
String x_xsrf_token = null;
|
|
||||||
String x_csrf_token = null;
|
|
||||||
if (request.getUrl().toString().contains("accounts/verify_credentials")) {
|
|
||||||
|
|
||||||
String cookies = CookieManager.getInstance().getCookie(request.getUrl().toString());
|
|
||||||
|
|
||||||
Map<String, String> requestHeaders = request.getRequestHeaders();
|
|
||||||
Iterator<Map.Entry<String, String>> it = requestHeaders.entrySet().iterator();
|
|
||||||
while (it.hasNext()) {
|
|
||||||
Map.Entry<String, String> pair = it.next();
|
|
||||||
if (pair.getKey().compareTo("X-XSRF-TOKEN") == 0) {
|
|
||||||
x_xsrf_token = pair.getValue();
|
|
||||||
}
|
|
||||||
if (pair.getKey().compareTo("X-CSRF-TOKEN") == 0) {
|
|
||||||
x_csrf_token = pair.getValue();
|
|
||||||
}
|
|
||||||
it.remove();
|
|
||||||
}
|
|
||||||
if (x_xsrf_token != null && x_csrf_token != null) {
|
|
||||||
String finalX_xsrf_token = x_xsrf_token;
|
|
||||||
String finalX_csrf_token = x_csrf_token;
|
|
||||||
new Handler(Looper.getMainLooper()).post(() -> {
|
|
||||||
view.stopLoading();
|
|
||||||
SharedPreferences sharedpreferences1 = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
|
||||||
SharedPreferences.Editor editor = sharedpreferences1.edit();
|
|
||||||
String token = "X-XSRF-TOKEN= " + finalX_xsrf_token + ";X-CSRF-TOKEN= " + finalX_csrf_token + "|" + cookies;
|
|
||||||
editor.putString(Helper.PREF_KEY_OAUTH_TOKEN, token);
|
|
||||||
editor.commit();
|
|
||||||
view.setVisibility(View.GONE);
|
|
||||||
//Update the account with the token;
|
|
||||||
new UpdateAccountInfoAsyncTask(WebviewConnectActivity.this, token, clientId, clientSecret, null, instance, social);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super.shouldInterceptRequest(view, request);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
|
|
||||||
if (request.getUrl().toString().contains(currentInstanceLogin + "/api/v1")) {
|
|
||||||
request.getRequestHeaders();
|
|
||||||
Map<String, String> requestHeaders = request.getRequestHeaders();
|
|
||||||
Iterator<Map.Entry<String, String>> it = requestHeaders.entrySet().iterator();
|
|
||||||
String token = null;
|
|
||||||
while (it.hasNext()) {
|
|
||||||
Map.Entry<String, String> pair = it.next();
|
|
||||||
if (pair.getKey().equals("Authorization")) {
|
|
||||||
token = pair.getValue();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
it.remove();
|
|
||||||
}
|
|
||||||
if (token != null) {
|
|
||||||
AccountsVM accountsVM = new ViewModelProvider(WebviewConnectActivity.this).get(AccountsVM.class);
|
|
||||||
String finalToken = token;
|
|
||||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
|
||||||
Runnable myRunnable = () -> {
|
|
||||||
accountsVM.getConnectedAccount(currentInstanceLogin, finalToken).observe(WebviewConnectActivity.this, mastodonAccount -> {
|
|
||||||
if (mastodonAccount != null) {
|
|
||||||
Account account = new Account();
|
|
||||||
account.client_id = client_idLogin;
|
|
||||||
account.client_secret = client_secretLogin;
|
|
||||||
account.token = finalToken;
|
|
||||||
account.api = apiLogin;
|
|
||||||
account.software = softwareLogin;
|
|
||||||
account.instance = currentInstanceLogin;
|
|
||||||
account.mastodon_account = mastodonAccount;
|
|
||||||
account.user_id = mastodonAccount.id;
|
|
||||||
//We check if user have really moderator rights
|
|
||||||
if (requestedAdmin) {
|
|
||||||
AdminVM adminVM = new ViewModelProvider(WebviewConnectActivity.this).get(AdminVM.class);
|
|
||||||
adminVM.getAccount(account.instance, account.token, account.user_id).observe(WebviewConnectActivity.this, adminAccount -> {
|
|
||||||
account.admin = adminAccount != null;
|
|
||||||
proceedLogin(WebviewConnectActivity.this, account);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
proceedLogin(WebviewConnectActivity.this, account);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Toasty.error(WebviewConnectActivity.this, getString(R.string.toast_error), Toasty.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
mainHandler.post(myRunnable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super.shouldInterceptRequest(view, request);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
|
||||||
super.shouldOverrideUrlLoading(view, url);
|
|
||||||
if (url.contains(Helper.REDIRECT_CONTENT_WEB)) {
|
|
||||||
Matcher matcher = Helper.codePattern.matcher(url);
|
|
||||||
if (!matcher.find()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
String code = matcher.group(1);
|
|
||||||
OauthVM oauthVM = new ViewModelProvider(WebviewConnectActivity.this).get(OauthVM.class);
|
|
||||||
//API call to get the user token
|
|
||||||
String scope = requestedAdmin ? Helper.OAUTH_SCOPES_ADMIN : Helper.OAUTH_SCOPES;
|
|
||||||
oauthVM.createToken(currentInstanceLogin, "authorization_code", client_idLogin, client_secretLogin, Helper.REDIRECT_CONTENT_WEB, scope, code)
|
|
||||||
.observe(WebviewConnectActivity.this, tokenObj -> {
|
|
||||||
if (tokenObj != null) {
|
|
||||||
Account account = new Account();
|
|
||||||
account.client_id = client_idLogin;
|
|
||||||
account.client_secret = client_secretLogin;
|
|
||||||
account.token = tokenObj.token_type + " " + tokenObj.access_token;
|
|
||||||
account.api = apiLogin;
|
|
||||||
account.software = softwareLogin;
|
|
||||||
account.instance = currentInstanceLogin;
|
|
||||||
//API call to retrieve account information for the new token
|
|
||||||
AccountsVM accountsVM = new ViewModelProvider(WebviewConnectActivity.this).get(AccountsVM.class);
|
|
||||||
accountsVM.getConnectedAccount(currentInstanceLogin, account.token).observe(WebviewConnectActivity.this, mastodonAccount -> {
|
|
||||||
if (mastodonAccount != null) {
|
|
||||||
account.mastodon_account = mastodonAccount;
|
|
||||||
account.user_id = mastodonAccount.id;
|
|
||||||
//We check if user have really moderator rights
|
|
||||||
if (requestedAdmin) {
|
|
||||||
AdminVM adminVM = new ViewModelProvider(WebviewConnectActivity.this).get(AdminVM.class);
|
|
||||||
adminVM.getAccount(account.instance, account.token, account.user_id).observe(WebviewConnectActivity.this, adminAccount -> {
|
|
||||||
account.admin = adminAccount != null;
|
|
||||||
proceedLogin(WebviewConnectActivity.this, account);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
proceedLogin(WebviewConnectActivity.this, account);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Toasty.error(WebviewConnectActivity.this, getString(R.string.toast_error), Toasty.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Toasty.error(WebviewConnectActivity.this, getString(R.string.toast_token), Toasty.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
binding.webviewConnect.loadUrl(login_url);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBackPressed() {
|
|
||||||
if (binding.webviewConnect.canGoBack()) {
|
|
||||||
binding.webviewConnect.goBack();
|
|
||||||
} else {
|
|
||||||
super.onBackPressed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
if (alert != null) {
|
|
||||||
alert.dismiss();
|
|
||||||
alert = null;
|
|
||||||
}
|
|
||||||
binding.webviewConnect.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -18,7 +18,6 @@ import static android.content.Context.DOWNLOAD_SERVICE;
|
||||||
import static app.fedilab.android.BaseMainActivity.currentAccount;
|
import static app.fedilab.android.BaseMainActivity.currentAccount;
|
||||||
import static app.fedilab.android.activities.BaseActivity.currentThemeId;
|
import static app.fedilab.android.activities.BaseActivity.currentThemeId;
|
||||||
import static app.fedilab.android.helper.LogoHelper.getNotificationIcon;
|
import static app.fedilab.android.helper.LogoHelper.getNotificationIcon;
|
||||||
import static app.fedilab.android.webview.ProxyHelper.setProxy;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
@ -68,11 +67,8 @@ import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
import android.webkit.CookieManager;
|
|
||||||
import android.webkit.MimeTypeMap;
|
import android.webkit.MimeTypeMap;
|
||||||
import android.webkit.URLUtil;
|
import android.webkit.URLUtil;
|
||||||
import android.webkit.WebChromeClient;
|
|
||||||
import android.webkit.WebSettings;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
@ -152,7 +148,6 @@ import app.fedilab.android.activities.ComposeActivity;
|
||||||
import app.fedilab.android.activities.LoginActivity;
|
import app.fedilab.android.activities.LoginActivity;
|
||||||
import app.fedilab.android.activities.MainActivity;
|
import app.fedilab.android.activities.MainActivity;
|
||||||
import app.fedilab.android.activities.ProfileActivity;
|
import app.fedilab.android.activities.ProfileActivity;
|
||||||
import app.fedilab.android.activities.WebviewActivity;
|
|
||||||
import app.fedilab.android.broadcastreceiver.ToastMessage;
|
import app.fedilab.android.broadcastreceiver.ToastMessage;
|
||||||
import app.fedilab.android.client.entities.api.Attachment;
|
import app.fedilab.android.client.entities.api.Attachment;
|
||||||
import app.fedilab.android.client.entities.api.Status;
|
import app.fedilab.android.client.entities.api.Status;
|
||||||
|
@ -169,7 +164,6 @@ import app.fedilab.android.viewmodel.mastodon.AccountsVM;
|
||||||
import app.fedilab.android.viewmodel.mastodon.OauthVM;
|
import app.fedilab.android.viewmodel.mastodon.OauthVM;
|
||||||
import app.fedilab.android.watermark.androidwm.WatermarkBuilder;
|
import app.fedilab.android.watermark.androidwm.WatermarkBuilder;
|
||||||
import app.fedilab.android.watermark.androidwm.bean.WatermarkText;
|
import app.fedilab.android.watermark.androidwm.bean.WatermarkText;
|
||||||
import app.fedilab.android.webview.CustomWebview;
|
|
||||||
import es.dmoral.toasty.Toasty;
|
import es.dmoral.toasty.Toasty;
|
||||||
import okhttp3.MediaType;
|
import okhttp3.MediaType;
|
||||||
import okhttp3.MultipartBody;
|
import okhttp3.MultipartBody;
|
||||||
|
@ -412,60 +406,6 @@ public class Helper {
|
||||||
patternHashMap = Collections.unmodifiableMap(aMap);
|
patternHashMap = Collections.unmodifiableMap(aMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
|
||||||
* Initialize a CustomWebview
|
|
||||||
* @param activity Activity - activity containing the webview
|
|
||||||
* @param webviewId int - webview id
|
|
||||||
* @param rootView View - the root view that will contain the webview
|
|
||||||
* @return {@link CustomWebview}
|
|
||||||
*/
|
|
||||||
public static CustomWebview initializeWebview(Activity activity, int webviewId, View rootView) {
|
|
||||||
|
|
||||||
CustomWebview webView;
|
|
||||||
if (rootView == null) {
|
|
||||||
webView = activity.findViewById(webviewId);
|
|
||||||
} else {
|
|
||||||
webView = rootView.findViewById(webviewId);
|
|
||||||
}
|
|
||||||
final SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(activity);
|
|
||||||
boolean javascript = sharedpreferences.getBoolean(activity.getString(R.string.SET_JAVASCRIPT), true);
|
|
||||||
|
|
||||||
webView.getSettings().setJavaScriptEnabled(javascript);
|
|
||||||
webView.getSettings().setUseWideViewPort(true);
|
|
||||||
webView.getSettings().setLoadWithOverviewMode(true);
|
|
||||||
webView.getSettings().setSupportZoom(true);
|
|
||||||
webView.getSettings().setDisplayZoomControls(false);
|
|
||||||
webView.getSettings().setBuiltInZoomControls(true);
|
|
||||||
webView.getSettings().setAllowContentAccess(true);
|
|
||||||
webView.getSettings().setSaveFormData(true);
|
|
||||||
webView.getSettings().setLoadsImagesAutomatically(true);
|
|
||||||
webView.getSettings().setSupportMultipleWindows(false);
|
|
||||||
webView.getSettings().setMediaPlaybackRequiresUserGesture(true);
|
|
||||||
//String user_agent = sharedpreferences.getString(activity.getString(R.string.SET_CUSTOM_USER_AGENT), USER_AGENT);
|
|
||||||
// webView.getSettings().setUserAgentString(user_agent);
|
|
||||||
boolean cookies = sharedpreferences.getBoolean(activity.getString(R.string.SET_COOKIES), false);
|
|
||||||
CookieManager cookieManager = CookieManager.getInstance();
|
|
||||||
cookieManager.setAcceptThirdPartyCookies(webView, cookies);
|
|
||||||
webView.setBackgroundColor(Color.TRANSPARENT);
|
|
||||||
webView.getSettings().setAppCacheEnabled(true);
|
|
||||||
webView.getSettings().setDatabaseEnabled(true);
|
|
||||||
webView.getSettings().setDomStorageEnabled(true);
|
|
||||||
webView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
|
|
||||||
webView.setWebChromeClient(new WebChromeClient() {
|
|
||||||
@Override
|
|
||||||
public Bitmap getDefaultVideoPoster() {
|
|
||||||
return Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
boolean proxyEnabled = sharedpreferences.getBoolean(activity.getString(R.string.SET_PROXY_ENABLED), false);
|
|
||||||
if (proxyEnabled) {
|
|
||||||
String host = sharedpreferences.getString(activity.getString(R.string.SET_PROXY_HOST), "127.0.0.1");
|
|
||||||
int port = sharedpreferences.getInt(activity.getString(R.string.SET_PROXY_PORT), 8118);
|
|
||||||
setProxy(activity, webView, host, port, WebviewActivity.class.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
return webView;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manage downloads with URLs
|
* Manage downloads with URLs
|
||||||
|
@ -719,19 +659,6 @@ public class Helper {
|
||||||
if (url == null) {
|
if (url == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
|
|
||||||
boolean embedded_browser = sharedpreferences.getBoolean(context.getString(R.string.SET_EMBEDDED_BROWSER), true);
|
|
||||||
if (embedded_browser && !url.toLowerCase().startsWith("gemini://")) {
|
|
||||||
Intent intent = new Intent(context, WebviewActivity.class);
|
|
||||||
Bundle b = new Bundle();
|
|
||||||
String finalUrl = url;
|
|
||||||
if (!url.toLowerCase().startsWith("http://") && !url.toLowerCase().startsWith("https://"))
|
|
||||||
finalUrl = "http://" + url;
|
|
||||||
b.putString("url", finalUrl);
|
|
||||||
intent.putExtras(b);
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
context.startActivity(intent);
|
|
||||||
} else {
|
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
if (!url.toLowerCase().startsWith("http://") && !url.toLowerCase().startsWith("https://") && !url.toLowerCase().startsWith("gemini://")) {
|
if (!url.toLowerCase().startsWith("http://") && !url.toLowerCase().startsWith("https://") && !url.toLowerCase().startsWith("gemini://")) {
|
||||||
|
@ -744,7 +671,6 @@ public class Helper {
|
||||||
Toasty.error(context, context.getString(R.string.toast_error), Toast.LENGTH_LONG).show();
|
Toasty.error(context, context.getString(R.string.toast_error), Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform URLs to privacy frontend
|
* Transform URLs to privacy frontend
|
||||||
|
|
|
@ -50,7 +50,6 @@ import java.net.URLEncoder;
|
||||||
import app.fedilab.android.BaseMainActivity;
|
import app.fedilab.android.BaseMainActivity;
|
||||||
import app.fedilab.android.R;
|
import app.fedilab.android.R;
|
||||||
import app.fedilab.android.activities.ProxyActivity;
|
import app.fedilab.android.activities.ProxyActivity;
|
||||||
import app.fedilab.android.activities.WebviewConnectActivity;
|
|
||||||
import app.fedilab.android.client.entities.app.Account;
|
import app.fedilab.android.client.entities.app.Account;
|
||||||
import app.fedilab.android.client.entities.app.InstanceSocial;
|
import app.fedilab.android.client.entities.app.InstanceSocial;
|
||||||
import app.fedilab.android.databinding.FragmentLoginMainBinding;
|
import app.fedilab.android.databinding.FragmentLoginMainBinding;
|
||||||
|
@ -184,36 +183,14 @@ public class FragmentLoginMain extends Fragment {
|
||||||
PopupMenu popupMenu = new PopupMenu(requireActivity(), binding.menuIcon);
|
PopupMenu popupMenu = new PopupMenu(requireActivity(), binding.menuIcon);
|
||||||
MenuInflater menuInflater = popupMenu.getMenuInflater();
|
MenuInflater menuInflater = popupMenu.getMenuInflater();
|
||||||
menuInflater.inflate(R.menu.main_login, popupMenu.getMenu());
|
menuInflater.inflate(R.menu.main_login, popupMenu.getMenu());
|
||||||
MenuItem customTabItem = popupMenu.getMenu().findItem(R.id.action_custom_tabs);
|
|
||||||
MenuItem adminTabItem = popupMenu.getMenu().findItem(R.id.action_request_admin);
|
MenuItem adminTabItem = popupMenu.getMenu().findItem(R.id.action_request_admin);
|
||||||
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity());
|
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity());
|
||||||
boolean embedded_browser = sharedpreferences.getBoolean(getString(R.string.SET_EMBEDDED_BROWSER), true);
|
|
||||||
customTabItem.setChecked(!embedded_browser);
|
|
||||||
adminTabItem.setChecked(requestedAdmin);
|
adminTabItem.setChecked(requestedAdmin);
|
||||||
popupMenu.setOnMenuItemClickListener(item -> {
|
popupMenu.setOnMenuItemClickListener(item -> {
|
||||||
int itemId = item.getItemId();
|
int itemId = item.getItemId();
|
||||||
if (itemId == R.id.action_proxy) {
|
if (itemId == R.id.action_proxy) {
|
||||||
Intent intent = new Intent(requireActivity(), ProxyActivity.class);
|
Intent intent = new Intent(requireActivity(), ProxyActivity.class);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
} else if (itemId == R.id.action_custom_tabs) {
|
|
||||||
boolean checked = !embedded_browser;
|
|
||||||
item.setChecked(!item.isChecked());
|
|
||||||
SharedPreferences.Editor editor = sharedpreferences.edit();
|
|
||||||
editor.putBoolean(getString(R.string.SET_EMBEDDED_BROWSER), checked);
|
|
||||||
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
|
|
||||||
item.setActionView(new View(requireContext()));
|
|
||||||
item.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onMenuItemActionExpand(MenuItem item) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onMenuItemActionCollapse(MenuItem item) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
editor.apply();
|
|
||||||
} else if (itemId == R.id.action_request_admin) {
|
} else if (itemId == R.id.action_request_admin) {
|
||||||
|
|
||||||
item.setChecked(!item.isChecked());
|
item.setChecked(!item.isChecked());
|
||||||
|
@ -267,15 +244,6 @@ public class FragmentLoginMain extends Fragment {
|
||||||
client_idLogin = app.client_id;
|
client_idLogin = app.client_id;
|
||||||
client_secretLogin = app.client_secret;
|
client_secretLogin = app.client_secret;
|
||||||
String redirectUrl = MastodonHelper.authorizeURL(currentInstanceLogin, client_idLogin, requestedAdmin);
|
String redirectUrl = MastodonHelper.authorizeURL(currentInstanceLogin, client_idLogin, requestedAdmin);
|
||||||
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity());
|
|
||||||
boolean embedded_browser = sharedpreferences.getBoolean(getString(R.string.SET_EMBEDDED_BROWSER), true);
|
|
||||||
if (embedded_browser) {
|
|
||||||
Intent i = new Intent(requireActivity(), WebviewConnectActivity.class);
|
|
||||||
i.putExtra("login_url", redirectUrl);
|
|
||||||
i.putExtra("requestedAdmin", requestedAdmin);
|
|
||||||
startActivity(i);
|
|
||||||
requireActivity().finish();
|
|
||||||
} else {
|
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
intent.setData(Uri.parse(redirectUrl));
|
intent.setData(Uri.parse(redirectUrl));
|
||||||
|
@ -284,8 +252,6 @@ public class FragmentLoginMain extends Fragment {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Toasty.error(requireActivity(), getString(R.string.toast_error), Toast.LENGTH_LONG).show();
|
Toasty.error(requireActivity(), getString(R.string.toast_error), Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Toasty.error(requireActivity(), getString(R.string.client_error), Toasty.LENGTH_SHORT).show();
|
Toasty.error(requireActivity(), getString(R.string.client_error), Toasty.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.ViewTreeObserver;
|
import android.view.ViewTreeObserver;
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
@ -53,9 +52,6 @@ import app.fedilab.android.databinding.FragmentSlideMediaBinding;
|
||||||
import app.fedilab.android.helper.CacheDataSourceFactory;
|
import app.fedilab.android.helper.CacheDataSourceFactory;
|
||||||
import app.fedilab.android.helper.Helper;
|
import app.fedilab.android.helper.Helper;
|
||||||
import app.fedilab.android.viewmodel.mastodon.TimelinesVM;
|
import app.fedilab.android.viewmodel.mastodon.TimelinesVM;
|
||||||
import app.fedilab.android.webview.CustomWebview;
|
|
||||||
import app.fedilab.android.webview.FedilabWebChromeClient;
|
|
||||||
import app.fedilab.android.webview.FedilabWebViewClient;
|
|
||||||
|
|
||||||
|
|
||||||
public class FragmentMedia extends Fragment {
|
public class FragmentMedia extends Fragment {
|
||||||
|
@ -67,7 +63,6 @@ public class FragmentMedia extends Fragment {
|
||||||
private boolean canSwipe;
|
private boolean canSwipe;
|
||||||
private Attachment attachment;
|
private Attachment attachment;
|
||||||
private boolean swipeEnabled;
|
private boolean swipeEnabled;
|
||||||
private CustomWebview webview_video;
|
|
||||||
private FragmentSlideMediaBinding binding;
|
private FragmentSlideMediaBinding binding;
|
||||||
|
|
||||||
|
|
||||||
|
@ -90,7 +85,6 @@ public class FragmentMedia extends Fragment {
|
||||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
swipeEnabled = true;
|
swipeEnabled = true;
|
||||||
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity());
|
|
||||||
|
|
||||||
url = attachment.url;
|
url = attachment.url;
|
||||||
binding.mediaPicture.setOnMatrixChangeListener(rect -> {
|
binding.mediaPicture.setOnMatrixChangeListener(rect -> {
|
||||||
|
@ -218,39 +212,6 @@ public class FragmentMedia extends Fragment {
|
||||||
loadVideo(url, type);
|
loadVideo(url, type);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "web":
|
|
||||||
binding.loader.setVisibility(View.GONE);
|
|
||||||
binding.mediaPicture.setVisibility(View.GONE);
|
|
||||||
webview_video = Helper.initializeWebview(requireActivity(), R.id.webview_video, binding.getRoot());
|
|
||||||
webview_video.setVisibility(View.VISIBLE);
|
|
||||||
FedilabWebChromeClient fedilabWebChromeClient = new FedilabWebChromeClient(requireActivity(), webview_video, binding.mainMediaFrame, binding.videoLayout);
|
|
||||||
fedilabWebChromeClient.setOnToggledFullscreen(fullscreen -> {
|
|
||||||
if (fullscreen) {
|
|
||||||
binding.videoLayout.setVisibility(View.VISIBLE);
|
|
||||||
WindowManager.LayoutParams attrs = (requireActivity()).getWindow().getAttributes();
|
|
||||||
attrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
|
|
||||||
attrs.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
|
|
||||||
(requireActivity()).getWindow().setAttributes(attrs);
|
|
||||||
(requireActivity()).getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
|
|
||||||
} else {
|
|
||||||
WindowManager.LayoutParams attrs = (requireActivity()).getWindow().getAttributes();
|
|
||||||
attrs.flags &= ~WindowManager.LayoutParams.FLAG_FULLSCREEN;
|
|
||||||
attrs.flags &= ~WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
|
|
||||||
(requireActivity()).getWindow().setAttributes(attrs);
|
|
||||||
(requireActivity()).getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
|
|
||||||
binding.videoLayout.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
webview_video.getSettings().setAllowFileAccess(true);
|
|
||||||
webview_video.setWebChromeClient(fedilabWebChromeClient);
|
|
||||||
webview_video.getSettings().setDomStorageEnabled(true);
|
|
||||||
webview_video.getSettings().setAppCacheEnabled(true);
|
|
||||||
// String user_agent = sharedpreferences.getString(getString(R.string.SET_CUSTOM_USER_AGENT), Helper.USER_AGENT);
|
|
||||||
// webview_video.getSettings().setUserAgentString(user_agent);
|
|
||||||
webview_video.getSettings().setMediaPlaybackRequiresUserGesture(false);
|
|
||||||
webview_video.setWebViewClient(new FedilabWebViewClient(requireActivity()));
|
|
||||||
webview_video.loadUrl(attachment.url);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,9 +259,6 @@ public class FragmentMedia extends Fragment {
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
player.setPlayWhenReady(false);
|
player.setPlayWhenReady(false);
|
||||||
}
|
}
|
||||||
if (webview_video != null) {
|
|
||||||
webview_video.onPause();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,9 +271,6 @@ public class FragmentMedia extends Fragment {
|
||||||
}
|
}
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
}
|
}
|
||||||
if (webview_video != null) {
|
|
||||||
webview_video.destroy();
|
|
||||||
}
|
|
||||||
if (timer != null) {
|
if (timer != null) {
|
||||||
timer.cancel();
|
timer.cancel();
|
||||||
timer = null;
|
timer = null;
|
||||||
|
@ -328,11 +283,6 @@ public class FragmentMedia extends Fragment {
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
player.setPlayWhenReady(true);
|
player.setPlayWhenReady(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (webview_video != null) {
|
|
||||||
webview_video.onResume();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scheduleStartPostponedTransition(final ImageView imageView) {
|
private void scheduleStartPostponedTransition(final ImageView imageView) {
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
package app.fedilab.android.webview;
|
|
||||||
/* Copyright 2021 Thomas Schneider
|
|
||||||
*
|
|
||||||
* This file is a part of Fedilab
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
|
||||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
|
||||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
||||||
* Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
|
||||||
* see <http://www.gnu.org/licenses>. */
|
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.res.Configuration;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.webkit.WebView;
|
|
||||||
|
|
||||||
public class CustomWebview extends WebView {
|
|
||||||
|
|
||||||
|
|
||||||
public CustomWebview(Context context) {
|
|
||||||
super(getFixedContext(context));
|
|
||||||
}
|
|
||||||
|
|
||||||
public CustomWebview(Context context, AttributeSet attrs) {
|
|
||||||
super(getFixedContext(context), attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CustomWebview(Context context, AttributeSet attrs, int defStyleAttr) {
|
|
||||||
super(getFixedContext(context), attrs, defStyleAttr);
|
|
||||||
}
|
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
public CustomWebview(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
|
||||||
super(getFixedContext(context), attrs, defStyleAttr, defStyleRes);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public CustomWebview(Context context, AttributeSet attrs, int defStyleAttr, boolean privateBrowsing) {
|
|
||||||
super(getFixedContext(context), attrs, defStyleAttr, privateBrowsing);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Context getFixedContext(Context context) {
|
|
||||||
return context.createConfigurationContext(new Configuration());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,228 +0,0 @@
|
||||||
package app.fedilab.android.webview;
|
|
||||||
/* Copyright 2021 Thomas Schneider
|
|
||||||
*
|
|
||||||
* This file is a part of Fedilab
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
|
||||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
|
||||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
||||||
* Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
|
||||||
* see <http://www.gnu.org/licenses>. */
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.media.MediaPlayer;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.SurfaceView;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.webkit.WebChromeClient;
|
|
||||||
import android.webkit.WebView;
|
|
||||||
import android.widget.FrameLayout;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.ProgressBar;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.appcompat.app.ActionBar;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
|
|
||||||
import app.fedilab.android.R;
|
|
||||||
|
|
||||||
|
|
||||||
public class FedilabWebChromeClient extends WebChromeClient implements MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener {
|
|
||||||
|
|
||||||
private final CustomWebview webView;
|
|
||||||
private final View activityNonVideoView;
|
|
||||||
private final ViewGroup activityVideoView;
|
|
||||||
private final ProgressBar pbar;
|
|
||||||
private final Activity activity;
|
|
||||||
private FrameLayout videoViewContainer;
|
|
||||||
private CustomViewCallback videoViewCallback;
|
|
||||||
private ToggledFullscreenCallback toggledFullscreenCallback;
|
|
||||||
private boolean isVideoFullscreen;
|
|
||||||
|
|
||||||
|
|
||||||
public FedilabWebChromeClient(Activity activity, CustomWebview webView, FrameLayout activityNonVideoView, ViewGroup activityVideoView) {
|
|
||||||
this.activity = activity;
|
|
||||||
this.isVideoFullscreen = false;
|
|
||||||
this.webView = webView;
|
|
||||||
this.pbar = activity.findViewById(R.id.progress_bar);
|
|
||||||
this.activityNonVideoView = activityNonVideoView;
|
|
||||||
this.activityVideoView = activityVideoView;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onProgressChanged(WebView view, int progress) {
|
|
||||||
if (pbar != null) {
|
|
||||||
if (progress < 100 && pbar.getVisibility() == ProgressBar.GONE) {
|
|
||||||
pbar.setVisibility(ProgressBar.VISIBLE);
|
|
||||||
}
|
|
||||||
pbar.setProgress(progress);
|
|
||||||
if (progress == 100) {
|
|
||||||
pbar.setVisibility(ProgressBar.GONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bitmap getDefaultVideoPoster() {
|
|
||||||
return Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReceivedIcon(WebView view, Bitmap icon) {
|
|
||||||
super.onReceivedIcon(view, icon);
|
|
||||||
LayoutInflater mInflater = LayoutInflater.from(activity);
|
|
||||||
ActionBar actionBar = ((AppCompatActivity) activity).getSupportActionBar();
|
|
||||||
if (actionBar != null) {
|
|
||||||
View webview_actionbar = mInflater.inflate(R.layout.webview_actionbar, new LinearLayout(activity), false);
|
|
||||||
TextView webview_title = webview_actionbar.findViewById(R.id.webview_title);
|
|
||||||
webview_title.setText(view.getTitle());
|
|
||||||
ImageView webview_favicon = webview_actionbar.findViewById(R.id.webview_favicon);
|
|
||||||
if (icon != null)
|
|
||||||
webview_favicon.setImageBitmap(icon);
|
|
||||||
actionBar.setCustomView(webview_actionbar);
|
|
||||||
actionBar.setDisplayShowCustomEnabled(true);
|
|
||||||
} else {
|
|
||||||
activity.setTitle(view.getTitle());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a callback that will be fired when the video starts or finishes displaying using a custom view (typically full-screen)
|
|
||||||
*
|
|
||||||
* @param callback A VideoEnabledWebChromeClient.ToggledFullscreenCallback callback
|
|
||||||
*/
|
|
||||||
public void setOnToggledFullscreen(ToggledFullscreenCallback callback) {
|
|
||||||
this.toggledFullscreenCallback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
//FULLSCREEN VIDEO
|
|
||||||
//Code from https://stackoverflow.com/a/16179544/3197259
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onShowCustomView(View view, CustomViewCallback callback) {
|
|
||||||
if (view instanceof FrameLayout) {
|
|
||||||
if (((AppCompatActivity) activity).getSupportActionBar() != null)
|
|
||||||
//noinspection ConstantConditions
|
|
||||||
((AppCompatActivity) activity).getSupportActionBar().hide();
|
|
||||||
// A video wants to be shown
|
|
||||||
FrameLayout frameLayout = (FrameLayout) view;
|
|
||||||
View focusedChild = frameLayout.getFocusedChild();
|
|
||||||
|
|
||||||
// Save video related variables
|
|
||||||
isVideoFullscreen = true;
|
|
||||||
this.videoViewContainer = frameLayout;
|
|
||||||
this.videoViewCallback = callback;
|
|
||||||
|
|
||||||
// Hide the non-video view, add the video view, and show it
|
|
||||||
activityNonVideoView.setVisibility(View.INVISIBLE);
|
|
||||||
activityVideoView.addView(videoViewContainer, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
|
||||||
activityVideoView.setVisibility(View.VISIBLE);
|
|
||||||
if (focusedChild instanceof android.widget.VideoView) {
|
|
||||||
// android.widget.VideoView (typically API level <11)
|
|
||||||
android.widget.VideoView videoView = (android.widget.VideoView) focusedChild;
|
|
||||||
// Handle all the required events
|
|
||||||
videoView.setOnCompletionListener(this);
|
|
||||||
videoView.setOnErrorListener(this);
|
|
||||||
} else {
|
|
||||||
// Other classes, including:
|
|
||||||
// - android.webkit.HTML5VideoFullScreen$VideoSurfaceView, which inherits from android.view.SurfaceView (typically API level 11-18)
|
|
||||||
// - android.webkit.HTML5VideoFullScreen$VideoTextureView, which inherits from android.view.TextureView (typically API level 11-18)
|
|
||||||
// - com.android.org.chromium.content.browser.ContentVideoView$VideoSurfaceView, which inherits from android.view.SurfaceView (typically API level 19+)
|
|
||||||
|
|
||||||
// Handle HTML5 video ended event only if the class is a SurfaceView
|
|
||||||
// Test case: TextureView of Sony Xperia T API level 16 doesn't work fullscreen when loading the javascript below
|
|
||||||
if (webView != null && webView.getSettings().getJavaScriptEnabled() && focusedChild instanceof SurfaceView) {
|
|
||||||
// Run javascript code that detects the video end and notifies the Javascript interface
|
|
||||||
String js = "javascript:";
|
|
||||||
js += "var _ytrp_html5_video_last;";
|
|
||||||
js += "var _ytrp_html5_video = document.getElementsByTagName('video')[0];";
|
|
||||||
js += "if (_ytrp_html5_video != undefined && _ytrp_html5_video != _ytrp_html5_video_last) {";
|
|
||||||
{
|
|
||||||
js += "_ytrp_html5_video_last = _ytrp_html5_video;";
|
|
||||||
js += "function _ytrp_html5_video_ended() {";
|
|
||||||
{
|
|
||||||
js += "_VideoEnabledWebView.notifyVideoEnd();"; // Must match Javascript interface name and method of VideoEnableWebView
|
|
||||||
}
|
|
||||||
js += "}";
|
|
||||||
js += "_ytrp_html5_video.addEventListener('ended', _ytrp_html5_video_ended);";
|
|
||||||
}
|
|
||||||
js += "}";
|
|
||||||
webView.loadUrl(js);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Notify full-screen change
|
|
||||||
if (toggledFullscreenCallback != null) {
|
|
||||||
toggledFullscreenCallback.toggledFullscreen(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Available in API level 14+, deprecated in API level 18+
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public void onShowCustomView(View view, int requestedOrientation, CustomViewCallback callback) {
|
|
||||||
onShowCustomView(view, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onHideCustomView() {
|
|
||||||
if (((AppCompatActivity) activity).getSupportActionBar() != null)
|
|
||||||
//noinspection ConstantConditions
|
|
||||||
((AppCompatActivity) activity).getSupportActionBar().show();
|
|
||||||
// This method should be manually called on video end in all cases because it's not always called automatically.
|
|
||||||
// This method must be manually called on back key press (from this class' onBackPressed() method).
|
|
||||||
if (isVideoFullscreen) {
|
|
||||||
// Hide the video view, remove it, and show the non-video view
|
|
||||||
activityVideoView.setVisibility(View.INVISIBLE);
|
|
||||||
activityVideoView.removeView(videoViewContainer);
|
|
||||||
activityNonVideoView.setVisibility(View.VISIBLE);
|
|
||||||
// Call back (only in API level <19, because in API level 19+ with chromium webview it crashes)
|
|
||||||
if (videoViewCallback != null && !videoViewCallback.getClass().getName().contains(".chromium.")) {
|
|
||||||
videoViewCallback.onCustomViewHidden();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset video related variables
|
|
||||||
isVideoFullscreen = false;
|
|
||||||
videoViewContainer = null;
|
|
||||||
videoViewCallback = null;
|
|
||||||
|
|
||||||
// Notify full-screen change
|
|
||||||
if (toggledFullscreenCallback != null) {
|
|
||||||
toggledFullscreenCallback.toggledFullscreen(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Video will start loading
|
|
||||||
@Override
|
|
||||||
public View getVideoLoadingProgressView() {
|
|
||||||
return super.getVideoLoadingProgressView();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Video finished playing, only called in the case of android.widget.VideoView (typically API level <11)
|
|
||||||
@Override
|
|
||||||
public void onCompletion(MediaPlayer mp) {
|
|
||||||
onHideCustomView();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error while playing video, only called in the case of android.widget.VideoView (typically API level <11)
|
|
||||||
@Override
|
|
||||||
public boolean onError(MediaPlayer mp, int what, int extra) {
|
|
||||||
return false; // By returning false, onCompletion() will be called
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ToggledFullscreenCallback {
|
|
||||||
void toggledFullscreen(boolean fullscreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,163 +0,0 @@
|
||||||
package app.fedilab.android.webview;
|
|
||||||
/* Copyright 2021 Thomas Schneider
|
|
||||||
*
|
|
||||||
* This file is a part of Fedilab
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
|
||||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
|
||||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
||||||
* Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
|
||||||
* see <http://www.gnu.org/licenses>. */
|
|
||||||
|
|
||||||
|
|
||||||
import static app.fedilab.android.client.entities.app.DomainsBlock.trackingDomains;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.net.http.SslError;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.webkit.SslErrorHandler;
|
|
||||||
import android.webkit.URLUtil;
|
|
||||||
import android.webkit.WebResourceResponse;
|
|
||||||
import android.webkit.WebView;
|
|
||||||
import android.webkit.WebViewClient;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.appcompat.app.ActionBar;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import app.fedilab.android.BuildConfig;
|
|
||||||
import app.fedilab.android.R;
|
|
||||||
import app.fedilab.android.activities.WebviewActivity;
|
|
||||||
|
|
||||||
|
|
||||||
public class FedilabWebViewClient extends WebViewClient {
|
|
||||||
|
|
||||||
private final Activity activity;
|
|
||||||
public List<String> domains = new ArrayList<>();
|
|
||||||
private int count = 0;
|
|
||||||
|
|
||||||
public FedilabWebViewClient(Activity activity) {
|
|
||||||
this.activity = activity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPageFinished(WebView view, String url) {
|
|
||||||
super.onPageFinished(view, url);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WebResourceResponse shouldInterceptRequest(final WebView view, String url) {
|
|
||||||
if (trackingDomains != null) {
|
|
||||||
URI uri;
|
|
||||||
try {
|
|
||||||
uri = new URI(url);
|
|
||||||
String domain = uri.getHost();
|
|
||||||
if (domain != null) {
|
|
||||||
domain = domain.startsWith("www.") ? domain.substring(4) : domain;
|
|
||||||
}
|
|
||||||
if (domain != null && trackingDomains.contains(domain)) {
|
|
||||||
if (activity instanceof WebviewActivity) {
|
|
||||||
count++;
|
|
||||||
domains.add(url);
|
|
||||||
((WebviewActivity) activity).setCount(activity, String.valueOf(count));
|
|
||||||
}
|
|
||||||
ByteArrayInputStream nothing = new ByteArrayInputStream("".getBytes());
|
|
||||||
return new WebResourceResponse("text/plain", "utf-8", nothing);
|
|
||||||
}
|
|
||||||
} catch (URISyntaxException e) {
|
|
||||||
try {
|
|
||||||
if (url.length() > 50) {
|
|
||||||
url = url.substring(0, 50);
|
|
||||||
}
|
|
||||||
uri = new URI(url);
|
|
||||||
String domain = uri.getHost();
|
|
||||||
if (domain != null) {
|
|
||||||
domain = domain.startsWith("www.") ? domain.substring(4) : domain;
|
|
||||||
}
|
|
||||||
if (domain != null && trackingDomains.contains(domain)) {
|
|
||||||
if (activity instanceof WebviewActivity) {
|
|
||||||
count++;
|
|
||||||
domains.add(url);
|
|
||||||
((WebviewActivity) activity).setCount(activity, String.valueOf(count));
|
|
||||||
}
|
|
||||||
ByteArrayInputStream nothing = new ByteArrayInputStream("".getBytes());
|
|
||||||
return new WebResourceResponse("text/plain", "utf-8", nothing);
|
|
||||||
|
|
||||||
}
|
|
||||||
} catch (URISyntaxException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super.shouldInterceptRequest(view, url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getDomains() {
|
|
||||||
return this.domains;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
|
|
||||||
if (BuildConfig.DONATIONS) {
|
|
||||||
if (view.getUrl() != null && view.getUrl().endsWith(".onion")) {
|
|
||||||
handler.proceed();
|
|
||||||
} else {
|
|
||||||
super.onReceivedSslError(view, handler, error);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
super.onReceivedSslError(view, handler, error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
|
||||||
if (URLUtil.isNetworkUrl(url)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
view.stopLoading();
|
|
||||||
view.goBack();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPageStarted(WebView view, String url, Bitmap favicon) {
|
|
||||||
super.onPageStarted(view, url, favicon);
|
|
||||||
count = 0;
|
|
||||||
domains = new ArrayList<>();
|
|
||||||
domains.clear();
|
|
||||||
ActionBar actionBar = ((AppCompatActivity) activity).getSupportActionBar();
|
|
||||||
LayoutInflater mInflater = LayoutInflater.from(activity);
|
|
||||||
if (actionBar != null) {
|
|
||||||
View webview_actionbar = mInflater.inflate(R.layout.webview_actionbar, new LinearLayout(activity), false);
|
|
||||||
TextView webview_title = webview_actionbar.findViewById(R.id.webview_title);
|
|
||||||
webview_title.setText(url);
|
|
||||||
actionBar.setCustomView(webview_actionbar);
|
|
||||||
actionBar.setDisplayShowCustomEnabled(true);
|
|
||||||
} else {
|
|
||||||
activity.setTitle(url);
|
|
||||||
}
|
|
||||||
//Changes the url in webview activity so that it can be opened with an external app
|
|
||||||
try {
|
|
||||||
if (activity instanceof WebviewActivity)
|
|
||||||
((WebviewActivity) activity).setUrl(url);
|
|
||||||
} catch (Exception ignore) {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,166 +0,0 @@
|
||||||
package app.fedilab.android.webview;
|
|
||||||
/* Copyright 2021 Thomas Schneider
|
|
||||||
*
|
|
||||||
* This file is a part of Fedilab
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
|
||||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
|
||||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
||||||
* Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
|
||||||
* see <http://www.gnu.org/licenses>. */
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.Proxy;
|
|
||||||
import android.util.ArrayMap;
|
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
public class ProxyHelper {
|
|
||||||
|
|
||||||
|
|
||||||
public static void setProxy(Context context, CustomWebview webview, String host, int port, String applicationClassName) {
|
|
||||||
|
|
||||||
setProxyKKPlus(context, webview, host, port, applicationClassName);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("all")
|
|
||||||
private static boolean setProxyICS(CustomWebview webview, String host, int port) {
|
|
||||||
try {
|
|
||||||
Class jwcjb = Class.forName("android.webkit.JWebCoreJavaBridge");
|
|
||||||
Class params[] = new Class[1];
|
|
||||||
params[0] = Class.forName("android.net.ProxyProperties");
|
|
||||||
Method updateProxyInstance = jwcjb.getDeclaredMethod("updateProxy", params);
|
|
||||||
|
|
||||||
Class wv = Class.forName("android.webkit.WebView");
|
|
||||||
Field mWebViewCoreField = wv.getDeclaredField("mWebViewCore");
|
|
||||||
Object mWebViewCoreFieldInstance = getFieldValueSafely(mWebViewCoreField, webview);
|
|
||||||
|
|
||||||
Class wvc = Class.forName("android.webkit.WebViewCore");
|
|
||||||
Field mBrowserFrameField = wvc.getDeclaredField("mBrowserFrame");
|
|
||||||
Object mBrowserFrame = getFieldValueSafely(mBrowserFrameField, mWebViewCoreFieldInstance);
|
|
||||||
|
|
||||||
Class bf = Class.forName("android.webkit.BrowserFrame");
|
|
||||||
Field sJavaBridgeField = bf.getDeclaredField("sJavaBridge");
|
|
||||||
Object sJavaBridge = getFieldValueSafely(sJavaBridgeField, mBrowserFrame);
|
|
||||||
|
|
||||||
Class ppclass = Class.forName("android.net.ProxyProperties");
|
|
||||||
Class pparams[] = new Class[3];
|
|
||||||
pparams[0] = String.class;
|
|
||||||
pparams[1] = int.class;
|
|
||||||
pparams[2] = String.class;
|
|
||||||
Constructor ppcont = ppclass.getConstructor(pparams);
|
|
||||||
|
|
||||||
updateProxyInstance.invoke(sJavaBridge, ppcont.newInstance(host, port, null));
|
|
||||||
return true;
|
|
||||||
} catch (Exception ex) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Proxy for Android 4.1 - 4.3.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("all")
|
|
||||||
private static boolean setProxyJB(CustomWebview webview, String host, int port) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
Class wvcClass = Class.forName("android.webkit.WebViewClassic");
|
|
||||||
Class wvParams[] = new Class[1];
|
|
||||||
wvParams[0] = Class.forName("android.webkit.WebView");
|
|
||||||
Method fromWebView = wvcClass.getDeclaredMethod("fromWebView", wvParams);
|
|
||||||
Object webViewClassic = fromWebView.invoke(null, webview);
|
|
||||||
|
|
||||||
Class wv = Class.forName("android.webkit.WebViewClassic");
|
|
||||||
Field mWebViewCoreField = wv.getDeclaredField("mWebViewCore");
|
|
||||||
Object mWebViewCoreFieldInstance = getFieldValueSafely(mWebViewCoreField, webViewClassic);
|
|
||||||
|
|
||||||
Class wvc = Class.forName("android.webkit.WebViewCore");
|
|
||||||
Field mBrowserFrameField = wvc.getDeclaredField("mBrowserFrame");
|
|
||||||
Object mBrowserFrame = getFieldValueSafely(mBrowserFrameField, mWebViewCoreFieldInstance);
|
|
||||||
|
|
||||||
Class bf = Class.forName("android.webkit.BrowserFrame");
|
|
||||||
Field sJavaBridgeField = bf.getDeclaredField("sJavaBridge");
|
|
||||||
Object sJavaBridge = getFieldValueSafely(sJavaBridgeField, mBrowserFrame);
|
|
||||||
|
|
||||||
Class ppclass = Class.forName("android.net.ProxyProperties");
|
|
||||||
Class pparams[] = new Class[3];
|
|
||||||
pparams[0] = String.class;
|
|
||||||
pparams[1] = int.class;
|
|
||||||
pparams[2] = String.class;
|
|
||||||
Constructor ppcont = ppclass.getConstructor(pparams);
|
|
||||||
|
|
||||||
Class jwcjb = Class.forName("android.webkit.JWebCoreJavaBridge");
|
|
||||||
Class params[] = new Class[1];
|
|
||||||
params[0] = Class.forName("android.net.ProxyProperties");
|
|
||||||
Method updateProxyInstance = jwcjb.getDeclaredMethod("updateProxy", params);
|
|
||||||
|
|
||||||
updateProxyInstance.invoke(sJavaBridge, ppcont.newInstance(host, port, null));
|
|
||||||
} catch (Exception ex) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// from https://stackoverflow.com/questions/19979578/android-webview-set-proxy-programatically-kitkat
|
|
||||||
@SuppressLint("NewApi")
|
|
||||||
@SuppressWarnings("all")
|
|
||||||
private static void setProxyKKPlus(Context appContext, CustomWebview webView, String host, int port, String applicationClassName) {
|
|
||||||
|
|
||||||
System.setProperty("http.proxyHost", host);
|
|
||||||
System.setProperty("http.proxyPort", port + "");
|
|
||||||
System.setProperty("https.proxyHost", host);
|
|
||||||
System.setProperty("https.proxyPort", port + "");
|
|
||||||
try {
|
|
||||||
Class applictionCls = Class.forName("android.app.Application");
|
|
||||||
Field loadedApkField = applictionCls.getDeclaredField("mLoadedApk");
|
|
||||||
loadedApkField.setAccessible(true);
|
|
||||||
Object loadedApk = loadedApkField.get(appContext);
|
|
||||||
Class loadedApkCls = Class.forName("android.app.LoadedApk");
|
|
||||||
Field receiversField = loadedApkCls.getDeclaredField("mReceivers");
|
|
||||||
receiversField.setAccessible(true);
|
|
||||||
ArrayMap receivers = (ArrayMap) receiversField.get(loadedApk);
|
|
||||||
for (Object receiverMap : receivers.values()) {
|
|
||||||
for (Object rec : ((ArrayMap) receiverMap).keySet()) {
|
|
||||||
Class clazz = rec.getClass();
|
|
||||||
if (clazz.getName().contains("ProxyChangeListener")) {
|
|
||||||
Method onReceiveMethod = clazz.getDeclaredMethod("onReceive", Context.class, Intent.class);
|
|
||||||
Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
|
|
||||||
|
|
||||||
onReceiveMethod.invoke(rec, appContext, intent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (NoSuchFieldException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (NoSuchMethodException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Object getFieldValueSafely(Field field, Object classInstance) throws IllegalArgumentException, IllegalAccessException {
|
|
||||||
boolean oldAccessibleValue = field.isAccessible();
|
|
||||||
field.setAccessible(true);
|
|
||||||
Object result = field.get(classInstance);
|
|
||||||
field.setAccessible(oldAccessibleValue);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,93 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
Copyright 2021 Thomas Schneider
|
|
||||||
|
|
||||||
This file is a part of Fedilab
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under the terms of the
|
|
||||||
GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
|
||||||
License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
|
||||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
||||||
Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
|
||||||
see <http://www.gnu.org/licenses>
|
|
||||||
-->
|
|
||||||
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/drawer_layout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:fitsSystemWindows="true"
|
|
||||||
tools:openDrawer="start">
|
|
||||||
|
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
tools:context=".activities.WebviewActivity">
|
|
||||||
|
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
|
||||||
android:id="@+id/appBar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.Toolbar
|
|
||||||
android:id="@+id/toolbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="?attr/actionBarSize"
|
|
||||||
android:fitsSystemWindows="true"
|
|
||||||
app:layout_scrollFlags="scroll|enterAlways">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/favicon"
|
|
||||||
android:layout_width="32dp"
|
|
||||||
android:layout_height="32dp"
|
|
||||||
android:contentDescription="@string/favicon" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/toolbar_title"
|
|
||||||
style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
</androidx.appcompat.widget.Toolbar>
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_marginBottom="?attr/actionBarSize"
|
|
||||||
android:orientation="vertical"
|
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
|
||||||
|
|
||||||
<ProgressBar
|
|
||||||
android:id="@+id/progress_bar"
|
|
||||||
style="?android:attr/progressBarStyleHorizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="10dp"
|
|
||||||
android:padding="1dp" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/webview_container"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1">
|
|
||||||
|
|
||||||
<app.fedilab.android.webview.CustomWebview
|
|
||||||
android:id="@+id/webview"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@color/white" />
|
|
||||||
</FrameLayout>
|
|
||||||
<!-- View where the video will be shown when video goes fullscreen -->
|
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/videoLayout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@color/black"
|
|
||||||
android:visibility="gone" />
|
|
||||||
</LinearLayout>
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
||||||
</androidx.drawerlayout.widget.DrawerLayout>
|
|
|
@ -1,40 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
Copyright 2022 Thomas Schneider
|
|
||||||
|
|
||||||
This file is a part of Fedilab
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under the terms of the
|
|
||||||
GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
|
||||||
License, or (at your option) any later version.
|
|
||||||
|
|
||||||
Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
|
||||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
||||||
Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
|
||||||
see <http://www.gnu.org/licenses>
|
|
||||||
-->
|
|
||||||
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:id="@+id/drawer_layout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<ProgressBar
|
|
||||||
android:id="@+id/progress_bar"
|
|
||||||
style="?android:attr/progressBarStyleHorizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="10dp"
|
|
||||||
android:padding="2dp" />
|
|
||||||
|
|
||||||
<app.fedilab.android.webview.CustomWebview
|
|
||||||
android:id="@+id/webviewConnect"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
</LinearLayout>
|
|
||||||
</androidx.drawerlayout.widget.DrawerLayout>
|
|
|
@ -43,19 +43,6 @@
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/main_media_frame"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_centerInParent="true">
|
|
||||||
|
|
||||||
<app.fedilab.android.webview.CustomWebview
|
|
||||||
android:id="@+id/webview_video"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:visibility="gone" />
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:id="@+id/videoLayout"
|
android:id="@+id/videoLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -16,11 +16,6 @@
|
||||||
android:id="@+id/action_proxy"
|
android:id="@+id/action_proxy"
|
||||||
android:title="@string/proxy_set"
|
android:title="@string/proxy_set"
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" />
|
||||||
<item
|
|
||||||
android:id="@+id/action_custom_tabs"
|
|
||||||
android:checkable="true"
|
|
||||||
android:title="@string/custom_tabs"
|
|
||||||
app:actionViewClass="android.widget.CheckBox" />
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_request_admin"
|
android:id="@+id/action_request_admin"
|
||||||
android:checkable="true"
|
android:checkable="true"
|
||||||
|
|
|
@ -774,7 +774,6 @@
|
||||||
<string name="SET_PROXY_TYPE" translatable="false">SET_PROXY_TYPE</string>
|
<string name="SET_PROXY_TYPE" translatable="false">SET_PROXY_TYPE</string>
|
||||||
<string name="SET_PROXY_HOST" translatable="false">SET_PROXY_HOST</string>
|
<string name="SET_PROXY_HOST" translatable="false">SET_PROXY_HOST</string>
|
||||||
<string name="SET_PROXY_PORT" translatable="false">SET_PROXY_PORT</string>
|
<string name="SET_PROXY_PORT" translatable="false">SET_PROXY_PORT</string>
|
||||||
<string name="SET_EMBEDDED_BROWSER" translatable="false">SET_EMBEDDED_BROWSER</string>
|
|
||||||
<string name="SET_DEFAULT_LOCALE_NEW" translatable="false">SET_DEFAULT_LOCALE_NEW</string>
|
<string name="SET_DEFAULT_LOCALE_NEW" translatable="false">SET_DEFAULT_LOCALE_NEW</string>
|
||||||
<string name="SET_SEND_CRASH_REPORTS" translatable="false">SET_SEND_CRASH_REPORTS</string>
|
<string name="SET_SEND_CRASH_REPORTS" translatable="false">SET_SEND_CRASH_REPORTS</string>
|
||||||
<string name="SET_DISABLE_GIF" translatable="false">SET_DISABLE_GIF</string>
|
<string name="SET_DISABLE_GIF" translatable="false">SET_DISABLE_GIF</string>
|
||||||
|
|
|
@ -52,12 +52,6 @@
|
||||||
app:summary="@string/set_clear_cache_exit_indication"
|
app:summary="@string/set_clear_cache_exit_indication"
|
||||||
app:title="@string/set_clear_cache_exit" />
|
app:title="@string/set_clear_cache_exit" />
|
||||||
|
|
||||||
<SwitchPreferenceCompat
|
|
||||||
app:defaultValue="true"
|
|
||||||
app:iconSpaceReserved="false"
|
|
||||||
app:key="@string/SET_EMBEDDED_BROWSER"
|
|
||||||
app:singleLineTitle="false"
|
|
||||||
app:title="@string/embedded_browser" />
|
|
||||||
|
|
||||||
<SwitchPreferenceCompat
|
<SwitchPreferenceCompat
|
||||||
app:defaultValue="false"
|
app:defaultValue="false"
|
||||||
|
|
Loading…
Reference in a new issue