I have been trying my best to understand the source material from android studio and the android developer website
https://developer.android.com/guide/webapps/webview#java
But I know that a app that just loads a webpage works perfectly for my needs at the moment. So I wanted to diversify. I wanted to see if I could make a webpage that was a bit more dynamic and an app that could use the "back button". What I have so far is in
Android Manifest
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
Activity Main
<android.support.constraint.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<WebView
android:id="#+id/mywebview"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</android.support.constraint.ConstraintLayout>
and the java main file
WebView myWebView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(myWebView);
myWebView.loadUrl("www.google.com");
myWebView.getSettings().setJavaScriptEnabled(true);
}
private class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (Uri.parse(url).getHost().equals("www.google.com")) {
// This is my website, so do not override; let my WebView load the page
return false;
}
// Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
}
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// Check if the key event was the Back button and if there's history
if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {
myWebView.goBack();
return true;
}
// If it wasn't the Back key or there's no web page history, bubble up to the default
// system behavior (probably exit the activity)
return super.onKeyDown(keyCode, event);
}
}
My computer cannot handle the android emulator and I try to test the apps on my phone but they keep stopping. I know this may seem super basic to some of you out there, but I am not sure why it keeps malfunctioning. All I want to do is make a simple code that uses the back button, webview and loads other links in webview
I have tried looking for resources elsewhere but they all use the same basic reference material.
Did you get your myWebView? I guess not!
WebView myWebView = (WebView) findViewById(R.id.mywebview);
Add this line before myWebView.loadUrl(...);
Related
How can I start an activity when my app is in background? I mean, when it has not been destroyed? I have tried with IntentService and nothing, I just want to make a StartActivity to launch my MainActivity in the background.
Your service needs to be a foreground service.
Here is how.
First in your Manifest.xml file.
Request for permission
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
......
<!-- Your Service-->
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"
android:permission="android.permission.FOREGROUND_SERVICE"/>
Start your service with:
startForegroundService(Intent(this, MyService::class.java))
Then in your service display the foreground notification(usually in the onStartCommand):
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val ncCompat = NotificationChannelCompat.Builder("your.own.id.here", NotificationManagerCompat.IMPORTANCE_DEFAULT).setName("Important").build()
NotificationManagerCompat.from(baseContext).createNotificationChannel(ncCompat)
startForeground("your.notification.id.goes.here".hashCode(), NotificationCompat.Builder(baseContext, nmCompat.id).setContentTitle("My Foreground Service").setContentText("Running Service").build())
return super.onStartCommand(intent, flags, startId)
}
Then your can start an activity(for example: see below)
val intent = Intent(application, MainActivity2::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_TASK_ON_HOME)
intent.addFlags(Intent.FLAG_FROM_BACKGROUND)
startActivity(intent)
Android may complain that your activity needs to inherit theme from Theme.AppCompat and you may also have difficulties loading an xml layout.
I believe your can work around those. Apart from that your are good to go.
And also note that i only tested it on Android 10 and below.
Right-click on the project, Select New >> Service >> Service and add the following to MyServices.java
public class MyService extends Service {
public MyService() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId){
onTaskRemoved(intent);
Toast.makeText(getApplicationContext(),"This is a Service running in Background",
Toast.LENGTH_SHORT).show();
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onTaskRemoved(Intent rootIntent) {
Intent restartServiceIntent = new Intent(getApplicationContext(),this.getClass());
restartServiceIntent.setPackage(getPackageName());
startService(restartServiceIntent);
super.onTaskRemoved(rootIntent);
}
}
Add the following code to res/layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="#+id/button"
android:text="Click here"
android:textStyle="bold"
android:textSize="16sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
</RelativeLayout>
Add the following code to src/MainActivity.java
public class MainActivity extends AppCompatActivity {
Button button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startService(new Intent(getApplicationContext(),MyService.class));
}
});
}
}
Add the following code to androidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.com.sample">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Let's try to run your application.
Click on the Click here button to start background services.
I'm trying to show GIF image by URL from JSON file. For that, I have function, which takes JSONObject and show image by Glide.
public class FragmentHandler extends Fragment implements View.OnClickListener {
private void showJsonContent(JSONObject jsonObject) throws JSONException {
if (jsonObject == null) return;
String gifLink = jsonObject.getString("gifURL");
String desc = jsonObject.getString("description");
captionTextView.setText(desc);
Glide.with(Objects.requireNonNull(getActivity())
.getApplicationContext())
.asGif()
.load(gifLink)
.listener(new RequestListener<GifDrawable>() {
#Override
public boolean onLoadFailed(GlideException e, Object model, Target<GifDrawable> target, boolean isFirstResource) {
progressBar.setVisibility(View.GONE);
return false;
}
#Override
public boolean onResourceReady(GifDrawable resource, Object model, Target<GifDrawable> target, DataSource dataSource, boolean isFirstResource) {
progressBar.setVisibility(View.GONE);
return false;
}
}).into(new ImageViewTarget<GifDrawable>(imageView) {
#Override
protected void setResource(GifDrawable resource) {
imageView.setImageDrawable(resource);
}
});
}
}
Progress Bar and ImageView in XML looks like that:
<ProgressBar
android:id="#+id/progress"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:visibility="visible" />
<ImageView
android:id="#+id/imageView"
android:layout_width="240dp"
android:layout_height="240dp"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:contentDescription="#string/gif_image" />
It works absolutely correct on Android 6 Pixel emulator (API 26), but with devices (physical and emulator) with a higher version, it doesn't show image. URL and JSON correct, because program prints message from another JSON field and I tried to debug it for the check.
I read really a lot of posts with a similar problem at StackOverflow and tried all suggestions, mostly concerning using asGif(). But it doesn't help. Are there any ways to solve this problem?
UPDATE:
Here is example of URL to the GIF image:
http://static.devli.ru/public/images/gifs/201402/90400af2-91c1-4f31-bf5e-b2561b598d7c.gif
And my AndroidManifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.gifapp">
<uses-feature android:name="android.hardware.wifi" android:required="true" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application
android:allowBackup="true"
android:fullBackupContent="#xml/my_backup_rules"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
During debugging I've discovered, that .listener calls onLoadFailed(...) method. So, after that, I stumbled to a suitable problem. On Android 7+ it caused because of new security configuration.
I'm new to Java and I was trying to make a simple program to display text when a button is pressed by using services. For some reason nothing happens when I press the "Start Service" and "Stop Service" buttons. Here's my code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startService(View view) {
startService(new Intent(getBaseContext(), MyService.class));
}
public void stopService(View view) {
stopService(new Intent(getBaseContext(), MyService.class));
}
public static class MyService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
}
}
And the buttons-
<Button
android:id="#+id/button"
android:layout_width="132dp"
android:layout_height="105dp"
android:layout_marginTop="8dp"
android:onClick="startService"
android:text="#string/Buttton1"
android:visibility="visible"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/button2"
android:layout_width="128dp"
android:layout_height="108dp"
android:layout_marginTop="8dp"
android:onClick="stopService"
android:text="#string/Button2"
android:visibility="visible"
app:layout_constraintHorizontal_bias="0.503"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/button" />
A few things wrong.
1: I don't think your service should be static.
2: Did you declare your service in your AndroidManifes.xml?
3: You don't need to use getBaseContext()
If you're in an activity use this
If you're in a fragment use getActivity()
So you have to declare all your services same as all your activities in the android manifest.To do that navigate to your apps manifest located under app>manifest>AndroidManifext.xml.Next, you need to add a service tag under application with the name of your service.
Example code:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.android.myapplication">
<application
android:allowBackup="false"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<service android:name=".MyService"/> <-----This is were you declared your service
<activity
android:name=".MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Everything should work fine after that.
I was using a fragment that's why it wasn't working. I used MainActivity and it worked. Thanks for the answers!
I want to integrate Google Mobile Ads into my app, but when I debug it, whenever using my own device, or using an emulator, no ads appear.
I am using the code from Google's developer page: https://developers.google.com/mobile-ads-sdk/docs/admob/fundamentals
When looking at logcat, I find that my app is not requesting any ads, and Admob is reporting no requests.
What am I missing?
Here is my code
AndroidManifest
<application android:icon="#drawable/ic_launcher">
<meta-data android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version"/>
android:label="#string/app_name" >
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.google.android.gms.ads.AdActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"/>
</application>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
</manifest>
layout - main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/adBanner"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads">
<com.google.ads.AdView android:id="#+id/ad"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
ads:adUnitId="-omitted-"
ads:adSize="BANNER" />
</LinearLayout>
AdBanner.java (the class with Google's example test code)
package com.google.android.gms.ads.banner;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdSize;
import com.google.android.gms.ads.AdView;
import -omitted-
import android.os.Bundle;
import android.widget.LinearLayout;
import -omitted-
public class AdBanner extends MainActivity{
/**
* A simple {#link Activity} that embeds an AdView.
*/
/** The view to show the ad. */
private AdView adView;
/* Your ad unit id. Replace with your actual ad unit id. */
private static final String AD_UNIT_ID = "-omitted-";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Create an ad.
adView = new AdView(this);
adView.setAdSize(AdSize.BANNER);
adView.setAdUnitId(AD_UNIT_ID);
// Add the AdView to the view hierarchy. The view will have no size
// until the ad is loaded.
LinearLayout layout = (LinearLayout) findViewById(R.id.adBanner);
layout.addView(adView);
// Create an ad request. Check logcat output for the hashed device ID to
// get test ads on a physical device.
AdRequest adRequest = new AdRequest.Builder()
.addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
.addTestDevice("-omitted-")
.build();
// Start loading the ad in the background.
adView.loadAd(adRequest);
}
#Override
public void onResume() {
super.onResume();
if (adView != null) {
adView.resume();
}
}
#Override
public void onPause() {
if (adView != null) {
adView.pause();
}
super.onPause();
}
/** Called before the activity is destroyed. */
#Override
public void onDestroy() {
// Destroy the AdView.
if (adView != null) {
adView.destroy();
}
super.onDestroy();
}
}
I have seen something strange in your code:
In your AdBanner.java you use this:
import com.google.android.gms.ads.AdView;
but in your layout you use:
<com.google.ads.AdView
which corresponds to old Admob, but seems you may want to use com.google.android.gms.ads.AdView in your layout instead
I think you must check the android logs to see if any errors or warnings are given for your admob. For example: I was not able to see the ads too and when i check the logs i found the "not enough space" warning for my advertisement. I was using the size "SMART_BANNER" that uses the width as 360dp (you can check the sizes here). So i changed my AdView's width to exact 360dp to solve my problem and it is now working: Stil
I hope this information helps. Just check the logs and also console.
In addition, my adView:
<com.google.android.gms.ads.AdView
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="#+id/adView"
android:layout_width="360dp"
android:layout_height="wrap_content"
ads:adSize="SMART_BANNER"
ads:adUnitId="#string/banner_ad_unit_id" />
Best regards.
I have a simple Activity that uses a android:theme="#android:style/Theme.Dialog" in the manifest.
My activity consists of an EditText, 2 Buttons, and a TextView. It is nothing more than a box for the user to enter in a name and press OK/Cancel.
I just want to focus the EditText and have the soft keyboard automatically show when the Activity is started. I've read countless posts about this but I just can't seem to get it to work. When the activity starts the blinking cursor appears in the EditText, but the keyboard won't show until I click inside it.
Here is my Activity:
public class Finalize extends Activity {
private EditText mEditName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.finalize_dialog);
mEditName = (EditText) findViewById(R.id.file_name_edit);
mEditName.setFocusable(true);
mEditName.requestFocus();
mEditName.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
}
});
}
}
I've also tried this in onCreate:
InputMethodManager mgr = (InputMethodManager) getSystemService(this.INPUT_METHOD_SERVICE);
mgr.showSoftInput(mEditName, 0);
Edit: My manifest for reference
<activity class=".Finalize"
android:name=".Finalize"
android:label="#string/file_name_title"
android:theme="#android:style/Theme.Dialog"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateAlwaysVisible">
</activity>
The following should work. Go to your manifest and update your activity line with the android:windowSoftInputMode attribute.
<activity android:name=".Finalize"
android:windowSoftInputMode="stateAlwaysVisible">
...
</activity>
See the following documentation page for more details on the different parameters that can be passed into this attribute.
I tested the above and it works fine for me. Here is my terribly simple example.
Code:
public class DialogActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
Layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello" />
<EditText android:id="#+id/edit_text_test"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
Manifest:
<activity android:name=".DialogActivity"
android:windowSoftInputMode="stateAlwaysVisible"
android:label="#string/app_name"
android:theme="#android:style/Theme.Dialog">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Try this its work for me
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED,0);