Extract only mp4 links by jsoup - hyperlink

I have aEditText to insert the URL, a button to lunch the HTML parsing and another EditText to show the results,
how to i extract a website source with jsoup only that links ended with .mp4 ?
This is my profile link:
https://www.instagram.com/p/BEZcgC8/
there is two same mp4 link...
<meta property="og:video" content="http://igcdn-videos-h-8-a.akamaihd.net
/hphotos-ak-xal1/t50.2886-16/13053343_16890256565548_842608422_n.mp4"
/>
<meta property="og:video:secure_url" content="https://igcdn-videos-
h-8-a.akamaihd.net/hphotos-ak-xal1/t50.2886-16
/13053343_16890911255689848_842608422_n.mp4" />
<meta property="og:video:type" content="video/mp4" />
I want results like this to EditText
https://example.com/ringuser.mp4
xml layout : activity_main.xml
<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"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="com.survivingwithandroid.jsoup.MainActivity">
<TextView android:id="#+id/txt1"
android:text="#string/app_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
style="#android:style/TextAppearance.Large"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/txt1"
android:layout_marginTop="20dp"
android:text="Website URL"
android:id="#+id/txt2"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/txt2"
android:ems="15"
android:id="#+id/edtURL"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/edtURL"
android:layout_centerHorizontal="true"
android:text="Get data!"
android:layout_marginTop="15dp"
android:id="#+id/btnGo"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/btnGo"
android:layout_marginTop="10dp"
android:text="Result data"
android:id="#+id/txt3"/>
<EditText
android:id="#+id/edtResp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/txt3"
android:inputType="textMultiLine"
android:lines="6"
android:editable="false"
android:layout_marginTop="10dp"/>
</RelativeLayout>
logcat:
09-12 19:38:35.148: D/NativeCrypto(22237): ssl=0x52f3ceb0 sslRead
buf=0x41837fd0 len=174,timeo=3000
09-12 19:38:35.149: D/NativeCrypto(22237): Doing SSL_Read()
ssl=0x52f3ceb0, appData=0x52f0eec0
09-12 19:38:35.149: D/NativeCrypto(22237): Returned from SSL_Read()
with result 174, error code 0
ssl=0x52f3ceb0, appData=0x52f0eec0
09-12 19:38:35.233: D/dalvikvm(22237): GC_FOR_ALLOC freed 849K, 25% free
3278K/4324K, paused 12ms,
total 12ms
09-12 19:38:35.309: D/NativeCrypto(22237): NativeCrypto_EVP_VerifyInit
ctx=0x52f2ec48
09-12 19:38:35.309: D/NativeCrypto(22237): NativeCrypto_EVP_VerifyInit
algorithmChars=RSA-SHA1
09-12 19:38:35.393: D/dalvikvm(22237): GC_FOR_ALLOC freed 856K, 21% free
3960K/5012K, paused 15ms,
total 15ms
09-12 19:38:35.551: D/MyTag(22237): Final links
09-12 19:38:36.477: I/SurfaceTextureClient(22237): [STC::queueBuffer]
(this:0x504d5528) fps:2.68,
dur:1491.40, max:498.01, min:102.51
09-12 19:38:37.487: I/SurfaceTextureClient(22237): [STC::queueBuffer]
(this:0x504d5528) fps:1.98,
dur:1009.32, max:512.27, min:497.04
09-12 19:38:38.978: I/SurfaceTextureClient(22237): [STC::queueBuffer]
(this:0x504d5528) fps:2.01,
dur:1491.22, max:497.44, min:496.74
09-12 19:38:39.987: I/SurfaceTextureClient(22237): [STC::queueBuffer]
(this:0x504d5528) fps:1.98,
dur:1009.04, max:512.26, min:496.77
09-12 19:38:41.494: I/SurfaceTextureClient(22237): [STC::queueBuffer]
(this:0x504d5528) fps:1.99,
dur:1507.38, max:513.62, min:495.68
09-12 19:38:42.984: I/SurfaceTextureClient(22237): [STC::queueBuffer]
(this:0x504d5528) fps:2.01,
dur:1489.89, max:497.03, min:496.14
09-12 19:38:43.994: I/SurfaceTextureClient(22237): [STC::queueBuffer]
(this:0x504d5528) fps:1.98,
dur:1009.40, max:513.22, min:496.18
09-12 19:38:45.500: I/SurfaceTextureClient(22237): [STC::queueBuffer]
(this:0x504d5528) fps:1.99,
dur:1506.13, max:512.60, min:496.73
09-12 19:38:46.990: I/SurfaceTextureClient(22237): [STC::queueBuffer]
(this:0x504d5528) fps:2.01,
dur:1490.53, max:497.36, min:496.37
09-12 19:38:48.000: I/SurfaceTextureClient(22237): [STC::queueBuffer]
(this:0x504d5528) fps:1.98,
dur:1009.87, max:513.21, min:496.66
09-12 19:38:49.009: I/SurfaceTextureClient(22237): [STC::queueBuffer]
(this:0x504d5528) fps:1.98,
dur:1008.96, max:512.33, min:496.63
09-12 19:38:50.500: I/SurfaceTextureClient(22237): [STC::queueBuffer]
(this:0x504d5528) fps:2.01,
dur:1491.21, max:497.98, min:495.79
09-12 19:38:51.510: I/SurfaceTextureClient(22237): [STC::queueBuffer]
(this:0x504d5528) fps:1.98,
dur:1009.38, max:512.70, min:496.68
09-12 19:38:53.016: I/SurfaceTextureClient(22237): [STC::queueBuffer]
(this:0x504d5528) fps:1.99,
dur:1505.97, max:512.45, min:496.70
09-12 19:38:55.516: I/SurfaceTextureClient(22237): [STC::queueBuffer]
(this:0x504d5528) fps:1.98,
dur:1009.17, max:512.00, min:497.17
09-12 19:38:34.789: D/NativeCrypto(22237): Doing SSL_Read()
ssl=0x52f3ceb0, appData=0x52f0eec0
09-12 19:38:34.789: D/NativeCrypto(22237): Returned from SSL_Read() with
result 1, error code 0
ssl=0x52f3ceb0, appData=0x52f0eec0
09-12 19:38:57.022: I/SurfaceTextureClient(22237): [STC::queueBuffer]
(this:0x504d5528) fps:1.99,
dur:1505.99, max:509.86, min:497.09
09-12 19:38:58.512: I/SurfaceTextureClient(22237): [STC::queueBuffer]
(this:0x504d5528) fps:2.01,
dur:1490.55, max:498.20, min:495.64
09-12 19:38:59.523: I/SurfaceTextureClient(22237): [STC::queueBuffer]
(this:0x504d5528) fps:1.98,
dur:1010.26, max:513.02, min:497.24
09-12 19:39:00.440: D/OpenGLRenderer(22237): Flushing caches (mode 0)
09-12 19:39:00.471: D/InputMethodManager(22237): deactivate the
inputconnection in
ControlledInputConnectionWrapper.
09-12 19:39:00.497: D/OpenGLRenderer(22237): Flushing caches (mode 0)
09-12 19:39:00.682: D/dalvikvm(22237): GC_FOR_ALLOC freed 1317K, 27%
free 4178K/5692K, paused 21ms,
total 21ms
09-12 19:39:00.716: V/PhoneWindow(22237): DecorView setVisiblity:
visibility = 4
09-12 19:39:00.720: V/PhoneWindow(22237): DecorView setVisiblity:
visibility = 0
09-12 19:39:00.721: W/IInputConnectionWrapper(22237): showStatusIcon on
inactive InputConnection
09-12 19:39:00.724: V/InputMethodManager(22237): Not IME target window,
ignoring
09-12 19:39:00.783: V/InputMethodManager(22237): onWindowFocus:
android.widget.EditText{41a17428
VFED..CL .F....ID 24,127-504,218 #7f09003e app:id/edtURL}
softInputMode=288 first=true flags=#1810100
New java by Davide Pastore but it doesnt show any result when press button...
public class MainActivity extends ActionBarActivity {
private EditText respText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final EditText edtUrl = (EditText) findViewById(R.id.edtURL);
Button btnGo = (Button) findViewById(R.id.btnGo);
respText = (EditText) findViewById(R.id.edtResp);
btnGo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String siteUrl = edtUrl.getText().toString();
( new ParseURL() ).execute(new String[]{siteUrl});
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is
present.
//getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private class ParseURL extends AsyncTask<String, Void, String> {
private String finalLinks;
#Override
protected String doInBackground(String... strings) {
StringBuffer buffer = new StringBuffer();
try {
Document doc = Jsoup.connect(strings[0]).get();
Elements mp4Links = doc.select("a[href$=.mp4]");
List<String> links = new ArrayList<String>();
for (Element mp4Link : mp4Links) {
String absHref = mp4Link.attr("abs:href");
links.add(absHref);
}
finalLinks = "";
for (String link : links) {
finalLinks += link + "\n";
}
Log.d("MyTag", "Final links " + finalLinks);
}
catch(Throwable t) {
t.printStackTrace();
}
return buffer.toString();
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
respText.setText(finalLinks);
}
}
}
old java
public class MainActivity extends Activity {
// URL Address
String url = "http://www.androidbegin.com";
ProgressDialog mProgressDialog;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Locate the Buttons in activity_main.xml
Button titlebutton = (Button) findViewById(R.id.titlebutton);
Button descbutton = (Button) findViewById(R.id.descbutton);
Button logobutton = (Button) findViewById(R.id.logobutton);
// Capture button click
titlebutton.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
// Execute Title AsyncTask
new Title().execute();
}
});
// Capture button click
descbutton.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
// Execute Description AsyncTask
new Description().execute();
}
});
// Capture button click
logobutton.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
// Execute Logo AsyncTask
new Logo().execute();
}
});
}
// Title AsyncTask
private class Title extends AsyncTask<Void, Void, Void> {
String title;
#Override
protected void onPreExecute() {
super.onPreExecute();
mProgressDialog = new ProgressDialog(MainActivity.this);
mProgressDialog.setTitle("Android Basic JSoup Tutorial");
mProgressDialog.setMessage("Loading...");
mProgressDialog.setIndeterminate(false);
mProgressDialog.show();
}
#Override
protected Void doInBackground(Void... params) {
try {
// Connect to the web site
Document document = Jsoup.connect(url).get();
// Get the html document title
title = document.title();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
// Set title into TextView
TextView txttitle = (TextView) findViewById(R.id.titletxt);
txttitle.setText(title);
mProgressDialog.dismiss();
}
}
// Description AsyncTask
private class Description extends AsyncTask<Void, Void, Void> {
String desc;
#Override
protected void onPreExecute() {
super.onPreExecute();
mProgressDialog = new ProgressDialog(MainActivity.this);
mProgressDialog.setTitle("Android Basic JSoup Tutorial");
mProgressDialog.setMessage("Loading...");
mProgressDialog.setIndeterminate(false);
mProgressDialog.show();
}
#Override
protected Void doInBackground(Void... params) {
try {
// Connect to the web site
Document document = Jsoup.connect(url).get();
// Using Elements to get the Meta data
Elements description = document
.select("meta[name=description]");
// Locate the content attribute
desc = description.attr("content");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
// Set description into TextView
TextView txtdesc = (TextView) findViewById(R.id.desctxt);
txtdesc.setText(desc);
mProgressDialog.dismiss();
}
}
// Logo AsyncTask
private class Logo extends AsyncTask<Void, Void, Void> {
Bitmap bitmap;
#Override
protected void onPreExecute() {
super.onPreExecute();
mProgressDialog = new ProgressDialog(MainActivity.this);
mProgressDialog.setTitle("Android Basic JSoup Tutorial");
mProgressDialog.setMessage("Loading...");
mProgressDialog.setIndeterminate(false);
mProgressDialog.show();
}
#Override
protected Void doInBackground(Void... params) {
try {
// Connect to the web site
Document document = Jsoup.connect(url).get();
// Using Elements to get the class data
Elements img = document.select("a[class=brand brand-image]
img[src]");
// Locate the src attribute
String imgSrc = img.attr("src");
// Download image from URL
InputStream input = new java.net.URL(imgSrc).openStream();
// Decode Bitmap
bitmap = BitmapFactory.decodeStream(input);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
// Set downloaded image into ImageView
ImageView logoimg = (ImageView) findViewById(R.id.logo);
logoimg.setImageBitmap(bitmap);
mProgressDialog.dismiss();
}

Update 2
Just edit the CSS query to get what you prefer.
public class MainActivity extends AppCompatActivity {
private EditText respText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final EditText edtUrl = (EditText) findViewById(R.id.edtURL);
Button btnGo = (Button) findViewById(R.id.btnGo);
respText = (EditText) findViewById(R.id.edtResp);
btnGo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String siteUrl = edtUrl.getText().toString();
( new ParseURL() ).execute(new String[]{siteUrl});
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
//getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private class ParseURL extends AsyncTask<String, Void, String> {
private String finalLinks;
#Override
protected String doInBackground(String... strings) {
StringBuffer buffer = new StringBuffer();
try {
Document doc = Jsoup.connect(strings[0]).get();
Elements mp4Links = doc.select("meta[content$=.mp4]");
List<String> links = new ArrayList<String>();
for (Element mp4Link : mp4Links) {
String absHref = mp4Link.attr("content");
links.add(absHref);
}
finalLinks = "";
for (String link : links) {
finalLinks += link + "\n";
}
Log.d("MyTag", "Final links " + finalLinks);
}
catch(Throwable t) {
t.printStackTrace();
}
return buffer.toString();
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
respText.setText(finalLinks);
}
}
}
Update
A complete example could be:
public class MainActivity extends AppCompatActivity {
private EditText respText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final EditText edtUrl = (EditText) findViewById(R.id.edtURL);
Button btnGo = (Button) findViewById(R.id.btnGo);
respText = (EditText) findViewById(R.id.edtResp);
btnGo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String siteUrl = edtUrl.getText().toString();
( new ParseURL() ).execute(new String[]{siteUrl});
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
//getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private class ParseURL extends AsyncTask<String, Void, String> {
private String finalLinks;
#Override
protected String doInBackground(String... strings) {
StringBuffer buffer = new StringBuffer();
try {
Document doc = Jsoup.connect(strings[0]).get();
Elements mp4Links = doc.select("a[href$=.mp4],meta[property=og:video],meta[property=og:video:secure_url]");
List<String> links = new ArrayList<String>();
for (Element mp4Link : mp4Links) {
String absHref = mp4Link.attr("abs:href");
links.add(absHref);
}
finalLinks = "";
for (String link : links) {
finalLinks += link + "\n";
}
Log.d("MyTag", "Final links " + finalLinks);
}
catch(Throwable t) {
t.printStackTrace();
}
return buffer.toString();
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
respText.setText(finalLinks);
}
}
}
Old
Let's say you have a HTML like this:
<html>
<head>
<title>Try jsoup</title>
</head>
<body>
<p>This is jsoup.</p>
mp4 1
mp4 2
mp4 3
mp4 4
ciao
</body>
</html>
You can retrieve all the links that ends with .mp4 using this code:
Elements mp4Links = doc.select("a[href$=.mp4]");
List<String> links = new ArrayList<String>();
for (Element mp4Link : mp4Links) {
String absHref = mp4Link.attr("abs:href");
links.add(absHref);
}
//Do your magic with the links List...
links will contain:
https://example.com/ringuser.mp4
https://example.com/ringuser_2.mp4
https://example.com/ringuser_3.mp4
https://example.com/ringuser_4.mp4

To filter HTML hyperlinks with a specific file extension using jsoup have a look at the following code:
Java code
String url = "http://www.sample-videos.com/";
Map<String, String> fileMap = new HashMap<String, String>();
String extensionFilter = ".mp4";
try {
Document doc = Jsoup.connect(url)
.userAgent("Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36")
.get();
url = url.endsWith("/") ? url : url + "/";
String fileUrl = null;
for (Element result : doc.select("a")) { // select all <a> tags
if ((fileUrl = result.attr("href")).contains(extensionFilter)) { // filter <a> tags with defined extension
if (!fileUrl.startsWith("http")) {
fileUrl = fileUrl.startsWith("/") ? url + fileUrl.substring(1, fileUrl.length() - 1) : url + fileUrl;
}
fileMap.put(fileUrl, fileUrl.substring(fileUrl.lastIndexOf("/")+1));
}
}
for (String file : fileMap.keySet()) { // do something useful with the extracted mp3 urls, e.g. downloading the files
System.out.println(fileMap.get(file) + "->" + file);
org.apache.commons.io.FileUtils.copyURLToFile(new URL(file), new File(fileMap.get(file)));
}
} catch (IOException e) {
e.printStackTrace();
}
Output
big_buck_bunny_240p_2mb.mp4->http://www.sample-videos.com/video/mp4/240/big_buck_bunny_240p_2mb.mp4
big_buck_bunny_720p_2mb.mp4->http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_2mb.mp4
big_buck_bunny_480p_2mb.mp4->http://www.sample-videos.com/video/mp4/480/big_buck_bunny_480p_2mb.mp4
big_buck_bunny_720p_10mb.mp4->http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_10mb.mp4
...

Related

Multi Select Spinner Xamarin Android

I am using a spinner and an arrayAdapter to populate items in spinner. I want to make the spinner multi-selectable but I just select one row.I searched in Google, solution available in Java, but i don't have any idea on how to implement it in Xamarin.
My code is as below,
adapterList= new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItemMultipleChoice);
spnMultiTest.Adapter = adapterList;
I want to make the spinner multi-selectable but I just select one row.I searched in Google, solution available in Java, but i don't have any idea on how to implement it in Xamarin.
Basically I just translate the codes from Android Spinner with multiple choice
to Xamarin codes. I have tested it and it works fine:
MultiSpinner.cs:
public interface MultiSpinnerListener
{
void onItemsSelected(bool[] selected);
}
public class MultiSpinner : Spinner, IDialogInterfaceOnMultiChoiceClickListener, IDialogInterfaceOnCancelListener
{
Context _context;
private List<String> items;
private bool[] selected;
private String defaultText;
private MultiSpinnerListener listener;
public MultiSpinner(Context context) : base(context)
{
_context = context;
}
public MultiSpinner(Context context, IAttributeSet arg1) : base(context, arg1)
{
_context = context;
}
public MultiSpinner(Context context, IAttributeSet arg1, int arg2) : base(context, arg1, arg2)
{
_context = context;
}
public void OnClick(IDialogInterface dialog, int which, bool isChecked)
{
if (isChecked)
selected[which] = true;
else
selected[which] = false;
}
public override void OnClick(IDialogInterface dialog, int which)
{
dialog.Cancel();
}
public override bool PerformClick()
{
AlertDialog.Builder builder = new AlertDialog.Builder(_context);
builder.SetMultiChoiceItems(
items.ToArray(), selected, this);
builder.SetPositiveButton("OK",this);
builder.SetOnCancelListener(this);
builder.Show();
return true;
}
public void SetItems(List<String> items, String allText,
MultiSpinnerListener listener)
{
this.items = items;
this.defaultText = allText;
this.listener = listener;
// all selected by default
selected = new bool[items.Count];
for (int i = 0; i < selected.Length; i++)
selected[i] = true;
ArrayAdapter<string> adapter = new ArrayAdapter<string>(_context,Resource.Layout.simple_spinner_item,Resource.Id.tv_item,new string[] { allText });
// all text on the spinner
//ArrayAdapter<String> adapter = new ArrayAdapter<String>(_context,Resource.Layout.simple_spinner_item, new String[] { allText });
Adapter = adapter;
}
public void OnCancel(IDialogInterface dialog)
{
Java.Lang.StringBuffer spinnerBuffer = new Java.Lang.StringBuffer();
bool someUnselected = false;
for (int i = 0; i < items.Count; i++)
{
if (selected[i] == true)
{
spinnerBuffer.Append(items[i]);
spinnerBuffer.Append(", ");
}
else
{
someUnselected = true;
}
}
String spinnerText;
if (someUnselected)
{
spinnerText = spinnerBuffer.ToString();
if (spinnerText.Length > 2)
spinnerText = spinnerText.Substring(0, spinnerText.Length - 2);
}
else
{
spinnerText = defaultText;
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(_context,Resource.Layout.simple_spinner_item,Resource.Id.tv_item,new string[] { spinnerText });
Adapter = adapter;
if (listener != null)
{
listener.onItemsSelected(selected);
}
}
}
simple_spinner_item.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/tv_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
Update:
Here is the codes for using this MultiSpinner:
Main.axml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<MultiSpinner.MultiSpinner
android:id="#+id/mSpinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
MainActivity.cs:
public class MainActivity : Activity
{
MultiSpinner mSpinner;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
mSpinner = FindViewById<MultiSpinner>(Resource.Id.mSpinner);
List<string> items = new List<string> {
"Android",
"iOS",
"UWP"
};
mSpinner.SetItems(items, "AllText", null);
}
}

populate images with firebase recycler adapter through databinding

I am populating a firebase data with firebase recycler adapter through databinding and want to populate images with the data either from Picasso or Glide, but unable to do. So can any one help me what to write and where to write the code of either Picasso or Glide.
public class ShopByCategoryFragment extends Fragment {
FirebaseRecyclerAdapter adapter;
Firebase mFirebaseRef = new Firebase("https://abc.firebaseio.com/").child("subCategories");
public ShopByCategoryFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.recycler_view, container, false);
final RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
adapter = new FirebaseRecyclerAdapter<SubCategories, ViewHolder>(SubCategories.class, R.layout.fragment_shop_by_category,
ViewHolder.class, mFirebaseRef) {
#Override
protected void populateViewHolder(ViewHolder viewHolder, SubCategories subCategories, int i) {
FragmentShopByCategoryBinding binding = viewHolder.getBinding();
binding.setSubCategories(subCategories);
}
};
recyclerView.setAdapter(adapter);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 2));
return rootView;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public FragmentShopByCategoryBinding binding;
public ViewHolder(View itemView) {
super(itemView);
binding = DataBindingUtil.bind(itemView);
}
public FragmentShopByCategoryBinding getBinding() {
return binding;
}
}
#Override
public void onDestroy() {
super.onDestroy();
adapter.cleanup();
}
}
<layout xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="SubCategories"
type="com.abc.www.shopping.model.SubCategories"/>
</data>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="wrap_content"
android:layout_height="#dimen/tile_height"
android:id="#+id/sub_category_image"
android:scaleType="centerCrop"
android:src="#{SubCategories.image}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="#dimen/tile_height"
android:text="#{SubCategories.title}"
android:id="#+id/sub_category_title"
android:padding="16dp"
android:textColor="#color/colorSubCategoryTitle"
android:layout_gravity="center"
android:textAppearance="#android:style/TextAppearance.Material.Title"
tools:targetApi="lollipop" />
</FrameLayout>
</android.support.v7.widget.CardView>
public class SubCategories extends BaseObservable {
private String title;
private String image;
public SubCategories() {
// empty constructor
}
public SubCategories(String title, String image) {
this.title = title;
this.image = image;
}
public String getTitle() {
return title;
}
public String getImage() {
return image;
}
}
I have made something similar to what you need. I'll share my code and do a little explanation.
I have a class that returns the FirebaseRecyclerAdapter like this:
public RecyclerView.Adapter postAdapter(String userKey, final Context context, MyClickListener clickListener) {
Query userPostRef = postRef.child(userKey);
myClickListener = clickListener;
return new FirebaseRecyclerAdapter<PostModel, DataObjectHolder>(PostModel.class, R.layout.stream_layout, DataObjectHolder.class, userPostRef) {
#Override
public void populateViewHolder(final DataObjectHolder dataviewHolder, final PostModel postModel, int position) {
StorageReference mStorageRef = FirebaseStorage.getInstance().getReference();
mStorageRef.child("uploaded_captures/" + postModel.getImageFilename() + ".jpg").getDownloadUrl()
.addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
dataviewHolder.setImage(uri.toString(), context);
dataviewHolder.setComment(postModel.getPostComment());
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
Log.e("FirebaseRecyclerAdapter", exception.getMessage());
}
});
}
};
}
and a ViewHolder that loads the image into the ImageView used by the layout:
private static class DataObjectHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
View mView;
public DataObjectHolder(View itemView) {
super(itemView);
mView = itemView;
}
void setImage(final String imageURL, final Context context) {
final ImageView postImage = (ImageView) mView.findViewById(R.id.imageView);
if (BuildConfig.DEBUG) {
Picasso.with(context).setIndicatorsEnabled(true);
}
Picasso.with(context)
.load(imageURL)
.networkPolicy(NetworkPolicy.OFFLINE)
.placeholder(R.drawable.ic_menu_camera)
.fit().centerCrop().into(postImage, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
Picasso.with(context)
.load(imageURL)
.placeholder(R.drawable.ic_menu_camera)
.fit().centerCrop().into(postImage);
}
});
}
void setComment(String text) {
TextView comment = (TextView) mView.findViewById(R.id.comment);
comment.setText(text);
}
#Override
public void onClick(View v) {
myClickListener.onItemClick(getAdapterPosition(), v);
}
}
On Picasso I'm using the NerworkPolicy.OFFLINE to check if the image is on the disk cache before trying to get it from the network. It's not perfect and I'm still having some issues with the delay of the images once the ViewHolder it's been recycled but I think it's a start for you to go on.
In my ViewHolder I do this by:
Glide.with(context)
.load(chat.getImageUrl())
.into(imageView);
I haven't tried using data binding for this yet, but the code is simple enough.

Android: Captured image is zero bytes when saved

I'm very new to Android and am trying to do something simple: using the camera API, I want to capture an image and save it to a directory.
I think my main problem is with the picturecallback() class. With this code I am able to save a jpeg image to a known directory on my SD card. I can see that it's in the correct location; however, the file size is 0 bytes and cannot be opened.
Here's my code:
PictureCallback myPictureCallback_JPG = new PictureCallback(){
#Override
public void onPictureTaken(byte[] arg0, Camera arg1) {
// TODO Auto-generated method stub
if (arg0 == null){
Toast.makeText(AndroidCamera.this,
"Image not saved. ",
Toast.LENGTH_LONG).show();
return;
//Why is it returning NULL the first time and a 0-byte thing next...
}
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null){
System.out.println("Error creating media file, check storage permissions: ");
return;
}
//
Uri uriTarget = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, new ContentValues());
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(arg0);
fos.close();
Toast.makeText(AndroidCamera.this,
"Image saved: " + uriTarget.toString(),
Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
camera.startPreview();
}};
When going through the debugger, the byte array arg0 seems to contain a lot of random numbers from -255 to 255. I'm not sure why any image values would apear negative other than that they were not actually captured correctly in the first place (capturing happens in oncreate).
Here is the main class:
package com.example.androidcamera;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
//import com.example.androidcamera.R;
import android.app.Activity;
import android.content.ContentValues;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore.Images.Media;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Toast;
public class AndroidCamera extends Activity implements SurfaceHolder.Callback{
Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
boolean previewing = false;
LayoutInflater controlInflater = null;
Button buttonTakePicture;
final int RESULT_SAVEIMAGE = 0;
public static final int MEDIA_TYPE_IMAGE = 1;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
getWindow().setFormat(PixelFormat.UNKNOWN);
surfaceView = (SurfaceView)findViewById(R.id.camerapreview);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
controlInflater = LayoutInflater.from(getBaseContext());
View viewControl = controlInflater.inflate(R.layout.control, null);
LayoutParams layoutParamsControl
= new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT);
this.addContentView(viewControl, layoutParamsControl);
buttonTakePicture = (Button)findViewById(R.id.takepicture);
buttonTakePicture.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
//camera.takePicture(myShutterCallback,
//myPictureCallback_JPG, myPictureCallback_JPG);
camera.takePicture(null, null, myPictureCallback_JPG);
}
});
LinearLayout layoutBackground = (LinearLayout)findViewById(R.id.background);
layoutBackground.setOnClickListener(new LinearLayout.OnClickListener(){
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
buttonTakePicture.setEnabled(false);
camera.autoFocus(myAutoFocusCallback);
//camera.
}});
}
AutoFocusCallback myAutoFocusCallback = new AutoFocusCallback(){
#Override
public void onAutoFocus(boolean arg0, Camera arg1) {
// TODO Auto-generated method stub
buttonTakePicture.setEnabled(true);
}};
ShutterCallback myShutterCallback = new ShutterCallback(){
#Override
public void onShutter() {
// TODO Auto-generated method stub
}};
PictureCallback myPictureCallback_RAW = new PictureCallback(){
#Override
public void onPictureTaken(byte[] arg0, Camera arg1) {
// TODO Auto-generated method stub
}};
PictureCallback myPictureCallback_JPG = new PictureCallback(){
#Override
public void onPictureTaken(byte[] arg0, Camera arg1) {
// TODO Auto-generated method stub
if (arg0 == null){
Toast.makeText(AndroidCamera.this,
"Image not saved. ",
Toast.LENGTH_LONG).show();
return;
//Why is it returning NULL the first time and a 0-byte thing next...
}
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null){
System.out.println("Error creating media file, check storage permissions: ");
return;
}
//
Uri uriTarget = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, new ContentValues());
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(arg0);
fos.close();
Toast.makeText(AndroidCamera.this,
"Image saved: " + uriTarget.toString(),
Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
camera.startPreview();
}};
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
if(previewing){
camera.stopPreview();
previewing = false;
}
if (camera != null){
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
previewing = true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
camera = Camera.open();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
camera.stopPreview();
camera.release();
camera = null;
previewing = false;
}
/** Create a File for saving an image or video */
private static File getOutputMediaFile(int type){
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyCameraApp");
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE){
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
} else {
return null;
}
return mediaFile;
}
#Override
protected void onPause() {
super.onPause();
releaseCamera(); // release the camera immediately on pause event
}
private void releaseCamera(){
if (camera != null){
camera.release(); // release the camera for other applications
camera = null;
}
}
}
My AndroidManifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidcamera"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="#drawable/ic_launcher" android:label="#string/app_name">
<activity android:name="AndroidCamera"
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>
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.CAMERA"></uses-permission>
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera.autofocus" />
</manifest>
And finally my main xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/background"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="bottom"
>
<Button
android:id="#+id/takepicture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" * Take Picture "
android:layout_gravity="right"
android:layout_margin="10dp"
/>
</LinearLayout>
Many thanks in advance.
Don't worry if the numbers in arg0[] look strange. This is because Java does not have an unsigned byte primitive data type.
In your file saving code, note that you display the Toast
"Image saved: " + uriTarget.toString()
while write() actually happens to
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
Probably you will find that the images are stored, but not where you expected them.

Struts2 ActionContext and Response for chaining actions

I have a pretty complex problem about struts2 chaining actions, thanks in advance for your patience reading my problem. I will try my best to describe it clearly.
Below is my struts.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.enable.SlashesInActionNames" value="true" />
<constant name="struts.devMode" value="false" />
<package name="default" extends="struts-default" namespace="/">
<action name="test" class="com.bv.test.TestAction1" >
<result name="success" type="chain">y</result>
</action>
<action name="x">
<result name="success">/index.jsp</result>
</action>
<action name="y" class="com.bv.test.TestAction2">
<result name="success">/index.jsp</result>
</action>
</package>
</struts>
My logic is like this:
When accessing to /myapp/test, TestAction1 will handle the request;
In TestAction1, I "include" action x (my 2nd action in my config) like this:
ResponseImpl myResponse = new ResponseImpl(response);
RequestDispatcher rd = request.getRequestDispatcher("/x.action");
rd.include(request, myResponse);
And the important thing is I am using a customized ResponseIml when including "x.action".
After including, I return "success", so the result chains to action y (3rd action in my config);
And at last, TestAction2 continue to handle the request, it will go to success result, and the jsp should be rendered, but what I see is a blank page.
The jsp file is very simple:
index.jsp
<h1>Test!</h1>
My question/puzzle is:
In TestAction1, if I get the response from ServletActionContext, I
am getting different ones before and after including; before
including is the default response, but after including I got an
instance of my customized ResponseImpl; I expect to get the same
one: i.e.: the default response;
In TestAction2, I get response from ServletActionContext, what I got
is the instance of my customized ResponseIml. This is my most important thing, I think I should get a default response instance here, i.e.: org.apache.catalina.connector.Response, I am running on JBoss;
I am getting a different ActionContext in TestAction2 (compared with
the ActionContext I get in TestAction1).
This problem really drive me on the nuts, I have spent days on it.
Any advice will be appreciated!
Thanks a million!!
My Code:
TestAction1:
public class TestAction1 {
public String execute() {
ActionContext ac = ActionContext.getContext();
System.out.println("Before including: the action context is : " + ac);
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
System.out.println("Before including: the response is : " + response);
ResponseImpl myResponse = new ResponseImpl(response);
RequestDispatcher rd = request.getRequestDispatcher("/x.action");
try {
rd.include(request, myResponse);
String s = myResponse.getOutput();
System.out.println("get from response: " + s);
}
catch (Exception e) {
e.printStackTrace();
}
ac = ActionContext.getContext();
System.out.println("After including : the action context is : " + ac);
response = ServletActionContext.getResponse();
System.out.println("After including : the response is : " + response);
return "success";
}
}
ResponseImpl:
import java.util.Locale;
import java.io.StringWriter;
import java.io.PrintWriter;
import java.io.OutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import javax.servlet.http.Cookie;
import javax.servlet.jsp.JspWriter;
/**
*
*
*/
public class ResponseImpl extends HttpServletResponseWrapper {
//=========================================================
// Private fields.
//=========================================================
private ServletOutputStream outputStream = null;
private ByteArrayOutputStream byteArrayOutputStream = null;
private StringWriter stringWriter = null;
private PrintWriter printWriter = null;
private HttpServletResponse _response = null;
private String contentType= "text/html";
private String encoding = "UTF-8";
/**
*
*/
class ServletOutputStream extends javax.servlet.ServletOutputStream {
private OutputStream outputStream = null;
/**
*
*/
ServletOutputStream(ByteArrayOutputStream outputStream) {
super();
this.outputStream = outputStream;
}
/**
*
*/
public void write(int b) throws IOException {
this.outputStream.write(b);
}
}
//=========================================================
// Public constructors and methods.
//=========================================================
/**
*
*/
public ResponseImpl(HttpServletResponse response) {
super(response);
this._response = response;
}
/**
*
*/
public String getOutput() {
if (this.stringWriter != null) {
return this.stringWriter.toString();
}
if (this.byteArrayOutputStream != null) {
try {
return this.byteArrayOutputStream.toString(this.encoding);
}
catch (UnsupportedEncodingException e) {
}
return this.byteArrayOutputStream.toString();
}
return null;
}
//=========================================================
// Implements HttpServletResponse interface.
//=========================================================
public void addCookie(Cookie cookie) {
}
public void addDateHeader(String name, long date) {
}
public void addHeader(String name, String value) {
}
public void addIntHeader(String name, int value) {
}
public boolean containsHeader(String name) {
return false;
}
public String encodeRedirectURL(String url) {
if (null != this._response) {
url = this._response.encodeRedirectURL(url);
}
return url;
}
public String encodeURL(String url) {
if (null != this._response) {
url = this._response.encodeURL(url);
}
return url;
}
public void sendError(int sc) {
}
public void sendError(int sc, String msg) {
}
public void sendRedirect(String location) {
}
public void setDateHeader(String name, long date) {
}
public void setHeader(String name, String value) {
}
public void setIntHeader(String name, int value) {
}
public void setStatus(int sc) {
}
public void resetBuffer() {
}
//=========================================================
// Implements deprecated HttpServletResponse methods.
//=========================================================
public void setStatus(int sc, String sm) {
}
//=========================================================
// Implements deprecated HttpServletResponse methods.
//=========================================================
public String encodeRedirectUrl(String url) {
return encodeRedirectURL(url);
}
public String encodeUrl(String url) {
return encodeURL(url);
}
//=========================================================
// Implements ServletResponse interface.
//=========================================================
public void flushBuffer() {
}
public int getBufferSize() {
return 0;
}
public String getCharacterEncoding() {
return this.encoding;
}
public String getContentType() {
return this.contentType;
}
public Locale getLocale() {
return null;
}
public javax.servlet.ServletOutputStream getOutputStream() {
if (this.outputStream == null) {
this.byteArrayOutputStream = new ByteArrayOutputStream();
this.outputStream =
new ServletOutputStream(this.byteArrayOutputStream);
}
return this.outputStream;
}
public PrintWriter getWriter() {
if (this.printWriter == null) {
this.stringWriter = new StringWriter();
this.printWriter = new PrintWriter(this.stringWriter);
}
return this.printWriter;
}
public boolean isCommitted() {
return true;
}
public void reset() {
}
public void setBufferSize(int size) {
}
public void setCharacterEncoding(String charset) {
}
public void setContentLength(int len) {
}
public void setContentType(String type) {
int needle = type.indexOf(";");
if (-1 == needle) {
this.contentType = type;
}
else {
this.contentType = type.substring(0, needle);
String pattern = "charset=";
int index = type.indexOf(pattern, needle);
if (-1 != index) {
this.encoding = type.substring(index + pattern.length());
}
}
}
public void setLocale(Locale locale) {
}
}
TestAction2:
public class TestAction2 {
public String execute() {
ActionContext ac = ActionContext.getContext();
System.out.println("In TestAction 2 : the action context is : " + ac);
HttpServletResponse response = ServletActionContext.getResponse();
System.out.println("In TestAction 2 : the response is : " + response);
return "success";
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Struts2 Application</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
</web-app>
This is my debug info.
Before including: the action context is
:com.opensymphony.xwork2.ActionContext#c639ce
Before including: the response is :
org.apache.catalina.connector.ResponseFacade#8b677f
get from response: <h1>Test!</h1>
After including : the action context is :
com.opensymphony.xwork2.ActionContext#2445d7
After including : the response is : com.bv.test.ResponseImpl#165547d
In TestAction 2 : the action context is
:com.opensymphony.xwork2.ActionContext#19478c7
In TestAction 2 : the response is : com.bv.test.ResponseImpl#165547d
So, I have different ActionContext instances before and after the including!!
When you do rd.include another request is fired internally inside the web server. So from struts point of view it sees a completely new request and a new action context is created as a result. (that's why you need to include 'INCLUDE' thing on the struts2 filter.. so that it's seeing included requests as well). Probably since thread local variables are used to track action context and all that when you do ActionContext.getContext() the context related to the new request (related to the include) gets retrieved.
Did you try resetting the response to the initial one in a finally block like below
try {
rd.include(request, myResponse);
String s = myResponse.getOutput();
System.out.println("get from response: " + s);
}
catch (Exception e) {
e.printStackTrace();
} finally {
ServletActionContext.setResponse(response);
}
If this resolves the response issue.. you could probably store the string 's' as a variable in the action context and retrieve it inside your Action2
You could also try the following as well. Instead of using chaining.. inside your TestAction1 include the TestAction2 with the original response. return 'none' from the action as the return value.
public class TestAction1 {
public String execute() {
ActionContext ac = ActionContext.getContext();
System.out.println("Before including: the action context is : " + ac);
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
System.out.println("Before including: the response is : " + response);
ResponseImpl myResponse = new ResponseImpl(response);
RequestDispatcher rd = request.getRequestDispatcher("/x.action");
try {
rd.include(request, myResponse);
String s = myResponse.getOutput();
System.out.println("get from response: " + s);
}
catch (Exception e) {
e.printStackTrace();
}
RequestDispatcher rd = request.getRequestDispatcher("/y.action");
try {
rd.include(request, response);
}
catch (Exception e) {
e.printStackTrace();
} finally {
return "none";
}
}
}

BrowserField and lost connection

I have an app that uses a browserfield to connect to a web-page.
All is working ok and the simulator shows the right page.
If I set the simulator Network Properties to "Out of Coverage" and click on a link in my web-page then I get an exception - in the BrowserFieldConnectionManagerImpl
How can catch this exception so I can take appropriate action?
The app is using BlackBerry SDK
The code is here:
public final class example_Screen extends MainScreen {
// Create the ErrorHandler class
public class MyBrowserFieldErrorHandler extends BrowserFieldErrorHandler {
protected MyBrowserFieldErrorHandler(BrowserField browserField){
super(browserField);
}
public void displayContentError(String url, String errorMessage) {
System.out.println("JERRY: displayContentError" + url);
System.out.println("JERRY: displayContentError" + errorMessage);
}
public void displayContentError(String url, InputConnection connection, Throwable t) {
displayContentError(url, t.getMessage());
}
public void navigationRequestError(BrowserFieldRequest request, Throwable t) {
displayContentError(request.getURL(), t.getMessage());
}
public void requestContentError(BrowserFieldRequest request, Throwable t) {
displayContentError(request.getURL(), t.getMessage());
}
public InputConnection resourceRequestError(BrowserFieldRequest request, Throwable t) {
displayContentError(request.getURL(), t.getMessage());
InputConnection connection = null;
return connection;
}
}
/**
* Creates a new example_Screen object
*/
public example_Screen() {
GIFEncodedImage ourAnimation = (GIFEncodedImage) GIFEncodedImage.getEncodedImageResource("2.gif");
AnimatedGIFField _ourAnimation = new AnimatedGIFField(ourAnimation, Field.FIELD_HCENTER + Field.FIELD_VCENTER);
this.add(_ourAnimation);
LabelField _ourLabelField = new LabelField("Updating ...", Field.FIELD_HCENTER + Field.FIELD_VCENTER);
this.add(_ourLabelField);
int anim_ht = _ourAnimation.getPreferredHeight();
int label_ht = _ourLabelField.getPreferredHeight();
EncodedImage ei = EncodedImage.getEncodedImageResource("img/menu.png");
int currentWidthFixed32 = Fixed32.toFP(ei.getWidth());
int currentHeightFixed32 = Fixed32.toFP(ei.getHeight());
int displayWidthFixed32 = Fixed32.toFP(Display.getWidth());
int displayHeightFixed32 = Fixed32.toFP((Display.getHeight() - anim_ht - label_ht));
int scaleXFixed32 = Fixed32.div(currentWidthFixed32, displayWidthFixed32);
int scaleYFixed32 = Fixed32.div(currentHeightFixed32, displayHeightFixed32);
ei = ei.scaleImage32(scaleXFixed32, scaleYFixed32);
BitmapField bmp = new BitmapField(ei.getBitmap(), Field.FIELD_HCENTER + Field.FIELD_VCENTER);
add(bmp);
BrowserFieldConfig myBrowserFieldConfig = new BrowserFieldConfig();
myBrowserFieldConfig.setProperty(BrowserFieldConfig.NAVIGATION_MODE, BrowserFieldConfig.NAVIGATION_MODE_POINTER);
BrowserField browserField = new BrowserField(myBrowserFieldConfig);
add(browserField);
browserField.requestContent("http://www.bbc.co.uk");
BrowserFieldListener listener = new BrowserFieldListener() {
public void documentAborted(BrowserField browserField, Document document) {
System.out.println("JERRY: documentAborted");
}
public void documentCreated(BrowserField browserField, ScriptEngine scriptEngine, Document document) {
System.out.println("JERRY: documentCreated");
}
public void documentError(BrowserField browserField, Document document) {
System.out.println("JERRY: documentError");
}
public void documentLoaded(BrowserField browserField, Document document) {
System.out.println("JERRY: documentLoaded");
Node node = document.getFirstChild();
String nodeText = node.getTextContent();
int index = -1;
if (nodeText != null) {
String errorText = "Error requesting content for:";
index = nodeText.indexOf(errorText);
}
Screen screen = browserField.getScreen();
try {
synchronized (Application.getEventLock()) {
if (index == -1) {
System.out.println("JERRY: documentLoaded: no error");
int count = screen.getFieldCount();
if (count > 1) {
screen.deleteRange(0, (count-1));
System.out.println("JERRY: documentLoaded: " + (count-1) + " fields deleted");
} else {
System.out.println("JERRY: documentLoaded: only 1 field so none deleted");
}
} else {
System.out.println("JERRY: documentLoaded: error");
}
}
} catch (final Exception ex) {
System.out.println("example_Screen: documentLoaded: exception caught: " + ex.toString());
}
}
public void documentUnloading(BrowserField browserField, Document document) {
System.out.println("JERRY: documentUnloading");
}
public void downloadProgress(BrowserField browserField, ContentReadEvent event) {
System.out.println("JERRY: downloadProgress");
}
};
browserField.addListener(listener);
// Attach the Error Handler to the BrowserField
BrowserFieldErrorHandler eHandler = new MyBrowserFieldErrorHandler(browserField);
browserField.getConfig().setProperty(BrowserFieldConfig.ERROR_HANDLER, eHandler);
}
}
BrowserField contains a method, addListener() which takes a reference to BrowserFieldListener implementation.
Extend BrowserFieldListener and process errors in methods documentError() and documentAborted() of this implementation.
Then add a reference of your class instance that extends BrowserFieldListener to your browser field via browserField.addListener(browserFieldListener);.
EDIT:
If this does not work, then use BrowserFieldErrorHandler class from RIM API. Build your own error handler and pass its instance to the browserfield configuration.
Below, there's sample code:
// Create the ErrorHandler class
public class MyBrowserFieldErrorHandler extends BrowserFieldErrorHandler {
public void displayContentError(String url, String errorMessage) {
String error = "Error: (url=" + url + "): " + t.getMessage();
Dialog.ask(Dialog.D_OK, error);
logMessage(“BrowserFieldError: “ + error );
}
public void displayContentError(String url, InputConnection connection, Throwable t) {
displayContentError(url, t.getMessage());
}
public void requestContentError(BrowserFieldRequest request, Throwable t){
displayContentError(request.getURL(), t.getMessage());
}
}
// Attach the Error Handler to the BrowserField
BrowserFieldErrorHandler eHandler = new MyBrowserFieldErrorHandler();
browserField.getConfig().setProperty(BrowserFieldConfig.ERROR_HANDLER,eHandler);
I get this sample code from DevCon2010 presentation of BrowserField capabilities. You can get it here: http://dev.tuyennguyen.ca/wp-content/uploads/2011/02/DEV49.pdf

Resources