laravel passport how to handle errors elegantly - laravel-passport

I am trying to use laravel5.7 + passport to do my API server(The dingo package is not compatible with some of my packages, I have to give it up). I want the global to be more compliant with API error handling, so I modified App\Exceptions\Handler.
<?php
namespace App\Exceptions;
use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
class Handler extends ExceptionHandler
{
/**
* A list of the exception types that are not reported.
*
* #var array
*/
protected $dontReport = [
//
];
/**
* A list of the inputs that are never flashed for validation exceptions.
*
* #var array
*/
protected $dontFlash = [
'password',
'password_confirmation',
];
/**
* Report or log an exception.
*
* #param \Exception $exception
* #return void
*/
public function report(Exception $exception)
{
parent::report($exception);
}
/**
* Render an exception into an HTTP response.
*
* #param \Illuminate\Http\Request $request
* #param \Exception $exception
* #return \Illuminate\Http\Response
*/
public function render($request, Exception $exception)
{
// Determine whether it is an API interface
if($request->is('api/*')) {
$response = [];
$error = $this->convertExceptionToResponse($exception);
$response['message'] = $exception->getMessage();
$response['status_code'] = $error->getStatusCode();
if(config('app.debug')) {
if($error->getStatusCode() >= 500) {
$response['debug']['line'] = $exception->getLine(); // error line
$response['debug']['file'] = $exception->getFile(); // error file
$response['debug']['class'] = get_class($exception); // error position
$response['debug']['trace'] = explode("\n", $exception->getTraceAsString()); //Error stack
}
}
// response api
return response()->json($response, $error->getStatusCode());
} else {
// response web
return parent::render($request, $exception);
}
}
}
error detail:
{
"message": "Unauthenticated.",
"status_code": 500,
"debug": {
"line": 67,
"file": "/Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php",
"class": "Illuminate\\Auth\\AuthenticationException",
"trace": [
"#0 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php(41): Illuminate\\Auth\\Middleware\\Authenticate->authenticate(Object(Illuminate\\Http\\Request), Array)",
"#1 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(163): Illuminate\\Auth\\Middleware\\Authenticate->handle(Object(Illuminate\\Http\\Request), Object(Closure), 'api')",
"#2 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))",
"#3 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Routing/Middleware/ThrottleRequests.php(58): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))",
"#4 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(163): Illuminate\\Routing\\Middleware\\ThrottleRequests->handle(Object(Illuminate\\Http\\Request), Object(Closure), 60, '1')",
"#5 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))",
"#6 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(104): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))",
"#7 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Routing/Router.php(684): Illuminate\\Pipeline\\Pipeline->then(Object(Closure))",
"#8 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Routing/Router.php(659): Illuminate\\Routing\\Router->runRouteWithinStack(Object(Illuminate\\Routing\\Route), Object(Illuminate\\Http\\Request))",
"#9 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Routing/Router.php(625): Illuminate\\Routing\\Router->runRoute(Object(Illuminate\\Http\\Request), Object(Illuminate\\Routing\\Route))",
"#10 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Routing/Router.php(614): Illuminate\\Routing\\Router->dispatchToRoute(Object(Illuminate\\Http\\Request))",
"#11 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(176): Illuminate\\Routing\\Router->dispatch(Object(Illuminate\\Http\\Request))",
"#12 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(30): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}(Object(Illuminate\\Http\\Request))",
"#13 /Users/noecs/Desktop/noecsSystemLaravel/vendor/fideloper/proxy/src/TrustProxies.php(57): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))",
"#14 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(163): Fideloper\\Proxy\\TrustProxies->handle(Object(Illuminate\\Http\\Request), Object(Closure))",
"#15 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))",
"#16 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(31): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))",
"#17 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(163): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle(Object(Illuminate\\Http\\Request), Object(Closure))",
"#18 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))",
"#19 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(31): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))",
"#20 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(163): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle(Object(Illuminate\\Http\\Request), Object(Closure))",
"#21 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))",
"#22 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php(27): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))",
"#23 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(163): Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize->handle(Object(Illuminate\\Http\\Request), Object(Closure))",
"#24 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))",
"#25 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/CheckForMaintenanceMode.php(62): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))",
"#26 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(163): Illuminate\\Foundation\\Http\\Middleware\\CheckForMaintenanceMode->handle(Object(Illuminate\\Http\\Request), Object(Closure))",
"#27 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))",
"#28 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(104): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))",
"#29 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(151): Illuminate\\Pipeline\\Pipeline->then(Object(Closure))",
"#30 /Users/noecs/Desktop/noecsSystemLaravel/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(116): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter(Object(Illuminate\\Http\\Request))",
"#31 /Users/noecs/Desktop/noecsSystemLaravel/vendor/swooletw/laravel-swoole/src/Server/Sandbox.php(257): Illuminate\\Foundation\\Http\\Kernel->handle(Object(Illuminate\\Http\\Request))",
"#32 /Users/noecs/Desktop/noecsSystemLaravel/vendor/swooletw/laravel-swoole/src/Server/Sandbox.php(196): SwooleTW\\Http\\Server\\Sandbox->handleRequest(Object(Illuminate\\Http\\Request))",
"#33 /Users/noecs/Desktop/noecsSystemLaravel/vendor/swooletw/laravel-swoole/src/Server/Sandbox.php(182): SwooleTW\\Http\\Server\\Sandbox->prepareResponse(Object(Illuminate\\Http\\Request))",
"#34 /Users/noecs/Desktop/noecsSystemLaravel/vendor/swooletw/laravel-swoole/src/Server/Manager.php(221): SwooleTW\\Http\\Server\\Sandbox->run(Object(Illuminate\\Http\\Request))",
"#35 {main}"
]
}
}
I tried to enter the wrong token, according to the API development specification, I should return the TOKEN of the 401 error. But beyond my expectations, the program output is a 500 error. This makes me very embarrassed, I don't know how to handle the error message of this API gracefully.

Related

iPhone 5c and anything running bluetooth 4.0 has wcsession timout

I have tested my code on the iPhone 6 plus running 9.0 with apple watch 1 and iPhone 7 running 10.0 with apple watch 2.
//HeartrateModel_Phone.m
#import "HeartrateModel_Phone.h"
#implementation HeartrateModel_Phone
{
Communicator * comm;
communicatorStatus commStatus;
HealthDataService * hkService;
workoutStatus monitoringStatus;
}
#synthesize delegate;
-(id)init
{
self = [super init];
if (self)
{
comm = [[Communicator alloc]init];
hkService = [[HealthDataService alloc]init];
monitoringStatus = noWorkoutActivated;
commStatus = noCommunicationActivated;
comm .delegate = self;
hkService.delegate = self;
bluetoothManager = [[CBCentralManager alloc]initWithDelegate:self queue:dispatch_get_main_queue()];
[comm start];
}
return self;
}//eom
-(void)activate
{
[comm start];
}//eom
/*
//disable to remove singleton option
+(HeartrateModel_Phone *)sharedInstance
{
static HeartrateModel_Phone * sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[HeartrateModel_Phone alloc] init];
});
return sharedInstance;
}//eom
*/
#pragma mark - Bluetooth
/*!
* #discussion Accepts a CBCentralManager and returns the bluetooth status
* #param CBCentralManager
* #return bluetoothStatus
*/
-(bluetoothStatus)getBluetoothStatus:(CBCentralManager *)central
{
switch (central.state)
{
case CBManagerStateUnsupported:
return bluetooth_notSupported;
break;
case CBManagerStateUnauthorized:
return bluetooth_unathorized;
break;
case CBManagerStatePoweredOff:
return bluetooth_off;
break;
case CBManagerStatePoweredOn:
return bluetooth_on;
break;
default:
return bluetooth_unknown;
break;
}
}//eom
#pragma mark Bluetooth Delegates
-(void)centralManagerDidUpdateState:(CBCentralManager *)central
{
bluetoothStatus status = [self getBluetoothStatus:central];
[delegate heartrateModelBluetoothStatusChanged:status];
if (VERBOSE) {
NSLog(#"%# Bluetooth '%#'", self, hrModelBluetoothStatusToString(status));
}
}//eom
#pragma mark - Start Workout Process
/*!
* #discussion Starts heartrate mode by sending a message to watch to start workout
if the following conditions are met:
* #brief 1) bluetooth must be enable/turned on
* #brief 2a) to start watch app automatically the iOS version must be 10 & above
*/
-(void)start
{
//making sure bluetooth is on
bluetoothStatus BTstatus = [self getBluetoothStatus:bluetoothManager];
if (BTstatus == bluetooth_on)
{
//checking OS version
NSOperatingSystemVersion osVersion = [[NSProcessInfo processInfo]operatingSystemVersion];
NSInteger currOSVersion = osVersion.majorVersion;
if (currOSVersion >= 10)
{
//checking watch is ready
if( ((comm .session) .isPaired)
&& ((comm .session) .isWatchAppInstalled) )
{
//setup workout configuration
HKWorkoutConfiguration * wkConfig = [[HKWorkoutConfiguration alloc]init];
wkConfig.activityType = HKWorkoutActivityTypeOther;
wkConfig.locationType = HKWorkoutSessionLocationTypeUnknown;
//attempt to start watch app automatically
[(hkService .hkStore) startWatchAppWithWorkoutConfiguration:wkConfig
completion:^(BOOL success, NSError * _Nullable error)
{
[delegate heartrateModelStartWorkResult:success withError:error];
//start monitoring heartrate data from healthkit
if (success){
[self startReading_HeartrateData];
}
}];
}
else
{
//communication not possible
NSErrorDomain errorDomain= #"";
NSInteger errorCode = 1111;
NSError * error = [NSError errorWithDomain:errorDomain
code:errorCode
userInfo:nil];
[delegate heartrateModelStartWorkResult:false withError:error];
}
}
else
{
//sending a live message to watch
[self messageStartWorkout:true];
}
}
else
{
//notify that bluetooth status is not on
[delegate heartrateModelBluetoothStatusChanged:BTstatus];
}
}//eom
/*!
* #discussion Stops the Heartrate model, sends message to watch to stop workout and stops monitoring healthkit for heartrate data
*/
-(void)end
{
[self stopReading_HeartrateData];
[self messageEndWorkout];
}//eom
#pragma mark - Live Message Start Workout
/*!
* #discussion Sends a start workout commands to counterpart via live message
* #param BOOL whether the listener/delegate VC would be notified of message delivery failures
*/
-(void)messageStartWorkout:(BOOL)reportFailure
{
NSDictionary<NSString *, id> * messageToSend = [[NSDictionary alloc]initWithObjectsAndKeys:
hrModelKeysToString(monitorKey_Command), hrModelKeysToString(monitor_key),
hrModelCommandToString(monitorCommand_start),hrModelCommandToString(monitor_Command), nil];
[(comm .session) sendMessage:messageToSend
replyHandler:^(NSDictionary<NSString *,id> * _Nonnull replyMessage)
{
} errorHandler:^(NSError * _Nonnull error) {
//communication not possible
if (reportFailure) {
[delegate heartrateModelStartWorkResult:false withError:error];
}
}];
}//eom
/*!
* #discussion Sends a stop workout commands to counterpart via live message
* #discussion if live message fails, sends a background message
*/
-(void)messageEndWorkout
{
NSDictionary<NSString *, id> * messageToSend = [[NSDictionary alloc]initWithObjectsAndKeys:
hrModelKeysToString(monitorKey_Command), hrModelKeysToString(monitor_key),
hrModelCommandToString(monitorCommand_end),hrModelCommandToString(monitor_Command), nil];
[(comm .session) sendMessage:messageToSend
replyHandler:^(NSDictionary<NSString *,id> * _Nonnull replyMessage)
{
//NSLog(#"reply message: %#", replyMessage);
} errorHandler:^(NSError * _Nonnull error)
{
//sending background message - optional
[comm sendApplicationContext:messageToSend];
}];
}//eom
-(void)messageRequestForWorkoutStatus
{
NSDictionary<NSString *, id> * messageToSend = [[NSDictionary alloc]initWithObjectsAndKeys:
hrModelKeysToString(monitorKey_Command), hrModelKeysToString(monitor_key),
hrModelCommandToString(monitorCommand_status),hrModelCommandToString(monitor_Command), nil];
[(comm .session) sendMessage:messageToSend
replyHandler:^(NSDictionary<NSString *,id> * _Nonnull replyMessage)
{
//NSLog(#"reply message: %#", replyMessage);
} errorHandler:^(NSError * _Nonnull error)
{
}];
}//eom
#pragma mark - Health Store Permission
/*!
* #discussion Request Heartrate Healthkit permission
* #return BOOL success
* #return NSError any errors with healthkit permission
*/
-(void)requestPermission:(void (^)(BOOL success, NSError *error)) completionBlock
{
[hkService requestPermission:^(BOOL success, NSError *error)
{
completionBlock(success, error);
}];
}//eom
#pragma mark - Communicator Delegates
-(void)communicatorActionStatus:(communicatorStatus)status
{
commStatus = status;
if (VERBOSE)
{
NSLog(#"%# Communication Status: '%#'", self, communicatorToString(status));
}
}//eom
-(NSDictionary<NSString *,id> *)communicatorDidReceivedLiveMessage:(NSDictionary<NSString *,id> *)message
{
[self handleMessageReceived:message];
NSDictionary<NSString *, id> * reply = [[NSDictionary alloc]
initWithObjectsAndKeys:#"Success", #"Received", nil];
if (delegate == nil)
{
reply = [[NSDictionary alloc] initWithObjectsAndKeys:#"Failed", #"Received", nil];
}
return reply;
}//eom
-(void)communicatorDidReceivedBackgroundMessage:(NSDictionary<NSString *,id> *)message
{
//nothing to do - not implemented for phone to received background messages
}//eom
-(void)communicatorStateChanged:(WCSession *)session
{
if (session .reachable) {
[self messageRequestForWorkoutStatus];
}
}//eom
#pragma mark Communication Helpers
/*!
* #discussion Handles message received and calls the corresponding handler
* #param NSDictionary Message Received from counterpart
*/
-(void)handleMessageReceived:(NSDictionary<NSString *,id> *)messageRcvd
{
if (VERBOSE)
{
NSLog(#"[hrModel] message RCVD %#", messageRcvd);
}
NSString * keyReceived = [messageRcvd objectForKey:hrModelKeysToString(monitor_key)];
//response / status
if ([keyReceived isEqualToString: hrModelKeysToString(monitorKey_Response)])
{
NSString * responseReceived = [messageRcvd objectForKey:hrModelResponseToString(monitor_Response)];
[self handleMessage_Response:responseReceived];
}
//error
else if ([keyReceived isEqualToString: hrModelKeysToString(monitorKey_Error)])
{
NSString * errorReceived = [messageRcvd objectForKey:hrModelErrorToString(monitor_Response)];
[self handleMessage_Error:errorReceived];
}
//Command
else if ([keyReceived isEqualToString: hrModelKeysToString(monitorKey_Command)])
{
NSString * commandReceived = [messageRcvd objectForKey:hrModelCommandToString(monitor_Command)];
[self handleMessage_Command:commandReceived];
}
}//eom
/*!
* #discussion Handles the response received from counterpart
* #param NSString Response received
*/
-(void)handleMessage_Response:(NSString *)responseRcvd
{
dispatch_async(dispatch_get_main_queue(),
^{
if ([responseRcvd isEqualToString:hrModelResponseToString(monitorResponse_started)])
{
monitoringStatus = started;
[self startReading_HeartrateData];
}
else if ([responseRcvd isEqualToString:hrModelResponseToString(monitorResponse_ended)])
{
monitoringStatus = ended;
[self stopReading_HeartrateData];
}
else if ([responseRcvd isEqualToString:hrModelResponseToString(monitorResponse_notStarted)])
{
monitoringStatus = noWorkoutActivated;
//no need to report failure to start since the nstimer on vc would be trigger
}
});
}//eom
/*!
* #discussion Handles the response received from counterpart
* #param NSString Response received
*/
-(void)handleMessage_Error:(NSString *)errorRcvd
{
monitoringStatus = noWorkoutActivated;
dispatch_async(dispatch_get_main_queue(),
^{
if ([errorRcvd isEqualToString:hrModelErrorToString(monitorError_workout)])
{
monitoringStatus = error_workout;
}
else if ([errorRcvd isEqualToString:hrModelErrorToString(monitorError_healthkit)])
{
monitoringStatus = error_healthkit;
}
else if ([errorRcvd isEqualToString:hrModelErrorToString(monitorError_communicator)])
{
monitoringStatus = error_communicator;
}
});
}//eom
/*!
* #discussion Handles the command received from counterpart
* #param NSString Command received
*/
-(void)handleMessage_Command:(NSString *)commandRcvd
{
//nothing to do - not implemented to received commands
}//eom
#pragma mark - Health Store Heartrate Reading
/*!
* #discussion Requests to Start monitoring healthkit for heartrate data
*/
-(void)startReading_HeartrateData
{
dispatch_async(dispatch_get_main_queue(), ^{
[hkService startHeartrateWithPollingTime:1.5
andSamplesWithSecondsBack:-25.0];
});
}//eom
/*!
* #discussion Requests to Stop monitoring healthkit for heartrate data
*/
-(void)stopReading_HeartrateData
{
dispatch_async(dispatch_get_main_queue(), ^{
[hkService stopPollingHeartrates];
});
}//eom
#pragma mark - HealthData Service Delegates
-(void)healthDataServicePollingSamplesReceived:(NSArray<__kindof HKSample *> *)samples
{
dispatch_async(dispatch_get_main_queue(), ^{
HKQuantitySample * lastHrSample = [samples firstObject];
//value
HKQuantity * hrValue = lastHrSample.quantity;
double hr = [hrValue doubleValueForUnit:hkService.hrUnit];
//dates
NSDate * startDate = lastHrSample.startDate;
NSDate * endDate = lastHrSample.endDate;
[delegate heartrateModelDidReceiveHeartrate:hr
withStartDate:startDate
andEndDate:endDate];
if (VERBOSE)
{
NSLog(#"[hrModel] hr %f |\n start %# |\n end %# ", hr, [startDate debugDescription], [endDate debugDescription]);
}
});
}//eom
#end
When I run my code with the iPhone 5c running 10.0 and apple watch 3.0, it will connect but it is inconsistent. Sometimes I would get wcsession timeout error and it failed to deliver the message.

How to load SVG file into SVGRenderer in three.js

I'm trying to use SVGRenderer in three.js (http://threejs.org/examples/#svg_sandbox). The example shows you how to make an SVG element (a circle) on the fly. I want to import an SVG file that I already have in my computer. How would I do that?
The createElementNS command doesn't seem to support importing SVG files?
I essentially want my image.svg to be displayed on a three.js scene.
You can use the THREE.SVGLoader() Library to achieve it :
var svgManager = new THREE.LegacySVGLoader();
var url = 'https://upload.wikimedia.org/wikipedia/commons/b/b0/NewTux.svg';
function svg_loading_done_callback(doc) {
init(new THREE.SVGObject(doc));
animate();
};
svgManager.load(url,
svg_loading_done_callback,
function() {
console.log("Loading SVG...");
},
function() {
console.log("Error loading SVG!");
});
var camera, scene, renderer;
function init(svgObject) {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 100000);
camera.position.z = 1500;
svgObject.position.x = Math.random() * innerWidth;
svgObject.position.y = 200;
svgObject.position.z = Math.random() * 10000 - 5000;
svgObject.scale.x = svgObject.scale.y = svgObject.scale.z = 0.01;
scene = new THREE.Scene();
scene.add(svgObject);
var ambient = new THREE.AmbientLight(0x80ffff);
scene.add(ambient);
var directional = new THREE.DirectionalLight(0xffff00);
directional.position.set(-1, 0.5, 0);
scene.add(directional);
renderer = new THREE.SVGRenderer();
renderer.setClearColor(0xf0f0f0);
renderer.setSize(window.innerWidth, window.innerHeight - 5);
document.body.appendChild(renderer.domElement);
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
var time = Date.now() * 0.0002;
camera.position.x = Math.sin(time) * 200;
camera.position.z = Math.cos(time) * 200;
camera.lookAt(scene.position);
renderer.render(scene, camera);
}
* {
margin: 0
}
<script src="http://threejs.org/build/three.min.js"></script>
<script src="http://threejs.org/examples/js/renderers/SVGRenderer.js"></script>
<script src="http://threejs.org/examples/js/renderers/Projector.js"></script>
<script src="http://threejs.org/examples/js/loaders/SVGLoader.js"></script>
<script>
/**
* #name LegacySVGLoader
* #author mrdoob / http://mrdoob.com/
* #author zz85 / http://joshuakoo.com/
* #see https://github.com/mrdoob/three.js/issues/14387
*/
THREE.LegacySVGLoader = function(manager) {
this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager;
};
THREE.LegacySVGLoader.prototype = {
constructor: THREE.LegacySVGLoader,
load: function(url, onLoad, onProgress, onError) {
var scope = this;
var parser = new DOMParser();
var loader = new THREE.FileLoader(scope.manager);
loader.load(url, function(svgString) {
var doc = parser.parseFromString(svgString, 'image/svg+xml'); // application/xml
onLoad(doc.documentElement);
}, onProgress, onError);
}
};
</script>
This is current answer from latest three.js lib:
https://threejs.org/examples/?q=svg#webgl_loader_svg
but this code loads svg into geometry mesh, so it is not a DOM element, it zooms out just like any other 3d object. Its like a billboard in 3d scene. If someone needs this kind of behavior then its fine.
If you want to load SVG to be DOM element, to have it float over 3D scene, to be able to add mouse click and hover events... I asked for example and here it is:
https://github.com/mrdoob/three.js/issues/15528

How do I create an Android material design UI widget?

I did read new android material design guide but i am not able to find anything about how to create this UI widget(element). Apps like Gmail, S converter etc has updated their apps to support new material design.
I have added screenshot of it. Here is the link to it. because of low points i can't put the picture. sorry about it
Any suggestions on how shall i make it??
You are talking about the Floating Action Button. Bottom line is: there is no native "FAB" widget (at least for now), it is a custom layout that must be implemented.
If you really want to fully implement a Material Design app, I recommend you take a look at Google's 2014 I/O app. They have an example of a FAB layout here.
Here's also the code to create one. It is from this gist.
public class FloatingActionButton extends View {
Context context;
Paint mButtonPaint;
Paint mDrawablePaint;
Bitmap mBitmap;
boolean mHidden = false;
public FloatingActionButton(Context context) {
super(context);
this.context = context;
init(Color.WHITE);
}
public void init(int color) {
setWillNotDraw(false);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
mButtonPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mButtonPaint.setColor(color);
mButtonPaint.setStyle(Paint.Style.FILL);
mButtonPaint.setShadowLayer(10.0f, 0.0f, 3.5f, Color.argb(100, 0, 0, 0));
mDrawablePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
setClickable(true);
canvas.drawCircle(getWidth() / 2, getHeight() / 2, (float) (getWidth() / 2.6), mButtonPaint);
canvas.drawBitmap(mBitmap, (getWidth() - mBitmap.getWidth()) / 2,
(getHeight() - mBitmap.getHeight()) / 2, mDrawablePaint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
setAlpha(1.0f);
} else if (event.getAction() == MotionEvent.ACTION_DOWN) {
setAlpha(0.6f);
}
return super.onTouchEvent(event);
}
public void setColor(int color) {
init(color);
}
public void setDrawable(Drawable drawable) {
mBitmap = ((BitmapDrawable) drawable).getBitmap();
invalidate();
}
public void hide() {
if (!mHidden) {
ObjectAnimator scaleX = ObjectAnimator.ofFloat(this, "scaleX", 1, 0);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(this, "scaleY", 1, 0);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(scaleX, scaleY);
animSetXY.setInterpolator(new AccelerateInterpolator());
animSetXY.setDuration(100);
animSetXY.start();
mHidden = true;
}
}
public void show() {
if (mHidden) {
ObjectAnimator scaleX = ObjectAnimator.ofFloat(this, "scaleX", 0, 1);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(this, "scaleY", 0, 1);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(scaleX, scaleY);
animSetXY.setInterpolator(new OvershootInterpolator());
animSetXY.setDuration(200);
animSetXY.start();
mHidden = false;
}
}
public boolean isHidden() {
return mHidden;
}
public static class Builder {
private FrameLayout.LayoutParams params;
private final Activity activity;
int gravity = Gravity.BOTTOM | Gravity.RIGHT; // default bottom right
Drawable drawable;
int color = Color.WHITE;
int size = 0;
float scale = 0;
/**
* Constructor using a context for this builder and the
* {#link FloatingActionButton} it creates
* #param context
*/
public Builder(Activity context) {
scale = context.getResources().getDisplayMetrics().density;
// The calculation (value * scale + 0.5f) is a widely used to convert to dps to pixel
// units based on density scale
// see <a href="http://developer.android.com/guide/practices/screens_support.html">
// developer.android.com (Supporting Multiple Screen Sizes)</a>
size = (int) (72 * scale + 0.5f); // default size is 72dp by 72dp
params = new FrameLayout.LayoutParams(size, size);
params.gravity = gravity;
this.activity = context;
}
/**
* Sets the FAB gravity.
*/
public Builder withGravity(int gravity) {
this.gravity = gravity;
return this;
}
/**
* Sets the FAB margins in dp.
*/
public Builder withMargins(int left, int top, int right, int bottom) {
params.setMargins((int) (left * scale + 0.5f), (int) (top * scale + 0.5f),
(int) (right * scale + 0.5f), (int) (bottom * scale + 0.5f));
return this;
}
/**
* Sets the FAB drawable.
*
* #param drawable
*/
public Builder withDrawable(final Drawable drawable) {
this.drawable = drawable;
return this;
}
/**
* Sets the FAB color.
*
* #param color
*/
public Builder withColor(final int color) {
this.color = color;
return this;
}
/**
* Sets the FAB size.
*
* #param size
* #return
*/
public Builder withSize(int size) {
size = (int) (size * scale + 0.5f);
params = new FrameLayout.LayoutParams(size, size);
return this;
}
/**
* Creates a {#link FloatingActionButton} with the
* arguments supplied to this builder.
*/
public FloatingActionButton create() {
final FloatingActionButton button = new FloatingActionButton(activity);
button.setColor(this.color);
button.setDrawable(this.drawable);
params.gravity = this.gravity;
ViewGroup root = (ViewGroup) activity.findViewById(android.R.id.content);
root.addView(button, params);
return button;
}
}
}
Then you would add like this:
FloatingActionButton mFab = new FloatingActionButton.Builder(this)
.withColor(getResources().getColor(R.color.accent_color))
.withDrawable(getResources().getDrawable(R.drawable.fab_icon))
.withSize(72)
.withMargins(0, 0, 16, 16)
.create();

FBLoginView: login isn't performed

I'm adding FBLoginView to my ViewController < FBLoginViewDelegate >:
FBLoginView *loginview = [[FBLoginView alloc] init];
loginview.frame = CGRectOffset(loginview.frame, 5, 5);
loginview.delegate = self;
[self.view addSubview:loginview];
[loginview sizeToFit];
All the necessary fields in plist (FacebookAppID, FacebookDisplayName, URL Schemes) are all set according to the tutorial. The facebook app is also configured according to the tutorial (bundle ID is set, Facebook login is enabled).
But the login still isn't performed. When I press on "log in", I get redirected to the browser with facebook login, but when it's finished, I'm not logged in the app (loginViewFetchedUserInfo:user: isn't called, "log in" hasn't changed to "log out").
What can be the problem?
Everything worked after I implemented the following in the AppDelegate.m (taken from one of the official examples):
- (void)sessionStateChanged:(FBSession *)session
state:(FBSessionState) state
error:(NSError *)error
{
switch (state) {
case FBSessionStateOpen:
if (!error) {
// We have a valid session
//NSLog(#"User session found");
[FBRequestConnection
startForMeWithCompletionHandler:^(FBRequestConnection *connection,
NSDictionary<FBGraphUser> *user,
NSError *error) {
if (!error) {
self.loggedInUserID = user.id;
self.loggedInSession = FBSession.activeSession;
}
}];
}
break;
case FBSessionStateClosed:
case FBSessionStateClosedLoginFailed:
[FBSession.activeSession closeAndClearTokenInformation];
break;
default:
break;
}
[[NSNotificationCenter defaultCenter]
postNotificationName:FBSessionStateChangedNotification
object:session];
if (error) {
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:#"Error"
message:error.localizedDescription
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
}
}
/*
* Opens a Facebook session and optionally shows the login UX.
*/
- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
return [FBSession openActiveSessionWithReadPermissions:nil
allowLoginUI:allowLoginUI
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
[self sessionStateChanged:session
state:state
error:error];
}];
}
/*
*
*/
- (void) closeSession {
[FBSession.activeSession closeAndClearTokenInformation];
}
/*
* If we have a valid session at the time of openURL call, we handle
* Facebook transitions by passing the url argument to handleOpenURL
*/
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
// attempt to extract a token from the url
return [FBAppCall handleOpenURL:url sourceApplication:sourceApplication];
}
You need to add the following to the app delegate
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
// Call FBAppCall's handleOpenURL:sourceApplication to handle Facebook app responses
BOOL wasHandled = [FBAppCall handleOpenURL:url sourceApplication:sourceApplication];
// You can add your app-specific url handling code here if needed
return wasHandled;
}
You may need to implement the
(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url method
Be sure to call:
return [FBSession.activeSession handleOpenURL:url];
When applicable.
#Sergey: Are you want to open FBDialog on your native app or in browser? If you to want open in your native app then use "FBSessionLoginBehaviorForcingWebView". Here is my code that I am using:
NSArray *permission = [NSArray arrayWithObjects:kFBEmailPermission,kFBUserPhotosPermission, nil];
FBSession *session = [[FBSession alloc] initWithPermissions:permission];
[FBSession setActiveSession: [[FBSession alloc] initWithPermissions:permission] ];
[[FBSession activeSession] openWithBehavior:FBSessionLoginBehaviorForcingWebView completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
switch (status) {
case FBSessionStateOpen:
[self yourmethod];
break;
case FBSessionStateClosedLoginFailed: {
// prefer to keep decls near to their use
// unpack the error code and reason in order to compute cancel bool
NSString *errorCode = [[error userInfo] objectForKey:FBErrorLoginFailedOriginalErrorCode];
NSString *errorReason = [[error userInfo] objectForKey:FBErrorLoginFailedReason];
BOOL userDidCancel = !errorCode && (!errorReason || [errorReason isEqualToString:FBErrorLoginFailedReasonInlineCancelledValue]);
if(error.code == 2) {
UIAlertView *errorMessage = [[UIAlertView alloc] initWithTitle:#"FBAlertTitle"
message:#"FBAuthenticationErrorMessage"
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[errorMessage performSelectorOnMainThread:#selector(show) withObject:nil waitUntilDone:YES];
errorMessage = nil;
}
}
break;
// presently extension, log-out and invalidation are being implemented in the Facebook class
default:
break; // so we do nothing in response to those state transitions
}
}];
permission = nil;
or you want to open in browser then use following :
In your .h file
#import <FacebookSDK/FacebookSDK.h> and add FBLoginViewDelegate delegate
In you .m file
FBLoginView *loginview = [[FBLoginView alloc] init];
loginview.frame = CGRectOffset(loginview.frame, 5, 5);
loginview.delegate = self;
[self.view addSubview:loginview];
[loginview sizeToFit];
// use following delegate methods
- (void)loginViewShowingLoggedInUser:(FBLoginView *)loginView {
// first get the buttons set for login mode
}
- (void)loginViewFetchedUserInfo:(FBLoginView *)loginView
user:(id<FBGraphUser>)user {
// here we use helper properties of FBGraphUser to dot-through to first_name and
// id properties of the json response from the server; alternatively we could use
// NSDictionary methods such as objectForKey to get values from the my json object
NSLog(#"userprofile:%#",user);
}
- (void)loginViewShowingLoggedOutUser:(FBLoginView *)loginView {
//BOOL canShareAnyhow = [FBNativeDialogs canPresentShareDialogWithSession:nil];
}
- (void)loginView:(FBLoginView *)loginView handleError:(NSError *)error {
// see https://developers.facebook.com/docs/reference/api/errors/ for general guidance on error handling for Facebook API
// our policy here is to let the login view handle errors, but to log the results
NSLog(#"FBLoginView encountered an error=%#", error);
}

Clickbank api for getting the receipt information

I have tried creating a small class for clickbank which fetches the receipt information from the clickbank. I thought, it might be helpful for someone. In function get_payment_info($tries, $receipt) tries has been used because clickbank doesn't recognize transaction immediately after it happens.
<?php
define('CLICKBANK_DEV_KEY','DEV-KEY');
define('CLICKBANK_API_KEY','API-KEY');
Class ClickBank
{
/*
* $tries how many times to check for receipt
* because when you come back from clicbank it sometimes shows it invalid
*
* $receipt
*
* #return empty array if receipt not valid
* receipt info array if receipt is valid
*/
function get_payment_info($tries, $receipt){
$receipt_info = array();
while($tries>0 && count($receipt_info)==0){
$receipt_info = $this->get_receipt_info($receipt);
$tries--;
}
return $receipt_info;
}
function get_receipt_info($receipt){
$receipt_info = array();
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.clickbank.com/rest/1.2/orders/$receipt");
curl_setopt($ch, CURLOPT_HEADER, false);
//curl_setopt($ch, CURLOPT_GET, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Accept: application/json", "Authorization:".CLICKBANK_DEV_KEY.":".CLICKBANK_API_KEY));
$result = curl_exec($ch);
$curl_info = curl_getinfo($ch);
curl_close($ch);
if($curl_info['http_code']==200){
$receipt_info = json_decode($result);
}
return $receipt_info;
}
}
$clickbank = new ClickBank();
$receipt = $_GET['cbreceipt'];
// it will return you transaction details
$transaction_info = $clickbank->get_payment_info(10, $receipt);

Resources