Blackberry BrowserField 中的浏览器进度跟踪器
有没有人能够在黑莓中为 BrowserField 实现进度跟踪栏,我正在努力解决这个问题。我想告诉用户,当他打开我的应用程序中的浏览器字段时,实际上正在发生一些事情。
我已经检查过 BrowserFieldProgressBar 演示,但它仅适用于 OS 6,因为它适用于 BrowserField2。进度条或带有 gif 的对话框都可以。我尝试实现以下操作,但是 PopUpScreen 不会显示在浏览器字段上,一旦我退出浏览器字段,它就会卡住:
public class BrowserPopUpScreen extends MainScreen{
private GridFieldManager _manager;
private BrowserField _browserField; // Campo de la interfaz que se utiliza para mostrar una página web
private final String GRAPH_URL = "https://graph.facebook.com"; // URL de Graph API de Facebook.
private final String NEXT_URL = "http://www.facebook.com/connect/login_success.html"; // URL adonde se redirige al usuario cuando la operacion es exitosa.
private final String APPLICATION_KEY = "e1812f3b71678c8e0017831cc4cbc87a"; // Llave de la aplicación en Facebook.
private final String APPLICATION_SECRET = ""; // Secreto de la aplicacion en Facebook.
private final String APPLICATION_ID = ""; // ID de la aplicacion en Facebook.
public static final int FACEBOOK_SIGNUP = 1; // Constante que indica que el usuario desea registrarse con Facebook
public static final int FACEBOOK_LINK = 2; // Constante que indica que el usuario desea conectar su cuenta de Facebook a la cuenta de Social Voice
/**
* Construye la pantalla de browser.
*
* Dependiendo te la acción que recibe en caso de ser FACEBOOK_SIGNUP
* peticiona en envió de información de usuario a Facebook, en caso contrario
* solo pide un token de acceso para el usuario.
*
* @param manager
* Administrador de contenido que utilizará la pantalla
* @param action
* Acción que se realizará, en caso de ser registro la
* acción será FACEBOOK_SIGNUP, en caso de solo conectar
* Fonyk con Facebook será FACEBOOK_LINK
*/
public BrowserPopUpScreen(GridFieldManager manager, final int action)
{
_manager = manager;
_browserField = new BrowserField();
// Se crea el URL de la petición y se hace el llamado a dicho URL
_browserField.requestContent(new StringBuffer().append("https://graph.facebook.com/oauth/authorize?client_id=").append(APPLICATION_ID).append("&").append("redirect_uri=").append(NEXT_URL).append("&").append("scope=offline_access,publish_stream,email").append("&display=wap").toString());
final LoadingScreen loadingScreen = new LoadingScreen();
//Este metodo detecta cuando se realiza un cambio en el BrowserField
BrowserFieldListener browserListener = new BrowserFieldListener() {
public void documentLoaded(BrowserField browserField, Document document) throws Exception
{
loadingScreen.onClose();
//Se verifica si es nuestro URL de redirección
if(_browserField.getDocumentUrl().startsWith(NEXT_URL))
{
String url = _browserField.getDocumentUrl();
String code = getElement(url, "code");
//Si la petición fue exitosa al URL se le agrega un campo code
//revisamos si este no es uno para continuar con la operacion
if(!code.equals(""))
{
//Creamos un cliente http para hacer un GET y obtener el token
//de acceso
HttpClient httpClient = new HttpClient(MainApp.connFactory);
//Se crea un hashtable que va a contener la información de nuestra aplicación
//y el código proporcionado previamente
Hashtable data = new Hashtable();
data.put("client_id", APPLICATION_ID);
data.put("redirect_uri", NEXT_URL);
data.put("client_secret", APPLICATION_SECRET);
data.put("code", code);
StringBuffer response = httpClient.doGet(GRAPH_URL.concat("/oauth/access_token"), data);
if(response.length() == 0)
throw new Exception();
//Se obtiene el token de acceso de la respuesta y se asigna a nuestro
//objeto usuario
String accessToken = getElement(response.toString(), "access_token");
MainApp.user.setFacebookAccessToken(accessToken);
MainApp.user.setFacebookAccess(true);
//Si la acción a realizar es de registro, se utiliza el token de acceso
//para peticionar los datos del usuario a FB
if(action == FACEBOOK_SIGNUP)
{
data.clear();
data.put("access_token", accessToken);
response = null;
response = httpClient.doGet(GRAPH_URL.concat("/me"), data);
JSONObject jsonResponse = new JSONObject(response.toString());
// Al obtener una respuesta se establecen los valores en el objeto definido
// inicialmente en la aplicacion
MainApp.facebookUserInfo.setFirstName(jsonResponse.optString("first_name"));
MainApp.facebookUserInfo.setLastBame(jsonResponse.optString("last_name"));
MainApp.facebookUserInfo.setEmail(jsonResponse.optString("email"));
// MainApp.facebookUserInfo.set_birthday(jsonResponse.optString("birthday"));
MainApp.facebookUserInfo.setGender(jsonResponse.optString("gender"));
MainApp.facebookUserInfo.setMiddleName(jsonResponse.optString("middle_name"));
MainApp.facebookUserInfo.setLink(jsonResponse.optString("link"));
}
//Se invoca a la aplicación para cerrar esta pantalla después de
//completarse la operación
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().getActiveScreen().close();
}
});
}
}
}
};
_browserField.addListener(browserListener);
add(_browserField);
UiApplication.getUiApplication().pushScreen(loadingScreen);
}
private class LoadingScreen extends PopupScreen{
private AnimatedGIFField _loader;
public LoadingScreen(){
super(new VerticalFieldManager());
GIFEncodedImage ourAnimation = (GIFEncodedImage) GIFEncodedImage.getEncodedImageResource("ajax-loader (7).gif");
_loader = new AnimatedGIFField(ourAnimation, Field.FIELD_HCENTER);
this.add(_loader);
}
public boolean onClose() {
setDirty(false);
return super.onClose();
}
}
/**
* Extra un valor especificado del URL
*
* @param url
URL del cuál se va a extraer un valor
* @param element
Elemento que se desea obtener
* @return
*/
private String getElement(String url, String element)
{
int startIndex = url.indexOf(element);
if (startIndex > -1) {
int stopIndex = url.length();
if (url.indexOf('&', startIndex) > -1) {
stopIndex = url.indexOf('&', startIndex);
} else if (url.indexOf(';', startIndex) > -1) {
stopIndex = url.indexOf(';', startIndex);
}
element = url.substring(url.indexOf('=', startIndex) + 1, stopIndex);
return element;
}
return "";
}
}
Has anyone been able to implement a progress tracker bar for a BrowserField in blackberry i'm struggling with this. I want to tell the user that something is actually happening when he opens the browser field in my app.
I already checked the BrowserFieldProgressBar demo, but that only works on OS 6 since it's for BrowserField2. Either a progress bar or a dialog with a gif works. I tried implementing the following, but the PopUpScreen doesn't show over the browser field and once i exit the browserfield it gets stuck:
public class BrowserPopUpScreen extends MainScreen{
private GridFieldManager _manager;
private BrowserField _browserField; // Campo de la interfaz que se utiliza para mostrar una página web
private final String GRAPH_URL = "https://graph.facebook.com"; // URL de Graph API de Facebook.
private final String NEXT_URL = "http://www.facebook.com/connect/login_success.html"; // URL adonde se redirige al usuario cuando la operacion es exitosa.
private final String APPLICATION_KEY = "e1812f3b71678c8e0017831cc4cbc87a"; // Llave de la aplicación en Facebook.
private final String APPLICATION_SECRET = ""; // Secreto de la aplicacion en Facebook.
private final String APPLICATION_ID = ""; // ID de la aplicacion en Facebook.
public static final int FACEBOOK_SIGNUP = 1; // Constante que indica que el usuario desea registrarse con Facebook
public static final int FACEBOOK_LINK = 2; // Constante que indica que el usuario desea conectar su cuenta de Facebook a la cuenta de Social Voice
/**
* Construye la pantalla de browser.
*
* Dependiendo te la acción que recibe en caso de ser FACEBOOK_SIGNUP
* peticiona en envió de información de usuario a Facebook, en caso contrario
* solo pide un token de acceso para el usuario.
*
* @param manager
* Administrador de contenido que utilizará la pantalla
* @param action
* Acción que se realizará, en caso de ser registro la
* acción será FACEBOOK_SIGNUP, en caso de solo conectar
* Fonyk con Facebook será FACEBOOK_LINK
*/
public BrowserPopUpScreen(GridFieldManager manager, final int action)
{
_manager = manager;
_browserField = new BrowserField();
// Se crea el URL de la petición y se hace el llamado a dicho URL
_browserField.requestContent(new StringBuffer().append("https://graph.facebook.com/oauth/authorize?client_id=").append(APPLICATION_ID).append("&").append("redirect_uri=").append(NEXT_URL).append("&").append("scope=offline_access,publish_stream,email").append("&display=wap").toString());
final LoadingScreen loadingScreen = new LoadingScreen();
//Este metodo detecta cuando se realiza un cambio en el BrowserField
BrowserFieldListener browserListener = new BrowserFieldListener() {
public void documentLoaded(BrowserField browserField, Document document) throws Exception
{
loadingScreen.onClose();
//Se verifica si es nuestro URL de redirección
if(_browserField.getDocumentUrl().startsWith(NEXT_URL))
{
String url = _browserField.getDocumentUrl();
String code = getElement(url, "code");
//Si la petición fue exitosa al URL se le agrega un campo code
//revisamos si este no es uno para continuar con la operacion
if(!code.equals(""))
{
//Creamos un cliente http para hacer un GET y obtener el token
//de acceso
HttpClient httpClient = new HttpClient(MainApp.connFactory);
//Se crea un hashtable que va a contener la información de nuestra aplicación
//y el código proporcionado previamente
Hashtable data = new Hashtable();
data.put("client_id", APPLICATION_ID);
data.put("redirect_uri", NEXT_URL);
data.put("client_secret", APPLICATION_SECRET);
data.put("code", code);
StringBuffer response = httpClient.doGet(GRAPH_URL.concat("/oauth/access_token"), data);
if(response.length() == 0)
throw new Exception();
//Se obtiene el token de acceso de la respuesta y se asigna a nuestro
//objeto usuario
String accessToken = getElement(response.toString(), "access_token");
MainApp.user.setFacebookAccessToken(accessToken);
MainApp.user.setFacebookAccess(true);
//Si la acción a realizar es de registro, se utiliza el token de acceso
//para peticionar los datos del usuario a FB
if(action == FACEBOOK_SIGNUP)
{
data.clear();
data.put("access_token", accessToken);
response = null;
response = httpClient.doGet(GRAPH_URL.concat("/me"), data);
JSONObject jsonResponse = new JSONObject(response.toString());
// Al obtener una respuesta se establecen los valores en el objeto definido
// inicialmente en la aplicacion
MainApp.facebookUserInfo.setFirstName(jsonResponse.optString("first_name"));
MainApp.facebookUserInfo.setLastBame(jsonResponse.optString("last_name"));
MainApp.facebookUserInfo.setEmail(jsonResponse.optString("email"));
// MainApp.facebookUserInfo.set_birthday(jsonResponse.optString("birthday"));
MainApp.facebookUserInfo.setGender(jsonResponse.optString("gender"));
MainApp.facebookUserInfo.setMiddleName(jsonResponse.optString("middle_name"));
MainApp.facebookUserInfo.setLink(jsonResponse.optString("link"));
}
//Se invoca a la aplicación para cerrar esta pantalla después de
//completarse la operación
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().getActiveScreen().close();
}
});
}
}
}
};
_browserField.addListener(browserListener);
add(_browserField);
UiApplication.getUiApplication().pushScreen(loadingScreen);
}
private class LoadingScreen extends PopupScreen{
private AnimatedGIFField _loader;
public LoadingScreen(){
super(new VerticalFieldManager());
GIFEncodedImage ourAnimation = (GIFEncodedImage) GIFEncodedImage.getEncodedImageResource("ajax-loader (7).gif");
_loader = new AnimatedGIFField(ourAnimation, Field.FIELD_HCENTER);
this.add(_loader);
}
public boolean onClose() {
setDirty(false);
return super.onClose();
}
}
/**
* Extra un valor especificado del URL
*
* @param url
URL del cuál se va a extraer un valor
* @param element
Elemento que se desea obtener
* @return
*/
private String getElement(String url, String element)
{
int startIndex = url.indexOf(element);
if (startIndex > -1) {
int stopIndex = url.length();
if (url.indexOf('&', startIndex) > -1) {
stopIndex = url.indexOf('&', startIndex);
} else if (url.indexOf(';', startIndex) > -1) {
stopIndex = url.indexOf(';', startIndex);
}
element = url.substring(url.indexOf('=', startIndex) + 1, stopIndex);
return element;
}
return "";
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
乍一看,有 4 件事对我来说很奇怪:
1)。您在请求内容之后设置侦听器(因此可能会发生页面可以在侦听器做出反应之前加载)。
2)。
loadingScreen.onClose();
- 您期望这会做什么?3)。
UiApplication.getUiApplication().getActiveScreen().close();
- 您真的确定要关闭哪个屏幕吗?看来你是个无可救药的乐观主义者。4).我从未使用过
BrowserFieldListener
,因此这一点只是猜测:BrowserFieldListener
还有其他回调,包括失败回调。那么,如果BrowserField.requestContent(String url)
失败(可能有十几个潜在原因)怎么办?最终会调用您正在使用的相同回调吗?更新:
我想问题是你所做的所有事情都是在 UI 线程上按顺序发生的。因此,您按下进度屏幕,执行一些有用的操作,然后关闭进度 - 所有这些都按顺序在 UI 线程上发生。在这种情况下,您不会给 UI 框架实际显示/绘制进度屏幕的机会。为了绘制屏幕,UI 线程需要一些空闲的 cpu 时间。当 UI 线程到达可以开始绘制进度屏幕的程度时,它发现已经不需要这样做了,因为进度屏幕已经关闭。
一个简单(但肮脏)的解决方法是在按下进度屏幕后立即调用
UiApplication.repaint()
。该方法执行以下操作:At a glance 4 things look odd to me:
1). you are settings listener AFTER you have requested the content (so it may happen the page can be loaded BEFORE the listener will be able to react).
2).
loadingScreen.onClose();
- what do you expect this will do?3).
UiApplication.getUiApplication().getActiveScreen().close();
- are you really sure which screen you are closing? Looks like your are an incurable optimist.4). I've never used
BrowserFieldListener
, so this point is just a guess:BrowserFieldListener
has other callbacks including those for failures. So what ifBrowserField.requestContent(String url)
fails (there could be a dozen potential reasons for that) - will that end up calling the same callback you are using?UPDATE:
I guess the problem is all what you're doing happens sequentially on a UI-thread. So you push a progress screen, do sthm useful, then close the progress - all this happens on a UI-thread sequentially. In this case you do not give the UI-framework a chance to actually display/draw the progress screen. To draw a screen the UI-thread needs some FREE cpu time. When UI-thread comes to the point where it could start drawing the progress screen it finds there is no need to do it already, because the progress screen has been closed.
A simple (and dirty) workaround would be to call
UiApplication.repaint()
right after you push the progress screen. This method does the following: