we are looking for a way to do the following:
user with BB enters a number (or selects a contact and clicks 'send')
our app in the background detects the call event
our app does something (e.g. blocks the call / makes a call to a different number, etc)
can this be done at all? can it be done transparently to the user (i.e. no dialogs or user involvement)?
which APIs should I look at?
Thanks
Outgoing call interception
call interception http://img200.imageshack.us/img200/6927/callinit.png
create extention of Application for background service
implement PhoneListener
use callInitiated
should be signed before use on device
should be tested against known issue
Code example:
import net.rim.blackberry.api.phone.Phone;
import net.rim.blackberry.api.phone.PhoneListener;
import net.rim.device.api.system.Application;
import net.rim.device.api.ui.component.Dialog;
public class CatchCall extends Application implements PhoneListener {
public CatchCall() {
Phone.addPhoneListener(this);
}
public static void main(String[] args) {
new CatchCall().enterEventDispatcher();
}
public void callAdded(int callId) {
}
public void callAnswered(int callId) {
}
public void callConferenceCallEstablished(int callId) {
}
public void callConnected(int callId) {
}
public void callDirectConnectConnected(int callId) {
}
public void callDirectConnectDisconnected(int callId) {
}
public void callDisconnected(int callId) {
}
public void callEndedByUser(int callId) {
}
public void callFailed(int callId, int reason) {
}
public void callHeld(int callId) {
}
public void callIncoming(int callId) {
}
public void callInitiated(int callid) {
Dialog.inform("call initiated");
}
public void callRemoved(int callId) {
}
public void callResumed(int callId) {
}
public void callWaiting(int callid) {
}
public void conferenceCallDisconnected(int callId) {
}
}
Cancel call
You can use event injection to fire Close button press event:
public void dropCall()
{
KeyEvent inject = new KeyEvent(KeyEvent.KEY_DOWN, Characters.ESCAPE, 0);
inject.post();
}
Don't forget to set permissions for device release: Options => Advanced Options => Applications => [Your Application] =>Edit Default permissions =>Interactions =>key stroke Injection
See also
BlackBerry - Simulate a KeyPress event
Related
I have this Class as my page object:
public class LaunchPageObject {
private AppiumDriver<AndroidElement> driver;
public LaunchPageObject() {
}
public LaunchPageObject(AppiumDriver<AndroidElement> driver) {
this.driver=driver;
PageFactory.initElements(new AppiumFieldDecorator(this.driver), this);
}
public void Click_SigninNow() {
lnk_SigninNow.click();
}
#AndroidFindBy(xpath="//android.widget.Button[#text='LOGIN WITH FACEBOOK']")
MobileElement btn_SignupWithEmail;
#AndroidFindBy(xpath="//android.widget.Button[#text='SIGN UP WITH EMAIL']")
MobileElement btn_LoginWithFacebook;
#AndroidFindBy(xpath="//android.widget.TextView[#text='Sign in now']")
MobileElement lnk_SigninNow;
}
and I have this class as my test case class:
public class LaunchPageTest extends Android {
#Test
public void Click_SigninNow() throws MalformedURLException {
LaunchPageObject lp = new LaunchPageObject(setDriver());
lp.Click_SigninNow();
}
}
I have this error log:
FAILED: Click_SigninNow
java.lang.ExceptionInInitializerError
at io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy(ProxyFactory.java:52)
at io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy(ProxyFactory.java:33)
at io.appium.java_client.pagefactory.AppiumFieldDecorator.proxyForAnElement(AppiumFieldDecorator.java:217)
at io.appium.java_client.pagefactory.AppiumFieldDecorator.access$0(AppiumFieldDecorator.java:215)
at io.appium.java_client.pagefactory.AppiumFieldDecorator$1.proxyForLocator(AppiumFieldDecorator.java:107)
at org.openqa.selenium.support.pagefactory.DefaultFieldDecorator.decorate(DefaultFieldDecorator.java:62)
at io.appium.java_client.pagefactory.AppiumFieldDecorator.decorate(AppiumFieldDecorator.java:155)
at org.openqa.selenium.support.PageFactory.proxyFields(PageFactory.java:113)
at org.openqa.selenium.support.PageFactory.initElements(PageFactory.java:105)
at POM.LaunchPageObject.(LaunchPageObject.java:35)
at TestCases.LaunchPageTest.Click_SigninNow(LaunchPageTest.java:17)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
The test opens the app but is not able to click the element. Any idea what is happening here?
Keep your page object and test classes like below
public class LaunchPageObject {
#AndroidFindBy(xpath="//android.widget.Button[#text='LOGIN WITH FACEBOOK']")
MobileElement btn_SignupWithEmail;
#AndroidFindBy(xpath="//android.widget.Button[#text='SIGN UP WITH EMAIL']")
MobileElement btn_LoginWithFacebook;
#AndroidFindBy(xpath="//android.widget.TextView[#text='Sign in now']")
MobileElement lnk_SigninNow;
public void click_SigninNow() {
lnk_SigninNow.click();
}
}
public class LaunchPageTest extends Android {
LaunchPageObject lp = PageFactory.initElements(getDriver(), LaunchPageObject.class);
#Test
public void Click_SigninNow() throws MalformedURLException {
lp.Click_SigninNow();
}
}
This mqtt subscriber code works fine. I can easily subscribe to messages which are published at broker.hivemq.com with respective topic.
public class AccelerometerSubscriber implements MqttCallback,
IMqttActionListener {
public static void main(String[] args) throws MqttException {
int QUALITY_OF_SERVICE = 2;
MqttClient client=new MqttClient("tcp://broker.hivemq.com:1883",
MqttClient.generateClientId());
client.setCallback( new SimpleMqttCallBack() );
client.connect();
System.out.println("Subscribing ....");
client.subscribe("MQTT Examples"); }
System.out.println("some action"); //------------right here--------------
public void connectionLost(Throwable throwable) {
System.out.println("Connection to MQTT broker lost!"); }
public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
System.out.println("Message received:\n\t"+ new String(mqttMessage.getPayload()) );
}
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
// not used in this example
}}
Now I want to perform action only when a message is received. I'm unable to do that.
You have a class (AccelerometerSubscriber) that implements the interface MqttCallback, use an instance of it instead of doing client.setCallback( new SimpleMqttCallBack() );
public class AccelerometerSubscriber implements MqttCallback, IMqttActionListener {
public static void main(String[] args) throws MqttException {
AccelerometerSubscriber as = new AccelerometerSubscriber();
int QUALITY_OF_SERVICE = 2;
MqttClient client = new MqttClient("tcp://broker.hivemq.com:1883", MqttClient.generateClientId());
client.setCallback(as);
client.connect();
System.out.println("Subscribing ....");
client.subscribe("MQTT Examples");
}
#Override
public void connectionLost(Throwable throwable) {
System.out.println("Connection to MQTT broker lost!");
}
#Override
public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
//message is received is here!!!
System.out.println("Message received:\n\t" + new String(mqttMessage.getPayload()));
}
#Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
System.out.println("deliveryComplete");
}
#Override
public void onFailure(IMqttToken arg0, Throwable arg1) {
System.out.println("onFailure");
}
#Override
public void onSuccess(IMqttToken arg0) {
System.out.println("onSuccess");
}
}
I have parent presenter: UsersListPresenter that contains nested presenter: UserPresenter in NestedSlot.
public class UsersListPresenter extends ApplicationPresenter<UsersListPresenter.MyView, UsersListPresenter.MyProxy> implements UsersListUiHandlers,
OpenWindowEvent.OpenModaHandler, UserAddedEvent.UserAddedHandler {
#ProxyStandard
#NameToken(ClientRouting.Url.users)
#UseGatekeeper(IsUserLoggedGatekeeper.class)
public interface MyProxy extends TabContentProxyPlace<UsersListPresenter> {}
#TabInfo(container = AppPresenter.class)
static TabData getTabLabel(IsUserLoggedGatekeeper adminGatekeeper) {
return new MenuEntryGatekeeper(ClientRouting.Label.users, 1, adminGatekeeper);
}
public interface MyView extends View, HasUiHandlers<UsersListUiHandlers> {
void setUsers(List<UserDto> users);
void addUser(UserDto user);
}
public static final NestedSlot SLOT_USER_WINDOW = new NestedSlot();
//interface Driver extends SimpleBeanEditorDriver<UserDto, UserEditor> {}
private static final UserService userService = GWT.create(UserService.class);
private AppPresenter appPresenter;
private UserTestPresenter userPresenter;
#Inject
UsersListPresenter(EventBus eventBus, MyView view, MyProxy proxy, AppPresenter appPresenter, UserTestPresenter userPresenter) {
super(eventBus, view, proxy, appPresenter, AppPresenter.SLOT_TAB_CONTENT);
this.appPresenter = appPresenter;
this.userPresenter = userPresenter;
getView().setUiHandlers(this);
}
#Override
protected void onBind() {
super.onBind();
updateList();
setInSlot(SLOT_USER_WINDOW, userPresenter);
addRegisteredHandler(OpenWindowEvent.getType(), this);
}
#Override
protected void onReveal() {
super.onReveal();
initializeApplicationUiComponents(ClientRouting.Label.users);
}
#Override
public void onOpenModal(OpenWindowEvent event) {
openModal(event.getUser());
}
#Override
public void openModal(UserDto user) {
userPresenter.openModal(user);
}
}
public class UsersListView extends ViewWithUiHandlers<UsersListUiHandlers> implements UsersListPresenter.MyView {
interface Binder extends UiBinder<Widget, UsersListView> {}
#UiField
SimplePanel windowSlot;
#Inject
UsersListView(Binder uiBinder) {
initWidget(uiBinder.createAndBindUi(this));
}
#Override
public void setInSlot(Object slot, IsWidget content) {
if (slot == UsersListPresenter.SLOT_USER_WINDOW) {
windowSlot.setWidget(content);
}
};
}
public class UserTestPresenter extends Presenter<UserTestPresenter.MyView, UserTestPresenter.MyProxy> implements UserTestUiHandlers {
public interface MyView extends View, HasUiHandlers<UserTestUiHandlers> {
void openModal(UserDto user);
}
#ProxyStandard
#NameToken("/user/{userid}")
public interface MyProxy extends ProxyPlace<UserTestPresenter> {
}
private PlaceManager placeManager;
#Inject
public UserTestPresenter(EventBus eventBus, MyView view, MyProxy proxy, PlaceManager placeManager) {
super(eventBus, view, proxy, UsersListPresenter.SLOT_USER_WINDOW);
this.placeManager = placeManager;
getView().setUiHandlers(this);
}
#Override
public void prepareFromRequest(PlaceRequest request) {
GWT.log("Prepare from request " + request.getNameToken());
}
#Override
protected void onReveal() {
super.onReveal();
};
public void openModal(UserDto user) {
getView().openModal(user);
}
#Override
public void onSave(UserDto user) {
// TODO Auto-generated method stub
MaterialToast.fireToast("onSaveClick in new presenter for " + user.toString());
}
#Override
public void onClose() {
PlaceRequest placeRequest = new PlaceRequest.Builder().nameToken("/users/{userid}").with("userid", "list").build();
placeManager.revealPlace(placeRequest);
}
public class UserTestView extends ViewWithUiHandlers<UserTestUiHandlers> implements UserTestPresenter.MyView {
interface Binder extends UiBinder<Widget, UserTestView> {}
#UiField
MaterialRow main;
#UiField
MaterialWindow window;
#UiField
MaterialLabel userName, userFullName;
#UiField
MaterialButton saveButton;
private HandlerRegistration saveButtonClickHandler;
#Inject
UserTestView(Binder uiBinder) {
initWidget(uiBinder.createAndBindUi(this));
// adding default click handler
saveButtonClickHandler = saveButton.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {}
});
}
#Override
public void openModal(final UserDto user) {
userName.setText(user.getEmail());
userFullName.setText(user.getId() + " " + user.getEmail());
saveButtonClickHandler.removeHandler();
saveButtonClickHandler = saveButton.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
getUiHandlers().save(user);
}
});
window.openWindow();
}
}
when user from list is clicked the window with clicked users is opened. At this moment url should change from http://localhost:8080/cms/#/users/list to http://localhost:8080/cms/#/user/3
for better understanding below is screencast from that code:
and now some job done, but still not ideal:
here is my gwtp configuration:
public class ClientModule extends AbstractPresenterModule {
#Override
protected void configure() {
bind(RestyGwtConfig.class).asEagerSingleton();
install(new Builder()//
.defaultPlace(ClientRouting.HOME.url)//
.errorPlace(ClientRouting.ERROR.url)//
.unauthorizedPlace(ClientRouting.LOGIN.url)//
.tokenFormatter(RouteTokenFormatter.class).build());
install(new AppModule());
install(new GinFactoryModuleBuilder().build(AssistedInjectionFactory.class));
bind(CurrentUser.class).in(Singleton.class);
bind(IsAdminGatekeeper.class).in(Singleton.class);
bind(IsUserLoggedGatekeeper.class).in(Singleton.class);
bind(ResourceLoader.class).asEagerSingleton();
}
}
As You can see I use tokenFormatter(RouteTokenFormatter.class)
how it can be achieved with gwtp framework?
One way to achieve this is to change the URL of your UserListPresenter to support passing in the user id as an optional parameter:
#NameToken("/users/{userid}")
public interface MyProxy extends ProxyPlace<UserListPresenter> {
}
You need to override the prepareFromRequest method of your UserListPresenter and there you check if the userid is set and open your modal window if it is.
#Override
public void prepareFromRequest(PlaceRequest request) {
String userid = request.getParameter("userid", "list");
if (userid != "list") {
# open modal
}
else {
# close modal
}
}
You also need to change the logic when you click your on a user in your list:
#Override
public void onOpenModal(OpenWindowEvent event) {
PlaceRequest placeRequest = new PlaceRequest.Builder()
.nameToken("/users/{userid}")
.with("userid", event.getUser().getId())
.build();
placeManager.revealPlace(placeRequest);
}
This will change the URL and open the modal.
I want to create an call recorder application in blackberry. While searching in this forum i have got call-recorder-in-blackberry this link. The code given in the below link is fairly understood.
It might be a silly question to you experts but my question is how to us that piece of code. I mean the MyScreen object will work on UIApplication. But how can i make my module start while starting the device, and run in background waiting for the phone call listener to invoke.
I have used this below code, it records the call but only if the call is on loud speaker mode. Now how can i do the same without putting in loud speaker mode.
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.file.FileConnection;
import javax.microedition.media.Manager;
import javax.microedition.media.Player;
import javax.microedition.media.control.RecordControl;
import net.rim.blackberry.api.phone.Phone;
import net.rim.blackberry.api.phone.PhoneCall;
import net.rim.blackberry.api.phone.PhoneListener;
import net.rim.device.api.system.Application;
import net.rim.device.api.ui.component.Dialog;
public class CatchCall extends Application implements PhoneListener {
Player player;
RecordControl recorder;
private ByteArrayOutputStream output;
byte[] data;
boolean yes = false;
int st;
public CatchCall() {
Phone.addPhoneListener(this);
}
public static void main(String[] args) {
new CatchCall().enterEventDispatcher();
}
public void callAdded(int callId) {
}
public void callAnswered(int callId) {
}
public void callConferenceCallEstablished(int callId) {
}
public void callConnected(int callId) {
// TODO Auto-generated method s
PhoneCall phoneCall = Phone.getCall(callId);
if (phoneCall != null) {
if (yes)
initPlay();
}
}
public void callDirectConnectConnected(int callId) {
}
public void callDirectConnectDisconnected(int callId) {
}
public void callDisconnected(int callId) {
// TODO Auto-generated method stub
if (yes) {
try {
recorder.commit();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
player.close();
data = output.toByteArray();
saveRecordedFile(data);
}
}
public void callEndedByUser(int callId) {
}
public void callFailed(int callId, int reason) {
}
public void callHeld(int callId) {
}
public void callIncoming(int callId) {
Dialog.ask(Dialog.D_YES_NO, "Are u sure to record this call");
}
public void callInitiated(int callid) {
PhoneCall phoneCall = Phone.getCall(callid);
if (phoneCall != null) {
st = Dialog.ask(Dialog.D_YES_NO, "Are u sure to record this call");
if (st == Dialog.YES)
yes = true;
else
yes = false;
}
}
public void callRemoved(int callId) {
}
public void callResumed(int callId) {
}
public void callWaiting(int callid) {
}
public void conferenceCallDisconnected(int callId) {
}
private void initPlay() {
try {
player = Manager.createPlayer("capture://audio");
player.realize();
recorder = (RecordControl) player.getControl("RecordControl");
output = new ByteArrayOutputStream();
recorder.setRecordStream(output);
recorder.startRecord();
player.start();
} catch (Exception e) {
Dialog.alert(e + "");
}
}
public static boolean saveRecordedFile(byte[] data) {
try {
String filePath1 = System.getProperty("fileconn.dir.music");
String fileName = "Call Recorder(";
boolean existed = true;
for (int i = 0; i < Integer.MAX_VALUE; i++) {
try {
FileConnection fc = (FileConnection) Connector.open(filePath1 + fileName + i + ").amr");
if (!fc.exists()) {
existed = false;
}
fc.close();
} catch (IOException e) {
Dialog.alert("unable to save");
return existed;
}
if (!existed) {
fileName += i + ").amr";
filePath1 += fileName;
break;
}
}
System.out.println(filePath1);
System.out.println("");
FileConnection fconn = (FileConnection) javax.microedition.io.Connector .open(filePath1, javax.microedition.io.Connector.READ_WRITE);
if (fconn.exists())
fconn.delete();
fconn.create();
OutputStream outputStream = fconn.openOutputStream();
outputStream.write(data);
outputStream.close();
fconn.close();
return true;
} catch (Exception e) {
}
return false;
}
}
Actually direct call recording not possible with blackberry. AFAIK that posted code is call recording when call on speakerphone. That means If mobile have the loud speaker, then put a call to loud speaker and record that voice. And look at this discussion, Call recorder in Blackberry.
It's not possible to record the audio of a phone call (other than with a loud speakerphone) as you are trying to do. This is intentional. You would need another approach off the device to do this. However, I can answer your other questions:
To make your application autostart, you can follow these steps: http://supportforums.blackberry.com/t5/Java-Development/Configure-an-application-to-start-automatically-when-the/ta-p/444748
Also, as this application above doesn't extend from UiApplication, you should check the "run as a system module" box as well, when you follow the directions above. That way it won't appear on the ribbon or as an icon in the list of applications.
I'd like to describe one trick I learned at supportforums.blackberry.com
There is a native dialer Phone Application in BlackBerry.
The trick is to programmatically run menu items of dialer after incoming call, call fail or any other call event.
There is a PhoneListener interface, which gives an ability to listen to the status of incoming and outgoing phone calls.
See Listen for and handle phone events
A quote from supportforums.blackberry.com - Re: How to exit an Ui application (by simon_hain):
Listeners are hard referenced by the application they are added to. Figuratively speaking, they become part of the rim application.
If you add a listener to the phone application this listener is executed in the context of the phone app.
You can check this by using Ui.getUiEngine().getActiveScreen() in a listener method. The returned screen is the call screen of the phone application.
I use this to execute commands on phone calls:
- on callInitiated or callConnected i store a reference to the phone screen.
- i call phoneScreen.getMenu(0)
now i want to execute a command:
- i change the locale to "en"
- i iterate through the menu using menu.getSize() and menu.getItem(i)
- i check if menuItem.toString equals my command
- i call menuItem.run()
- and change the locale back (if it was changed)
you can use this to:
mute
unmute
activate speakerphone
view speeddiallist
end the call (only prior to 4.5/4.6, not sure which one)
and many more. just print the available menu items :)
A sample code for this trick, on incoming call print all menu to console, on answer call mute phone on end call - unmute phone:
public class UseScreenMenu extends Application implements PhoneListener {
String MENU_ITEM_MUTE = "Mute";
String MENU_ITEM_UNMUTE = "Unmute";
public UseScreenMenu() {
Phone.addPhoneListener(this);
}
public static void main(String[] args) {
UseScreenMenu app = new UseScreenMenu();
app.enterEventDispatcher();
}
public void callIncoming(int callId) {
printMenu();
}
public void callAnswered(int callId) {
runMenuItem(MENU_ITEM_MUTE);
}
public void callEndedByUser(int callId) {
runMenuItem(MENU_ITEM_UNMUTE);
}
private void printMenu() {
Screen screen = Ui.getUiEngine().getActiveScreen();
Menu menu = screen.getMenu(0);
System.out.println("Menu of BB Dialler - Begin");
for (int i = 0, cnt = menu.getSize(); i < cnt; i++)
System.out.println("Menu of BB Dialler - "
+menu.getItem(i).toString());
System.out.println("Menu of BB Dialler - End");
}
private void runMenuItem(String menuItemText) {
Screen screen = Ui.getUiEngine().getActiveScreen();
Menu menu = screen.getMenu(0);
for (int i = 0, cnt = menu.getSize(); i < cnt; i++)
if(menu.getItem(i).toString().equalsIgnoreCase(menuItemText))
menu.getItem(i).run();
}
public void callAdded(int callId) {}
public void callConferenceCallEstablished(int callId) {}
public void callConnected(int callId) {}
public void callDirectConnectConnected(int callId) {}
public void callDirectConnectDisconnected(int callId) {}
public void callDisconnected(int callId) {}
public void callFailed(int callId, int reason) {}
public void callHeld(int callId) {}
public void callInitiated(int callid) {}
public void callRemoved(int callId) {}
public void callResumed(int callId) {}
public void callWaiting(int callid) {}
public void conferenceCallDisconnected(int callId) {}
}