How to add vibration to cocos2d-x 3.2 on Android and iOS devices? - cocos2d-x

I want to vibrate my device in one of my slider functionality, using cocos2d-x 3.2.
I followed some of reference links regarding this on the official forums but I'm still stumped.
Can anyone help me?

After Searching a lot , Finally i am done with my Vibrate Function in Cocos2d-x 3.2 for android.
There is one Vibrator Class.
Vibrator.h
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include <jni.h>
#include <android/log.h>
#include "platform/android/jni/JniHelper.h"
#endif
#define CLASS_NAME "org/cocos2dx/lib/Cocos2dxHelper"
class Vibrator
{
public:
static void Vibrate(int time);
static void CancelVibrate();
};
#endif
Vibrator.cpp
#include "Vibrator.h"
void Vibrator::Vibrate(int time)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "vibrate", "(I)V"))
{
t.env->CallStaticVoidMethod(t.classID, t.methodID, time);
t.env->DeleteLocalRef(t.classID);
}
#endif
}
void Vibrator::CancelVibrate()
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "cancelVibrate", "()V"))
{
t.env->CallStaticVoidMethod(t.classID, t.methodID);
t.env->DeleteLocalRef(t.classID);
}
#endif
}
=> in AndroidManifest.xml : add below permission .
=> in src/org/cocos2dx/lib/Cocos2dxHelper.java file : add below 2 methods
first import => import android.os.Vibrator;
then , add these 2 methods
public static void vibrate ( int vibrateTime) {
Vibrator vib = (Vibrator) sActivity.getSystemService (Service.VIBRATOR_SERVICE);
vib.vibrate (vibrateTime);
}
public static void cancelVibrate () {
Vibrator vib = (Vibrator) sActivity.getSystemService (Service.VIBRATOR_SERVICE);
vib.cancel ();
}
Now, Whenever we want to use Vibrate Function we just have to include this Vibrator Class & Simply Calling it as below .
Vibrator::Vibrate(50);
For Disabling it,
Vibrator::CancelVibrate();
in won't work in Tab as it does not having Vibrator in it .

There's supposed to be a working implementation of vibrate on iOS and Android on FenneX's github.
The header file is in
Classes/FenneX/NativeWrappers/NativeUtility.h.
iOS implementation is in proj.ios_mac/ios/Misc/NativeUtility.mm
Android implemention have the C++ in
proj.android/jni/NativeUtility.cpp
the Java somewhere in the src.
sourced from a forum post asking the same thing

Based on the code found in the forum post:
you need to add a header in your Classes/ folder where you just have the cpp function declared but not defined.
you need to add a function definition in the proj.android/jni, in a .cpp file. I used proj.android/jni/hellocpp/main.cpp, which I believe is the default for a starter cocos2dxv3 project. In this method you call the method you've defined in your java, in this case it was defined as a static method on your Activity. The default was named `AppActivity.
make sure you've got the vibration permission on your proj.android/AndroidManifest.xml, <uses-permission android:name="android.permission.VIBRATE"/>
So, in one of your standard C++ headers in the Classes/ folder, add
//Classes/any_header.h
void vibrate(int milliseconds);
and in the associated .cpp file, call it:
//Classes/any_header.cpp
void get_hit()
{
vibrate(200);
}
In your proj.android/AndroidManifest.xml, you'll want to add that line
<manifest>
...
<uses-permission android:name="android.permission.VIBRATE"/>
</manifest>
In a cpp file the jni will deal with, say proj.android/jni/hellocpp/main.cpp, you'll need to define the connection between the Java and C++ by calling the Java method:
//proj.android/jni/hellocpp/main.cpp
/* this function should already exist though */
void cocos_android_app_init (JNIEnv* env, jobject thiz) {
LOGD("cocos_android_app_init");
AppDelegate *pAppDelegate = new AppDelegate();
}
/* this is the new one you're adding, where org/cocos2dx/cpp/AppActivity
is the java file where your Activity with the vibrate static method is defined
*/
void vibrate(int milliseconds)
{
JniMethodInfo minfo;
CCAssert(JniHelper::getStaticMethodInfo(minfo, "org/cocos2dx/cpp/AppActivity", "vibrate", "(I)V"), "Function doesn't exist");
minfo.env->CallStaticVoidMethod(minfo.classID, minfo.methodID, (jint)milliseconds);
minfo.env->DeleteLocalRef(minfo.classID);
}
finally, here's the .java file where the android call to vibrate is made. Mine was proj.android/src/org/cocos2dx/cpp/AppActivity.java
/* default imports */
package org.cocos2dx.cpp;
import org.cocos2dx.lib.Cocos2dxActivity;
/* imports needed for vibration stuff */
import android.os.Vibrator;
import android.content.Context;
import android.app.ActivityManager;
import android.util.Log;
import android.os.Bundle;
public class AppActivity extends Cocos2dxActivity {
private static volatile Cocos2dxActivity mainActivity;
public static void setMainActivity(Cocos2dxActivity activity)
{
mainActivity = activity;
}
public static Cocos2dxActivity getMainActivity()
{
if(mainActivity == null)
{
Log.w("MY_APP_NAME_GOES_HERE", "Warning : null main Activity");
}
return mainActivity;
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
AppActivity.setMainActivity(this);
}
public static void vibrate(int milliseconds)
{
Vibrator v = (Vibrator) getMainActivity().getSystemService(Context.VIBRATOR_SERVICE);
if (getMainActivity().getSystemService(Context.VIBRATOR_SERVICE) != null)
{
v.vibrate(milliseconds);
}
}
}

Related

Trying to integrate facebook with libgdx, where to implement this code because there is no "module:app" is present?

According to facebook:-
"Add the following to the dependencies {} section of your build.gradle (module: app) file to compile the latest version of the Facebook SDK:
implementation 'com.facebook.android:facebook-android-sdk:[4,5)'"
I don't see any module named app in the android studio project.where to add above line?
module:app in this case just means the main android app. So you should add the dependency to the android module.
Then I bet your next question how to use this library from the core since the Android module depends on the core module and not vice versa so you do not have access to the library in the core project. One way is to pass a contract to the platform launchers where each implements it differently.
//Simple contract
public interface IPlatformContract {
void runThis();
}
// Core project (MyGame)
private IPlatformContract platformContract;
public MyGame(IPlatformContract platformContract) {
this.platformContract = platformContract;
}
//DesktopLauncher
public static void main (String[] arg) {
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
// Launch desktop with it's own implementation of the contract.
new LwjglApplication(new MyGame(new IPlatformContract() {
#Override
public void runThis() {
System.out.println(" I run on desktop!");
}
}), config);
}
//AndroidLauncher, different way. Here the class itself implements the contract.
public class AndroidLauncher extends AndroidApplication implements IPlatformContract{
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
initialize(new LibgdxTestEnvironment(this), config);
}
#Override
public void runThis() {
System.out.println("I run on android!");
}
}
You can pass along the contract to other classes like screens in your core project so you have access to it. You can even make a Singleton.

AdMob Interstitial Cocos2d-x WP8

Can enyone tell me how to call AdMob Interstitial between scenes in my cocos2d-x game?
I have tried this http://robwirving.com/2014/07/21/calling-c-methods-c-winrt-components/ guide, but i don't know how to run it from cocos classes.
Is there any another ways, or some guides?
I've recently made it. You have to do few things. First of all create helper class, which will help you calling native function (I use this for all 3 platforms, but here's just windows phone):
NativeHelper.h:
#ifndef __NATIVE_HELPER_H_
#define __NATIVE_HELPER_H_
#include <string>
#include <functional>
#include "cocos2d.h"
using namespace std;
USING_NS_CC;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
namespace cocos2d
{
public delegate void CSharpShowInterstitialDelegate();
public ref class WP8NativeEventHelper sealed
{
public:
void WP8NativeEventHelper::SetCSharpShowInterstitialDelegate(CSharpShowInterstitialDelegate^ delegate){
m_CSharpShowInterstitialDelegate = delegate;
}
void CallShowInterstitial();
private:
property static CSharpShowInterstitialDelegate^ m_CSharpShowInterstitialDelegate;
};
}
#endif
class NativeHelper
{
public:
static void showInterstitial(string adSdk);
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
WP8NativeEventHelper^ wp8helper;
#endif
//instance required only for setting callback
static NativeHelper* getInstance();
~NativeHelper()
{
instanceFlag = false;
}
private:
static bool instanceFlag;
static NativeHelper* instance;
NativeHelper() {};
};
#endif // __NATIVE_HELPER_H_
So. We have special C++/CX class Wp8NativeEventHelper, which can "talk" with C#. Here we store a delegate.
How it works:
C# is calling SetCSharpShowInterstitialDelegate and passes a delegate to it, which will be remembered in static property.
Then C++\CX can call it using CallShowInterstitial.
Now NativeHelperWP.cpp:
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
#ifndef __NATIVE_HELPER_WP_H_
#define __NATIVE_HELPER_WP_H_
#include "NativeHelper.h"
void WP8NativeEventHelper::CallShowInterstitial(){
if (m_CSharpShowInterstitialDelegate)
{
m_CSharpShowInterstitialDelegate->Invoke();
}
}
bool NativeHelper::instanceFlag = false;
NativeHelper* NativeHelper::instance = NULL;
NativeHelper* NativeHelper::getInstance()
{
if(!instanceFlag){
instance = new NativeHelper();
instanceFlag = true;
instance->wp8helper = ref new WP8NativeEventHelper();
}
return instance;
}
void NativeHelper::showInterstitial(){
NativeHelper::getInstance()->wp8helper->CallShowInterstitial();
}
#endif
#endif
Here is just an implementation of CallShowInterstitial. Also in NativeHelper::showInterstitial we're calling C++/CX, which later calls c#.
Now c# code (MainPage.xaml.cs):
outside namespace:
using GoogleAds;
inside class:
private InterstitialAd interstitialAd;
in constructor:
WP8NativeEventHelper helper = new WP8NativeEventHelper();
helper.SetCSharpShowInterstitialDelegate(showInterstitial);
and also create showInterstitial function:
public void showInterstitial() //we recreate interstitial each time, because otherwise it'll show only once, only new requests won't work
{
interstitialAd = new InterstitialAd("MY_AD_UNIT_ID");
AdRequest adRequest = new AdRequest();
#if DEBUG
// Enable test ads.
adRequest.ForceTesting = true;
#endif
interstitialAd.ReceivedAd += OnAdReceived;
interstitialAd.LoadAd(adRequest);
}
and finally OnAdReceived:
private void OnAdReceived(object sender, AdEventArgs e)
{
System.Diagnostics.Debug.WriteLine("Ad received successfully");
interstitialAd.ShowAd();
}
Follow this guide to setup admob: https://developers.google.com/mobile-ads-sdk/docs/admob/wp/quick-start
Now let's use this.
In HelloWorldScene.h add:
#include "NativeHelper.h"
In HelloWorldScene.cpp:
NativeHelper::showInterstitial();
The same way you can show/hide/change position of admob banner for example (however it's buggy so I'm using ad mediation).

Calling helper function inside android application project from a library project

I have an android application project. I have created a library project and added reference in the application project. Now I need to call/access certain functions/class/methods that is there in the application project from the library project. How can I do that ?
Create an interface in the library that defines the functions you would like the library to call. Have the application implement the interface and then register the implementing object with the library. Then the library can call the application through that object.
In the library, declare the interface and add the registration function:
public class MyLibrary {
public interface AppInterface {
public void myFunction();
}
static AppInterface myapp = null;
static void registerApp(AppInterface appinterface) {
myapp = appinterface;
}
}
Then in your application:
public class MyApplication implements MyLibrary.AppInterface {
public void myFunction() {
// the library will be able to call this function
}
MyApplication() {
MyLibrary.registerApp(this);
}
}
You library can now call the app through the AppInterface object:
// in some library function
if (myapp != null) myapp.myFunction();
You can just create the object of that particular class and then you can directly call that method or variable.
class A{
public void methodA(){
new B().methodB();
//or
B.methodB1();
}
}
class B{
//instance method
public void methodB(){
}
//static method
public static void methodB1(){
}
}
Don't forget to import the necessary packages.

Why is my app crashing in System.Windows.ni.dll on startup with no useful stack trace? (seemingly after adopting Caliburn.Micro)

Start with the default "empty" Windows Phone App project (Windows Phone 8). Let's call it BlackAdder for fun.
Add Caliburn.Micro from Nuget
Move MainPage.xaml to the Views subdirectory and create a matching ViewModel in ViewModels\MainPageViewModel.cs
Fix the namespace for MainPage to Blackadder.Views in both the .xaml and .xaml.cs files
Update App.xaml
<Application
x:Class="BlackAdder.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:local="clr-namespace:BlackAdder">
<Application.Resources>
<local:Bootstrapper x:Key="bootstrapper"/>
</Application.Resources>
</Application>
Update App.xaml.cs
public partial class App : Application
{
public static PhoneApplicationFrame RootFrame { get; private set; }
public App()
{
InitializeComponent();
// Show graphics profiling information while debugging.
if (Debugger.IsAttached)
{
...
}
}
}
Create Bootstrapper.cs
public class Bootstrapper : PhoneBootstrapper
{
private PhoneContainer container;
protected override void Configure()
{
container = new PhoneContainer();
container.RegisterPhoneServices(RootFrame);
container.PerRequest<MainPageViewModel>();
AddCustomConventions();
}
protected static void AddCustomConventions()
{
}
protected override object GetInstance(Type service, string key)
{
return container.GetInstance(service, key);
}
protected override IEnumerable<object> GetAllInstances(Type service)
{
return container.GetAllInstances(service);
}
protected override void BuildUp(object instance)
{
container.BuildUp(instance);
}
}
When we run the app, it crashes in a very weird place.
An unhandled exception of type 'System.Reflection.TargetInvocationException' occurred in System.Windows.ni.dll
Additional information: Exception has been thrown by the target of an invocation.
There is no inner exception, and the stack trace is (seemingly) useless.
System.Windows.ni.dll!System.Windows.Threading.DispatcherOperation.Invoke()
System.Windows.ni.dll!System.Windows.Threading.Dispatcher.Dispatch(System.Windows.Threading.DispatcherPriority priority)
System.Windows.ni.dll!System.Windows.Threading.Dispatcher.OnInvoke(object context)
System.Windows.ni.dll!System.Windows.Hosting.CallbackCookie.Invoke(object[] args)
System.Windows.RuntimeHost.ni.dll!System.Windows.RuntimeHost.ManagedHost.InvokeDelegate(System.IntPtr pHandle, int nParamCount, System.Windows.Hosting.NativeMethods.ScriptParam* pParams, System.Windows.Hosting.NativeMethods.ScriptParam* pResult)
It turns out this has nothing to do with caliburn.micro at all. The problem lies in Properties\WMAppManifest.xaml.
After moving MainPage.xaml to the Views subdirectory, the Navigation Page setting (found on the first tab, Application UI) needs to be updated to Views\MainPage.xaml

CCBMemberVariableAssigner callbacks disfunctional for custom CCTableViewCell in CocosBuilder

my goal is to design a CCTableViewCell via CocosBuilder
and load it via CCBReader.
My steps so far:
I added a new non-fullscreen CCNode TestCell.ccb in cocosbuilder,
set the root's custom class to TestCell
and added a CCSprite as the roots child while setting
it's doc-root-var to bg.
My problem: after implementing a loader TestCellLoader
as well as the Cell TestCell the callback-function
TestCell::onAssignCCBMemberVariable is not called at all.
What I tried:
Using a CCLayerLoader instead of a CCNodeLoader worked for me so far,
this is the first time I'm using a CCNodeLoader so maybe I missed
a crucial point.
Thank you,
Ciao!
Ben
Here are the codes:
TestCellLoader.h
#include <cocos2d.h>
#include "cocos-ext.h"
#include "TestCell.h"
using namespace cocos2d;
using namespace cocos2d::extension;
class TestCellLoader : public CCNodeLoader
{
public:
CCB_STATIC_NEW_AUTORELEASE_OBJECT_METHOD(TestCellLoader, create);
protected:
CCB_VIRTUAL_NEW_AUTORELEASE_CREATECCNODE_METHOD(TestCell);
virtual CCNode* loadCCNode(CCNode *, CCBReader * pCCBReader);
};
TestCellLoader.cpp
#include "TestCellLoader.h"
CCNode * TestCellLoader::loadCCNode(CCNode * pParent, CCBReader * pCCBReader)
{
CCLOG("TestCell::loadCCNode");
CCNode * ccNode = this->createCCNode(pParent, pCCBReader);
return ccNode;
}
TestCell.h
class TestCell : public CCTableViewCell, public CCNodeLoaderListener, public CCBMemberVariableAssigner
{
public:
TestCell();
virtual ~TestCell();
static TestCell *create();
virtual bool init();
virtual bool initWithBG(CCSprite* bg);
static TestCell* cellWithBG(CCSprite* bg);
// ccbuilder callbacks
virtual bool onAssignCCBMemberVariable(cocos2d::CCObject * pTarget, const char * pMemberVariableName, cocos2d::CCNode * pNode);
virtual void onNodeLoaded(cocos2d::CCNode * pNode, cocos2d::extension::CCNodeLoader * pNodeLoader);
private:
CC_PROPERTY(CCSprite*, bg, Bg);
};
TestCell.m
#include "TestCell.h"
using namespace cocos2d;
using namespace cocos2d::extension;
TestCell::TestCell(){}
TestCell::~TestCell(){}
#pragma mark creation
TestCell* TestCell::create(){
TestCell *pRet = new TestCell();
pRet->init();
pRet->autorelease();
return pRet;
}
bool TestCell::init(){
return true;
}
bool TestCell::initWithBG(CCSprite* bg){
return true;
}
TestCell* TestCell::cellWithBG(CCSprite* bg){
return new TestCell;
}
#pragma mark - synthesize
void TestCell::setBg(cocos2d::CCSprite *sprite){
this->bg = sprite;
}
CCSprite* TestCell::getBg(){
return this->bg;
}
#pragma mark - ccbuilder callbacks
void TestCell::onNodeLoaded(cocos2d::CCNode * pNode, cocos2d::extension::CCNodeLoader * pNodeLoader)
{
CCLOG("TestCell::onNodeLoaded");
}
bool TestCell::onAssignCCBMemberVariable(CCObject* pTarget, const char* pMemberVariableName, CCNode* pNode)
{
CCLOG("TestCell::onAssignCCBMemberVariable %s", pMemberVariableName);
return false;
}
I guess you used a CCLayer as TestCell.ccb's Root object type. Since when you are creating a new ccb file, CCLayer is as default option.
And this is why you use a CCLayerLoader instead of a CCNodeLoader worked.
So change your TestCell.ccb's Root object type to CCNode, this maybe works.