I am trying to make a webview where the app loads a HTML page from assets if there is no internet connection. I have been following this QUESTION and i have made a CheckNetwork.java but where shall i put this code below into my MainActivity? I am a beginner at this so please explain as simple as possible.
if(CheckNetwork.isInternetAvailable(MainActivity.this))
{
// do something
}
This is my MainActivity
public class MainActivity extends ActionBarActivity {
WebView browser;
private ourViewClient mClass;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mClass = new ourViewClient(this);
browser = (WebView) findViewById(R.id.wvwMain);
browser.getSettings().setJavaScriptEnabled(true);
browser.getSettings().setLoadWithOverviewMode(true);
browser.getSettings().setUseWideViewPort(true);
browser.setWebViewClient(new ourViewClient(this));
try {
browser.loadUrl("http://MyWebPage");
}
catch (Exception e) {
e.printStackTrace();
}
}
}
This should do the trick for you:
if(CheckNetwork.isInternetAvailable(MainActivity.this))
browser.loadUrl("http://MyWebPage");
} else {
browser.loadUrl("file:///android_asset/your_html.html");
}
I am also including example of how you load a html from your assets.
Related
Clipboard data returns null when MainActivity is not active in top view activity when I click the button in Android java
I read this restriction about android10 and higher, but my activity is not a background service.
I need to get clipboard data when I click on the button located in the top view activity like the Google Translate application.
In my case, the clipboard returns null when MainActivity is not active.
https://developer.android.com/about/versions/10/privacy/changes#clipboard-data
public class MainActivity extends BridgeActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Initializes the Bridge
this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>() {{
// Additional plugins you've installed go here
// Ex: add(TotallyAwesomePlugin.class);
}});
startActivity(new Intent(MainActivity.this, FloatingWindow.class));
}
}
public class FloatingWindow extends Activity {
// ... additional code ....
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
floatingButtonDefinedInClass.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
try {
self.getClipboardText();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
public void getClipboardText() throws IOException {
try {
ClipboardManager myClipboard = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE);
ClipData clipData = myClipboard.getPrimaryClip();
if(clipData != null) {
text = (String) clipData.getItemAt(0).getText();
System.out.println(text); // returns null when mainactivity is not active
}
} catch (Exception e) {
e.printStackTrace();
}
}
// ... additional code ....
}
what does "mainactivity is not active" mean? you are getting access to ClipboardManager inside OnClickListener attached to Button, which is a View and need Context, so there must be alive Activity, which keeps this Button on the screen for clicking purpose...
btw. maybe you are you checking on Android 10 or above? it looks like according to docs
Limited access to clipboard data
Unless your app is the default input method editor (IME) or is the app
that currently has focus, your app cannot access clipboard data on
Android 10 or higher.
privacy/security reasons, thats how it will be working now
My app is based on a fullscreen WebView and I wanted to show a local file if there is no internet connection, otherwise load my website. I never used AsyncTask before and tried the following:
MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Check Internet Connection
mWebView = (WebView) findViewById(R.id.activity_main_webview);
HostAvailabilityTask hostAvailable = new HostAvailabilityTask(this);
boolean online = hostAvailable.isOnline();
if (!online) {
// Loading local html file into web view
mWebView.loadUrl("file:///android_asset/sample.html");
} else {
// load my website here
HostAvailabilityTask:
public class HostAvailabilityTask extends AsyncTask<String, Void, Boolean> {
private MainActivity main;
public HostAvailabilityTask(MainActivity main) {
this.main = main;
}
protected Boolean doInBackground(String... params) {
return isOnline(); // Correct way using AsyncTask?
}
protected void onPostExecute(Boolean... result) {
if(!result[0]) {
return; // What to return?
}
}
public boolean isOnline() {
Runtime runtime = Runtime.getRuntime();
try {
Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
int exitValue = ipProcess.waitFor();
return (exitValue == 0);
}
catch (IOException e) { e.printStackTrace(); }
catch (InterruptedException e) { e.printStackTrace(); }
return false;
}
}
As you can see I'm just calling the method isOnline(); inside the MainActivity and think this is the wrong way to use a AsyncTask? I just want to make sure to do it "the right way". I also don't know what would be logical to return in onPostExecute in that case?
As stated before I never used AsyncTask, so I hope someone could help me out. I also commented some lines in my code to make my confusion clear.
#Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error){
//Your code to do
Toast.makeText(getActivity(), "Your Internet Connection May not be active Or " + error , Toast.LENGTH_LONG).show();
}
I have a tab fragment inside of a container activity.
I would like to download some data to display in the tab. In the tab, I have made an asynctask that I execute just after inflating the fragment layout in onCreateView. When I do it this way, the AsyncTask's doInBackground... work occurs on the main thread and the view does not load until it is done. All of my progress... logs show up at the same time as soon as the task is done.
However, if I put a button in the fragment layout and start the asynctask work as a response to the button click, it works as expected, I get my normally spaced progress updates.
So, why does AsyncTask run on the main thread if it is the first thing to happen when my fragment starts? And, how can I prevent this? My ultimate goal is to show a progress wheel while the data is downloading.
Edit. Here is where I call my AsyncTask.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.temp_my_moments, container, false);
getMyClips(getActivity(), rootView, p_session, p_person,progressBar);
//If I use this button, it works fine:
// test = (Button) rootView.findViewById(R.id.testbutton);
// test.setOnClickListener(new View.OnClickListener() {
// #Override
// public void onClick(View v) {
// progressBar =(ProgressBar) rootView.findViewById(R.id.myMomentsProgress);
// getMyClips(getActivity(), rootView, p_session, p_person, progressBar);
// }
// });
return rootView;
}
And here is getMyClips():
public void getMyClips(Context context,View view,String thisSession,String thisPerson,ProgressBar progressBar) {
Log.d("Currently running", "getMyClips");
JSONObject params = new JSONObject();
try {
params.put("Function", clipsMine_apiCall);
params.put("p_session", thisSession);
params.put("p_person", thisPerson);
} catch (JSONException e1) {
e1.printStackTrace();
}
ApiClipCaller webServiceTask = new ApiClipCaller(context,view,progressBar);
if (webServiceTask.hasConnection()) {
webServiceTask.execute(params);
} else {
//TODO no internet connection
}
}
Edit Here is my AsyncTask. This is inside the Fragment:
public class ApiClipCaller extends AsyncTask<JSONObject, Integer, ApiResponse> {
public Context context;
public String clipID;
public String sessionID;
public String personID;
public String functionName;
public View view;
public ProgressBar progressBar;
public final String apiURL = "...."; //need to keep private
LinearLayout loading;
public ApiClipCaller(Context c, View v,ProgressBar progressBar) {
this.context = c;
this.view = v;
this.progressBar = progressBar;
loading = (LinearLayout) view.findViewById(R.id.loadingMyMoments);
}
#Override
protected ApiResponse doInBackground(JSONObject... params) {
JSONObject realParams = params[0];
try {
functionName = realParams.getString("Function");
} catch (JSONException e) {
e.printStackTrace();
}
ApiResponse responseObject = masterFunction(realParams);
//making some work to see if it is running correctly
for (int i=10;i<=100;i += 10)
{
try {
Thread.sleep(1000);
publishProgress(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return responseObject;
}
#Override
protected void onProgressUpdate(Integer... progress) {
loading.setVisibility(View.VISIBLE);
progressBar.setProgress(progress[0]);
Log.d("progress",Integer.toString(progress[0]));
}
#Override
protected void onPostExecute(ApiResponse responseObject) {
loading.setVisibility(View.GONE);
if (functionName.equals(clipsMine_apiCall)) {
JSONObject clipObject = responseObject.getResponseJSONObject();
//just testing here to see if I can get data back in the fragment view when it is done.
///This works as expected.
String responseString = responseObject.getResponseString();
TextView showAsyncResults = (TextView) view.findViewById(R.id.testAsyncTask);
showAsyncResults.setText(responseString);
}
super.onPostExecute(responseObject);
}
}
So, it seems like the answer is that I was going about this all wrong. It it is not possible to launch asynctask when the first activity or fragment loads, because the onCreate etc. methods are not actually on the UI thread. So, AsyncTask cannot be executed directly from there, as Ordous pointed out.
Instead, it seems like the solution is to load information when the application first starts by creating a class which extends Application and doing the loading work from there, because this will necessarily be on the main thread. The methods in there can be called from the activity to access the layouts and make a progress bar or similar.
Reference: http://developer.android.com/reference/android/app/Application.html
A good example: http://www.intertech.com/Blog/androids-application-class/
I have searched high and low and found so many examples of this, but unable to get it to work, my setup currently is:
Notifier.java
public class Notifier{
Context mContext;
Notifier(Context c) {
mContext = c;
}
#JavascriptInterface
public void showText()
{
Toast.makeText(mContext, "Some text!", Toast.LENGTH_LONG).show();
}
}
SearchLicenseActivity.java
public class SearchLicenseActivity extends Activity {
WebView webView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search_license);
LoadSearch();
}
public void LoadSearch(){
webView = (WebView)findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new Notifier(this), "Android");
webView.loadUrl("javascript:Android.showText();");
}
}
So I am expecting a Toast to show. It may be worth noting that this SearchActivity gets created when a button on a previous Activity is clicked; so I want it to execute LoadSearch straight away and get the Toast from the JavaScript.
I hope one of you out there can cure my woes over this!
Edit: I am also not getting any errors in LogCat.
OK, it turns out webView must have a webpage loaded.
Even if the url is "about:blank" this seems to work. So...
webView.loadUrl("about:blank");
webView.loadUrl("javascript:Android.showText();");
...works.
I've been looking into communicating between the main thread and a WebView, but whatever I try, nothing ever seems to happen. And unfortunately I don't really have a Javascript debug console at the ready in Android :-/
It's probably some stupid small mistake again, but I can't find the problem. It simply doesn't do anything. I don't see any errors or whatever.
#SuppressLint("SetJavaScriptEnabled")
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate (savedInstanceState);
setContentView (R.layout.activity_main);
WebView web = (WebView) findViewById (R.id.web);
web.getSettings ().setJavaScriptEnabled (true);
web.setWebChromeClient (new WebChromeClient ());
JavaScriptInterface jsInterface = new JavaScriptInterface (this);
web.addJavascriptInterface (jsInterface, "accessAndroid");
}
public class JavaScriptInterface
{
Context context;
JavaScriptInterface (Context c)
{
context = c;
}
public void gotoArticle (int id)
{
jsHandler.post
(
new Runnable ()
{
public void run ()
{
//TODO//
}
}
);
}
public void showDialog (final String message)
{
jsHandler.post
(
new Runnable ()
{
public void run ()
{
showDialog (message);
}
}
);
}
}
When running alert ('Something'); from the loaded webpage, all is fine. But dlg ('Something'); doesn't do anything.