As I receive numerous questions and suggestions concerning the custom drawing tool JavaScript interface of LectureNotes and how to implement specific drawing tools, I thought that it might be helpful to collect codes here, which should allow to easily copy them. Please feel invited to post additional ones!
To start, a simple dashed line with longer dashing
Code:
width = LN.getWidth();
height = LN.getHeight();
size = Math.min(width, height);
strokewidth = LN.getStrokeWidth();
dashing1 = 0.01 * size;
dashing2 = (LN.getStrokeCap() == 1) ? dashing1 : dashing1 + 2 * strokewidth;
x1 = LN.getX1();
y1 = LN.getY1();
x2 = LN.getX2();
y2 = LN.getY2();
LN.setDashing(dashing1, dashing2);
LN.drawLine(x1, y1, x2, y2);
or a dashed line for which the dashing is not fixed but depends on pencil width
Code:
strokewidth = LN.getStrokeWidth();
dashing1 = 10 * strokewidth;
dashing2 = (LN.getStrokeCap() == 1) ? dashing1 : dashing1 + 2 * strokewidth;
x1 = LN.getX1();
y1 = LN.getY1();
x2 = LN.getX2();
y2 = LN.getY2();
LN.setDashing(dashing1, dashing2);
LN.drawLine(x1, y1, x2, y2);
I dont know how to go about creating these tools, and sadly, at the moment I dont actually have the time to invest in learning any of it. So hopefully, someone here can help.
I'd like to create three drawing tools which are similar to existing ones
The tools I could use are:
-Therefore. As in, ==> Right now there are tools for arrows, I'd pretty must just like two horizontal lines instead of one.
-If and only if. As in, <==>. Right now there are tools for two headed arrow lines. Again, pretty must the same as that but two horizontal lines.
-Coordinate System, but with the addition of preplaced labels for each axis. That is, when giving it things like y min and y max, would it also be possible to have it ask for a text field for labels? So that label would show up, and scale with the rest of it?
If anyone who can tell me what to do, or better yet, provide the code for it, that would be great.
@mmcnulty: Double-lined arrows will come with the next update.
Concerning coordinate system: Text variables are presently not supported, one could only have an integer variable that then maps on a text.
Here's a script that draws an n-gon centered at the centre of the chosen rectangle and extending all the way across its shortest side. It takes 2 parameters: the number of sides and the angle (in degrees) at which the first point should be positioned (see the attached image for details).
Code:
width = LN.getWidth();
height = LN.getHeight();
pi = 3.1415927;
sides = LN.getParameter(1);
phi = LN.getParameter(2)*2*pi/360;
x1 = LN.getX1();
y1 = LN.getY1();
x2 = LN.getX2();
y2 = LN.getY2();
x0 = (x1+x2)/2;
y0 = (y1+y2)/2;
r = Math.min(x0-x1,y0-y1);
t = LN.getStrokeWidth();
LN.setStrokeWidth(3*t);
LN.drawPoint(x0, y0);
for (i=1 ; i<=sides ; i++){
LN.drawPoint(x0+r*Math.cos(2*pi*i/sides+phi),y0-r*Math.sin(2*pi*i/sides+phi));
}
LN.setStrokeWidth(t);
for (i=1 ; i<=sides ; i++){
LN.drawLine(x0+r*Math.cos(2*pi*i/sides+phi),y0-r*Math.sin(2*pi*i/sides+phi), x0+r*Math.cos(2*pi*(i+1)/sides+phi),y0-r*Math.sin(2*pi*(i+1)/sides+phi));
}
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
While creating the script I noticed that any error that would cause the script to fail (forgotten ; or any other bad syntax) would break that particular tool until LN was restarted. The rectangular area could still be chosen, but nothing would be drawn inside it. It took me a while to figure this out. At first I thought I had the wrong idea about either the scale or the axis orientation which caused the image to lie outside the bounded area. Just thought I should mention it in case someone else has the same problem. If you are sure your code should work, try restarting.
Here's another script. This one draws a rainbow coloured pie chart with up to 6 groups of data. Each parameter can take values between 0 and 100, so you can either enter the absolute numbers (if <100 for each group) or percentages. If you don't need all 6 you can set the extras to 0.
Code:
x1 = LN.getX1();
y1 = LN.getY1();
x2 = LN.getX2();
y2 = LN.getY2();
x0 = (x1+x2)/2;
y0 = (y1+y2)/2;
r = Math.min(x0-x1,y0-y1);
q1 = LN.getParameter(1);
q2 = LN.getParameter(2);
q3 = LN.getParameter(3);
q4 = LN.getParameter(4);
q5 = LN.getParameter(5);
q6 = LN.getParameter(6);
s = q1+q2+q3+q4+q5+q6;
pi = 3.1415927;
phi1 = 2*pi*q1/s;
phi2 = 2*pi*(q1+q2)/s;
phi3 = 2*pi*(q1+q2+q3)/s;
phi4 = 2*pi*(q1+q2+q3+q4)/s;
phi5 = 2*pi*(q1+q2+q3+q4+q5)/s;
phi6 = 2*pi;
LN.setColor(1,0,0);
LN.setAlpha(0.3);
LN.drawFilledArc(x0,y0,r,0,-phi1);
LN.setColor(1,0.5,0);
LN.setAlpha(0.3);
LN.drawFilledArc(x0,y0,r,-phi1,-phi2+phi1);
LN.setColor(1,1,0);
LN.setAlpha(0.3);
LN.drawFilledArc(x0,y0,r,-phi2,-phi3+phi2);
LN.setColor(0,1,0);
LN.setAlpha(0.3);
LN.drawFilledArc(x0,y0,r,-phi3,-phi4+phi3);
LN.setColor(0,0,1);
LN.setAlpha(0.3);
LN.drawFilledArc(x0,y0,r,-phi4,-phi5+phi4);
LN.setColor(1,0,1);
LN.setAlpha(0.3);
LN.drawFilledArc(x0,y0,r,-phi5,-phi6+phi5);
LN.setAlpha(1);
LN.setColor(0,0,0);
LN.drawCircle(x0,y0,r);
LN.drawLine(x0,y0,x0+r,y0);
LN.drawLine(x0,y0,x0+r*Math.cos(phi1),y0-r*Math.sin(phi1));
LN.drawLine(x0,y0,x0+r*Math.cos(phi2),y0-r*Math.sin(phi2));
LN.drawLine(x0,y0,x0+r*Math.cos(phi3),y0-r*Math.sin(phi3));
LN.drawLine(x0,y0,x0+r*Math.cos(phi4),y0-r*Math.sin(phi4));
LN.drawLine(x0,y0,x0+r*Math.cos(phi5),y0-r*Math.sin(phi5));
And one more. This one draws the pie chart in monochrome. The colour used to fill the area is the same as the colour of the currently active pencil. Opacity is inversely proportional to the square root of the percentage, so smaller areas are more opaque and larger areas are less opaque (giving the impression that the same amount of colour is spread over areas of different sizes).
Code:
x1 = LN.getX1();
y1 = LN.getY1();
x2 = LN.getX2();
y2 = LN.getY2();
x0 = (x1+x2)/2;
y0 = (y1+y2)/2;
r = Math.min(x0-x1,y0-y1);
q1 = LN.getParameter(1);
q2 = LN.getParameter(2);
q3 = LN.getParameter(3);
q4 = LN.getParameter(4);
q5 = LN.getParameter(5);
q6 = LN.getParameter(6);
s = q1+q2+q3+q4+q5+q6;
pi = 3.1415927;
phi1 = 2*pi*q1/s;
phi2 = 2*pi*(q1+q2)/s;
phi3 = 2*pi*(q1+q2+q3)/s;
phi4 = 2*pi*(q1+q2+q3+q4)/s;
phi5 = 2*pi*(q1+q2+q3+q4+q5)/s;
phi6 = 2*pi;
LN.setAlpha(1-Math.sqrt(q1/s));
LN.drawFilledArc(x0,y0,r,0,-phi1);
LN.setAlpha(1-Math.sqrt(q2/s));
LN.drawFilledArc(x0,y0,r,-phi1,-phi2+phi1);
LN.setAlpha(1-Math.sqrt(q3/s));
LN.drawFilledArc(x0,y0,r,-phi2,-phi3+phi2);
LN.setAlpha(1-Math.sqrt(q4/s));
LN.drawFilledArc(x0,y0,r,-phi3,-phi4+phi3);
LN.setAlpha(1-Math.sqrt(q5/s));
LN.drawFilledArc(x0,y0,r,-phi4,-phi5+phi4);
LN.setAlpha(1-Math.sqrt(q6/s));
LN.drawFilledArc(x0,y0,r,-phi5,-phi6+phi5);
LN.setAlpha(1);
LN.setColor(0,0,0);
LN.drawCircle(x0,y0,r);
LN.drawLine(x0,y0,x0+r,y0);
LN.drawLine(x0,y0,x0+r*Math.cos(phi1),y0-r*Math.sin(phi1));
LN.drawLine(x0,y0,x0+r*Math.cos(phi2),y0-r*Math.sin(phi2));
LN.drawLine(x0,y0,x0+r*Math.cos(phi3),y0-r*Math.sin(phi3));
LN.drawLine(x0,y0,x0+r*Math.cos(phi4),y0-r*Math.sin(phi4));
LN.drawLine(x0,y0,x0+r*Math.cos(phi5),y0-r*Math.sin(phi5));
Sent from my GT-N8010 using Tapatalk
A couple of scripts for people who, like me, draw graphs first and the marks the axes later The axes are drawn in black and the colour of the "curve" is the same as the currently selected pen.
You can see that the graphs are made up of a lot of dots if the y-axis is much taller than the x-axis, but I kinda like the effect
Bell curve (no parameters):
Code:
strokewidth = LN.getStrokeWidth();
head = 5*strokewidth;
open = 0.4;
headcos = head * Math.cos(open);
headsin = head * Math.sin(open);
x1 = LN.getX1();
y1 = LN.getY1();
x2 = LN.getX2();
y2 = LN.getY2();
red = LN.getRed();
green = LN.getGreen();
blue = LN.getBlue();
xmin = Math.min(x1, x2);
ymin = Math.min(y1, y2);
xmax = Math.max(x1, x2);
ymax = Math.max(y1, y2);
xavail = Math.max(0, xmax - xmin - headsin - 2 * headcos);
yavail = Math.max(0, ymax - ymin - headsin - 2 * headcos);
xorigin = headsin;
yorigin = headsin;
LN.setColor(0,0,0);
LN.drawLine((xmin + xmax)/2, ymin + headcos, (xmin + xmax)/2 , ymax);
LN.drawFilledTriangle( (xmin + xmax)/2 - headsin, ymin + headcos, (xmin + xmax)/2 , ymin, (xmin + xmax)/2 + headsin, ymin + headcos);
a = 0.8*(ymax-ymin);
b = (xmin + xmax)/2;
c = 0.8*(1/6)*(xmax-xmin);
d = ymax-yorigin;
LN.setStrokeWidth(1.2*strokewidth);
n = Math.floor((xmax-xmin)/2);
LN.setColor(red,green,blue);
for (i=0 ; i<=n-5 ; i++){
LN.drawPoint(b+i, -a*Math.exp(-i*i/(2*c*c))+d);
LN.drawPoint(b-i, -a*Math.exp(-i*i/(2*c*c))+d);
}
LN.setStrokeWidth(strokewidth);
LN.setColor(0,0,0);
LN.drawLine(xmin, ymax - yorigin, xmax - headcos, ymax - yorigin);
LN.drawFilledTriangle(xmax - headcos, ymax - yorigin + headsin, xmax, ymax - yorigin, xmax - headcos, ymax - yorigin - headsin);
Quadratic parabola (again, no parameters):
Code:
strokewidth = LN.getStrokeWidth();
head = 5*strokewidth;
open = 0.4;
headcos = head * Math.cos(open);
headsin = head * Math.sin(open);
x1 = LN.getX1();
y1 = LN.getY1();
x2 = LN.getX2();
y2 = LN.getY2();
red = LN.getRed();
green = LN.getGreen();
blue = LN.getBlue();
xmin = Math.min(x1, x2);
ymin = Math.min(y1, y2);
xmax = Math.max(x1, x2);
ymax = Math.max(y1, y2);
xavail = Math.max(0, xmax - xmin - headsin - 2 * headcos);
yavail = Math.max(0, ymax - ymin - headsin - 2 * headcos);
xorigin = headsin;
yorigin = headsin;
LN.setColor(0,0,0);
LN.drawLine(xmin, ymax - yorigin, xmax - headcos, ymax - yorigin);
LN.drawLine((xmin + xmax)/2, ymin + headcos, (xmin + xmax)/2 , ymax);
LN.drawFilledTriangle(xmax - headcos, ymax - yorigin + headsin, xmax, ymax - yorigin, xmax - headcos, ymax - yorigin - headsin);
LN.drawFilledTriangle( (xmin + xmax)/2 - headsin, ymin + headcos, (xmin + xmax)/2 , ymin, (xmin + xmax)/2 + headsin, ymin + headcos);
a = 4*(ymax-ymin);
b = (xmin + xmax)/2;
d = ymax-yorigin;
LN.setStrokeWidth(1.2*strokewidth);
n = Math.floor((xmax-xmin)/2);
c = (xmax-xmin);
LN.setColor(red,green,blue);
for (i=0 ; i<=n ; i++){
LN.drawPoint(b+i,-a*(i/c)*(i/c)+d);
LN.drawPoint(b-i,-a*(i/c)*(i/c)+d);
}
LN.setStrokeWidth(strokewidth);
And the final ones for today, these two scripts compute the probabilities for two well-known discrete probability distributions and draw a schematic representation.
Poisson: parameters are lambda = the expected value (and arbitrary positive real number) and k = the maximum value for which P(X=i) should be calculated and ploted (a positive integer).
Code:
strokewidth = LN.getStrokeWidth();
head = 5*strokewidth;
open = 0.4;
headcos = head * Math.cos(open);
headsin = head * Math.sin(open);
x1 = LN.getX1();
y1 = LN.getY1();
x2 = LN.getX2();
y2 = LN.getY2();
red = LN.getRed();
green = LN.getGreen();
blue = LN.getBlue();
xmin = Math.min(x1, x2);
ymin = Math.min(y1, y2);
xmax = Math.max(x1, x2);
ymax = Math.max(y1, y2);
xavail = Math.max(0, xmax - xmin - headsin - 2 * headcos);
yavail = Math.max(0, ymax - ymin - headsin - 2 * headcos);
xorigin = headsin;
yorigin = headsin;
l = LN.getParameter(1);
k = LN.getParameter(2);
a = 0.9*(ymax-ymin);
b = xmin + xorigin;
d = ymax-yorigin;
n = (xmax-xmin)*0.9/k;
c = (xmax-xmin);
LN.setStrokeWidth(3*strokewidth);
fac = 1;
for (i=1; i<=k ; i++){
fac = fac*i;
LN.drawLine(b+i*n,d-strokewidth,b+i*n,-a*(Math.pow(l,i)*Math.exp(-l)/fac)+d+strokewidth);
}
LN.setStrokeWidth(strokewidth);
LN.setColor(0,0,0);
LN.drawLine(xmin+xorigin, ymin + headcos, xmin +xorigin , ymax);
LN.drawFilledTriangle(xmax - headcos, ymax - yorigin + headsin, xmax, ymax - yorigin, xmax - headcos, ymax - yorigin - headsin);
LN.drawFilledTriangle( xmin + xorigin - headsin, ymin + headcos, xmin + xorigin , ymin, xmin + xorigin + headsin, ymin + headcos);
LN.setStrokeWidth(3*strokewidth);
LN.setColor(red,green,blue);
LN.drawLine(b,d-strokewidth,b,-a*Math.exp(-l)+d+strokewidth);
LN.drawPoint(b,d-a);
LN.setColor(0,0,0);
LN.setTextSize(16);
LN.drawText(1,b+10,d-a+6);
LN.drawText(Math.exp(-l),(xmin+xmax)/2,-a+d+6);
fac = 1;
for (i=1; i<=k ; i++){
fac = fac*i;
LN.drawText(Math.pow(l,i)*Math.exp(-l)/fac,(xmin+xmax)/2,-a+d+6+18*i);
}
LN.setStrokeWidth(strokewidth);
LN.drawLine(xmin, ymax - yorigin, xmax - headcos, ymax - yorigin);
Geometric: parameters are p = the probability of a certain event occuring in one trial (a real between 0 and 1) and k = the maximum value for which P(X=i) should be calculated and ploted (a positive integer).
Code:
strokewidth = LN.getStrokeWidth();
head = 5*strokewidth;
open = 0.4;
headcos = head * Math.cos(open);
headsin = head * Math.sin(open);
x1 = LN.getX1();
y1 = LN.getY1();
x2 = LN.getX2();
y2 = LN.getY2();
red = LN.getRed();
green = LN.getGreen();
blue = LN.getBlue();
xmin = Math.min(x1, x2);
ymin = Math.min(y1, y2);
xmax = Math.max(x1, x2);
ymax = Math.max(y1, y2);
xavail = Math.max(0, xmax - xmin - headsin - 2 * headcos);
yavail = Math.max(0, ymax - ymin - headsin - 2 * headcos);
xorigin = headsin;
yorigin = headsin;
p = LN.getParameter(1);
k = LN.getParameter(2);
q = 1-p;
a = 0.9*(ymax-ymin);
b = xmin + xorigin;
d = ymax-yorigin;
n = (xmax-xmin)*0.9/k;
c = (xmax-xmin);
LN.setStrokeWidth(3*strokewidth);
for (i=1; i<=k ; i++){
LN.drawLine(b+i*n,d-strokewidth,b+i*n,-a*p*Math.pow(q,i)+d+strokewidth);
}
LN.setStrokeWidth(strokewidth);
LN.setColor(0,0,0);
LN.drawLine(xmin+xorigin, ymin + headcos, xmin +xorigin , ymax);
LN.drawFilledTriangle(xmax - headcos, ymax - yorigin + headsin, xmax, ymax - yorigin, xmax - headcos, ymax - yorigin - headsin);
LN.drawFilledTriangle( xmin + xorigin - headsin, ymin + headcos, xmin + xorigin , ymin, xmin + xorigin + headsin, ymin + headcos);
LN.setStrokeWidth(3*strokewidth);
LN.setColor(red,green,blue);
LN.drawLine(b,d-strokewidth,b,-a*p+d+strokewidth);
LN.drawPoint(b,d-a);
LN.setColor(0,0,0);
LN.setTextSize(16);
LN.drawText(1,b+10,d-a+6);
for (i=0; i<=k ; i++){
LN.drawText(p*Math.pow(q,i),(xmin+xmax)/2,-a+d+6+18*i);
}
LN.setStrokeWidth(strokewidth);
LN.drawLine(xmin, ymax - yorigin, xmax - headcos, ymax - yorigin);
A code snippet
Here is my code for a bar graph. Some of the code is based on the standard examples from Acadoid.
It can have up to 6 bars (I guess more could be added). Error checking is limited so follow the following rules:
If you only want 3 bars, enter the first 3 numbers. For the 4th and beyond only use -1. Example:
First: 20
Second: 30
Third: 50
Fourth: -1
Fifth: -1
Sixth: -1
Works but...
First: 20
Second: 30
Third: 50
Fourth: -1
Fifth: -1
Sixth: 30
Doesn't Work as planned since my code makes assumptions.
I have included a picture which show this in action along with some other stuff I will post.
Enjoy!
Code:
width = LN.getWidth();
height = LN.getHeight();
total = 0;
var colours = new Array();
colours[1]= new Array();
colours[1][1]=1;
colours[1][2]=0;
colours[1][3]=0;
colours[2]= new Array();
colours[2][1]=0;
colours[2][2]=0;
colours[2][3]=1;
colours[3]= new Array();
colours[3][1]=0;
colours[3][2]=1;
colours[3][3]=0;
colours[4]= new Array();
colours[4][1]=1;
colours[4][2]=0;
colours[4][3]=1;
colours[5]= new Array();
colours[5][1]=1;
colours[5][2]=1;
colours[5][3]=0;
colours[6]= new Array();
colours[6][1]=0;
colours[6][2]=1;
colours[6][3]=1;
var parameterList=new Array();
totalParams=0;
maxValue=0;
x1 = LN.getX1()+3;
y1 = LN.getY1()+3;
x2 = LN.getX2()-3;
y2 = LN.getY2()-3;
for(i = 1; i <= 6; i++) {
parameterList[i] = LN.getParameter(i);
if (parameterList[i] > maxValue) {
maxValue= parameterList[i];
}
if (parameterList[i] >= 0) {
totalParams+=1;
total += parameterList[i];
}
}
curPos=0;
barWidth= Math.abs(x2-x1)/totalParams;
for(i = 1; i <= totalParams; i++) {
LN.setColor(colours[i][1], colours[i][2], colours[i][3]);
LN.drawFilledRect(x1+curPos, y2, x1+curPos+barWidth, y2-Math.abs(y2-y1)*(parameterList[i]/maxValue));
curPos += barWidth;
}
LN.setColor();
LN.drawLine(x1, y1-3, x1, y2+3);
LN.drawLine(x1-3, y2, x2+3, y2);
curPos=0;
for(i = 1; i <= totalParams; i++) {
LN.drawRect(x1+curPos, y2, x1+curPos+barWidth, y2-Math.abs(y2-y1)*(parameterList[i]/maxValue));
LN.drawLine( x1+curPos+barWidth , y2, x1+curPos+barWidth , y2+3);
curPos += barWidth;
}
List bullets
Here is the code for the bullets seen in my previous post. The snap-to-grid code was stolen from the included examples.
Code:
width = LN.getWidth();
scale = LN.getScale ();
step = width / 150 + scale * width / 25;
x1 = LN.getX1();
y1 = LN.getY1();
x2 = LN.getX2() - 10;
y2 = LN.getY2() - 10;
x1g = Math.floor((x1 - (step / 2)) / step + 0.5) * step;
y1g = Math.floor((y1 - (step / 2)) / step + 0.5) * step;
x2g = Math.floor((x2 - (step / 2)) / step + 0.5) * step;
y2g = Math.floor((y2 - (step / 2)) / step + 0.5) * step;
tall = scale * 14;
wide = tall * 2;
LN.setClip(x2g - tall, y2g- tall, x2g + wide, y2g + tall);
LN.drawLine(x2g, y2g, x2g - tall, y2g - tall);
LN.drawLine(x2g, y2g, x2g - tall, y2g + tall);
LN.drawLine(x2g - tall, y2g -tall, x2g + wide, y2g);
LN.drawLine(x2g - tall, y2g + tall, x2g + wide, y2g);
---------- Post added at 04:07 PM ---------- Previous post was at 04:03 PM ----------
And the check boxes. More code borrowing here...
Code:
width = LN.getWidth();
scale = LN.getScale ();
step = width / 150 + scale * width / 25;
x1 = LN.getX1();
y1 = LN.getY1();
x2 = LN.getX2() - 10;
y2 = LN.getY2() - 10;
x1g = Math.floor((x1 - (step / 2)) / step + 0.5) * step;
y1g = Math.floor((y1 - (step / 2)) / step + 0.5) * step;
x2g = Math.floor((x2 - (step / 2)) / step + 0.5) * step;
y2g = Math.floor((y2 - (step / 2)) / step + 0.5) * step;
tall = scale * 12;
wide = tall * 2;
LN.setClip( x2g - wide/2, y2g - wide/2, x2g+ wide/2, y2g + wide/2 );
LN.drawRect(x2g - wide/2, y2g - wide/2, x2g+ wide/2, y2g + wide/2);
---------- Post added at 04:12 PM ---------- Previous post was at 04:07 PM ----------
Enjoy and if anyone has a request I am sure someone might help you out... myself included.
Star:
Code:
x1 = LN.getX1();
y1 = LN.getY1();
x2 = LN.getX2();
y2 = LN.getY2();
pi = 3.14159;
r = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
xmin = x1 - r;
ymin = y1 - r;
xmax = x1 + r;
ymax = y1 + r;
scaler = r;
c1 = scaler * (Math.sqrt (5)-1) / 4;
c2 = scaler * (Math.sqrt (5)+1) / 4;
s1 = scaler * Math.sqrt (10 + 2 * Math.sqrt (5)) / 4;
s2 = scaler * Math.sqrt (10 - 2 * Math.sqrt (5)) / 4;
LN.setClip(xmin, ymin, xmax, ymax);
LN.drawLine(x1 + scaler, y1, x1 - c2, y1 + s2);
LN.drawLine(x1 + scaler, y1, x1 - c2, y1 - s2);
LN.drawLine(x1 - c2, y1 + s2, x1 + c1, y1 - s1);
LN.drawLine(x1 - c2, y1 - s2, x1 + c1, y1 + s1);
LN.drawLine(x1 + c1, y1 + s1, x1 + c1, y1 - s1);
Happy face:
Code:
x1 = LN.getX1();
y1 = LN.getY1();
x2 = LN.getX2();
y2 = LN.getY2();
r = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
xmin = x1 - r;
ymin = y1 - r;
xmax = x1 + r;
ymax = y1 + r;
eye = 1+ r/ 12;
LN.setClip(xmin, ymin, xmax, ymax);
LN.drawOval(x1, y1, r, r);
LN.drawFilledOval(x1 + r/ 3, y1 - r/3, eye, eye);
LN.drawFilledOval(x1 - r/ 3, y1 - r/3, eye, eye);
LN.drawArc(x1, y1, r / 1.8, 0, 3.14);
@acadoid: Any chance we will be able to use more than 6 parameters in the future? I'm planning on making a script that takes your sample and returns its average and sample standard deviation. If it were possible to go up to at least 10 parameters that would be great.
Fat arrows
This one draws a large, hollow arrow, using acadoid's snap-to-grid code:
Code:
width = LN.getWidth();
height = LN.getHeight();
scale = LN.getScale();
step = width / 150 + scale * width / 25;
x1 = LN.getX1();
y1 = LN.getY1();
x2 = LN.getX2();
y2 = LN.getY2();
x1g = (step / 2) + Math.floor((x1 - (step / 2)) / step + 0.5) * step;
y1g = (step / 2) + Math.floor((y1 - (step / 2)) / step + 0.5) * step;
x2g = (step / 2) + Math.floor((x2 - (step / 2)) / step + 0.5) * step;
y2g = (step / 2) + Math.floor((y2 - (step / 2)) / step + 0.5) * step;
arrowLength=Math.sqrt((x2g-x1g)*(x2g-x1g)+(y2g-y1g)*(y2g-y1g));
theta=Math.atan((y2g-y1g)/(x2g-x1g));
if (x2g>=x1g) {
xa=-0.2* arrowLength*Math.sin(theta)+x1g;
ya=0.2*arrowLength*Math.cos(theta)+y1g;
xb=0.2* arrowLength*Math.sin(theta)+x1g;
yb=-0.2*arrowLength*Math.cos(theta)+y1g;
xc=0.6*arrowLength*Math.cos(theta)+0.2* arrowLength*Math.sin(theta)+x1g;
yc=0.6*arrowLength*Math.sin(theta)-0.2*arrowLength*Math.cos(theta)+y1g;
xd=0.6*arrowLength*Math.cos(theta)+0.4* arrowLength*Math.sin(theta)+x1g;
yd=0.6*arrowLength*Math.sin(theta)-0.4*arrowLength*Math.cos(theta)+y1g;
xe=arrowLength*Math.cos(theta)+x1g;
ye=arrowLength*Math.sin(theta)+y1g;
xf=0.6*arrowLength*Math.cos(theta)-0.4* arrowLength*Math.sin(theta)+x1g;
yf=0.6*arrowLength*Math.sin(theta)+0.4*arrowLength*Math.cos(theta)+y1g;
xg=0.6*arrowLength*Math.cos(theta)-0.2* arrowLength*Math.sin(theta)+x1g;
yg=0.6*arrowLength*Math.sin(theta)+0.2*arrowLength*Math.cos(theta)+y1g;
}
else {
xa=x1g-(-0.2* arrowLength*Math.sin(theta));
ya=y1g-(0.2*arrowLength*Math.cos(theta));
xb=x1g-(0.2* arrowLength*Math.sin(theta));
yb=y1g-(-0.2*arrowLength*Math.cos(theta));
xc=x1g-(0.6*arrowLength*Math.cos(theta)+0.2* arrowLength*Math.sin(theta));
yc=y1g-(0.6*arrowLength*Math.sin(theta)-0.2*arrowLength*Math.cos(theta));
xd=x1g-(0.6*arrowLength*Math.cos(theta)+0.4* arrowLength*Math.sin(theta));
yd=y1g-(0.6*arrowLength*Math.sin(theta)-0.4*arrowLength*Math.cos(theta));
xe=x1g-(arrowLength*Math.cos(theta));
ye=y1g-(arrowLength*Math.sin(theta));
xf=x1g-(0.6*arrowLength*Math.cos(theta)-0.4* arrowLength*Math.sin(theta));
yf=y1g-(0.6*arrowLength*Math.sin(theta)+0.4*arrowLength*Math.cos(theta));
xg=x1g-(0.6*arrowLength*Math.cos(theta)-0.2* arrowLength*Math.sin(theta));
yg=y1g-(0.6*arrowLength*Math.sin(theta)+0.2*arrowLength*Math.cos(theta));
}
xmin = Math.min(xa, xb, xc, xd, xe, xf, xg);
ymin = Math.min(ya, yb, yc, yd, ye, yf, yg);
xmax = Math.max(xa, xb, xc, xd, xe, xf, xg);
ymax = Math.max(ya, yb, yc, yd, ye, yf, yg);
LN.setClip(xmin, ymin, xmax, ymax);
LN.drawLine(xa, ya, xb, yb);
LN.drawLine(xc, yc, xb, yb);
LN.drawLine(xc, yc, xd, yd);
LN.drawLine(xe, ye, xd, yd);
LN.drawLine(xe, ye, xf, yf);
LN.drawLine(xf, yf, xg, yg);
LN.drawLine(xg, yg, xa, ya);
@Tintinnuntius & Canguy247: Many thanks for posting the codes!
@Tintinnuntius: I actually thought that nobody would use all six parameters... More parameters can be added, I will increase the maximal number to ten. Anticipating your question: There has to be a maximal number of parameters due to the Android dialog resources.
Many thanks and a request/suggestion
First I want to say THANK-YOU to acadoid for this wonderful addition. It has surpassed my expectations.
Next, I would like to make a suggestion. These tools open the possibility for libraries (which I think You were considering in the other thread). My suggestion is to adjust the interface to allow 2 libraries to be loaded at a time with a simple dropdown or arrows to switch between installed libraries. That would allow someone to load a library, which can be customized by picking tools from other libraries, which does all of the most comkon things they need such as bullets and boxes. They could then have the second library which they can switch depending on their task. This way we could build libraries of schematic symbols for electronics, or flowchart symbols, or pukps and valves and the user could switch depending on their use at the time.
Also, it would be great if the custom tools were represented by pictures instead of numbers, but I see the difficulty in making this practical.
Finally, is it possible to have a small status bar as part of the floating tool widget which tells the user what tool/library is selected?
And thanks again!
Canguy247 said:
Also, it would be great if the custom tools were represented by pictures instead of numbers, but I see the difficulty in making this practical.
Click to expand...
Click to collapse
How about at least replacing numbers by a 2-letter code (that would still fit in the small window and be easily legible). The code is something one could specify while scripting the tool (just an extra input next to the box that lets you name the tool) and it would be easier to remember. For example:
- T for a table,
- Pn for a polygon on n vertices,
- sd for a tool that calculates the standard deviation of given data,
- ...
instead of
- 1 for a table,
- 13 for a polygon on n vertices,
- 5 for a tool that calculates the standard deviation of given data,
- ...
The toolbox would then look like a tiny periodic table
@Canguy247: You are not the first to suggest container/groups/libraries for custom drawing tools. I have that on my to-do-list.
I am also considering to allow small icons. The problem is not the icons of the custom drawing tools that LectureNotes ships with, but the custom drawing tools that users define. Note that there is also a drawing tools menu in which you can select drawing tools and custom drawing tools by name.
@Tintinnuntius: Letters or double-letters might be an option, but I guess that a small icon is better, isn't it?
acadoid said:
@Tintinnuntius: Letters or double-letters might be an option, but I guess that a small icon is better, isn't it?
Click to expand...
Click to collapse
An icon is better, of course. Would we be able to design and import our own? Or even better, just cut it from LN notebook.
@Tintinnuntius: The question of how to handle the icons is what makes adding these icons a bit complicated.
acadoid said:
@Tintinnuntius: The question of how to handle the icons is what makes adding these icons a bit complicated.
Click to expand...
Click to collapse
I don't know if this would work or not, but could you just develop an algorithm to use the javascript code for each tool to generate the icons for that tool automatically?
I've come across a funny bug in the pencil toolbox. If both the standard and custom tools are shown, the numbers for custom tools are nice and thin, but if the standard tools are removed, the numbers for custom tools get all fat
Related
Hey guys,
Have you ever had problem logging on a SSL certificate network?? An example is the cisco authentication on the wifi ( like my college has ). Well looking around I found this solution posted by dalvik.
http://code.google.com/p/android/issues/detail?id=1597#c18
This certainly is something that will be released on source.android.com (aka aosp)
when the Froyo code is released. In the meanwhile, I tryed to explain the change so
that people making custom ROMs could feel free to fix it. To be more explicit, here
is the exact diff:
diff --git a/core/java/android/net/http/SslCertificate.java
b/core/java/android/net/http/SslCertificate.java
index 46b2bee..2214405 100644
--- a/core/java/android/net/http/SslCertificate.java
+++ b/core/java/android/net/http/SslCertificate.java
@@ -196,26 +196,31 @@ public class SslCertificate {
*/
public DName(String dName) {
if (dName != null) {
- X509Name x509Name = new X509Name(mDName = dName);
-
- Vector val = x509Name.getValues();
- Vector oid = x509Name.getOIDs();
-
- for (int i = 0; i < oid.size(); i++) {
- if (oid.elementAt(i).equals(X509Name.CN)) {
- mCName = (String) val.elementAt(i);
- continue;
- }
-
- if (oid.elementAt(i).equals(X509Name.O)) {
- mOName = (String) val.elementAt(i);
- continue;
- }
-
- if (oid.elementAt(i).equals(X509Name.OU)) {
- mUName = (String) val.elementAt(i);
- continue;
+ mDName = dName;
+ try {
+ X509Name x509Name = new X509Name(dName);
+
+ Vector val = x509Name.getValues();
+ Vector oid = x509Name.getOIDs();
+
+ for (int i = 0; i < oid.size(); i++) {
+ if (oid.elementAt(i).equals(X509Name.CN)) {
+ mCName = (String) val.elementAt(i);
+ continue;
+ }
+
+ if (oid.elementAt(i).equals(X509Name.O)) {
+ mOName = (String) val.elementAt(i);
+ continue;
+ }
+
+ if (oid.elementAt(i).equals(X509Name.OU)) {
+ mUName = (String) val.elementAt(i);
+ continue;
+ }
}
+ } catch (IllegalArgumentException ex) {
+ // thrown if there is an error parsing the string
}
}
}
I'm not a developer and I don't have idea how to implement this patch to the rom, but if anybody knows how, I'll be happy to test the rom.
Thanks
Christian
Hello,
i would like to connect my desire with vpn to my fritzxbox.
can someone help me?
what do i have to choose?
L2TP-VPN
L2TP/IPSec PSK-VPN
L2TP/IPSec CRT-VPN
i have this two files vpnuser.cfg and vpnuser.vpn
there should be all necessitate data but don't know what to take.
cpnuser.vpn
Code:
n:version:3
n:network-ike-port:500
n:network-mtu-size:1380
n:client-addr-auto:1
n:network-natt-port:4500
n:network-natt-rate:15
n:network-frag-size:540
n:network-dpd-enable:1
n:client-banner-enable:1
n:network-notify-enable:1
n:client-dns-used:0
n:client-dns-auto:1
n:client-dns-suffix-auto:1
n:client-splitdns-used:1
n:client-splitdns-auto:0
n:client-wins-used:0
n:client-wins-auto:1
n:phase1-dhgroup:2
n:phase1-keylen:256
n:phase1-life-secs:86400
n:phase1-life-kbytes:0
n:vendor-chkpt-enable:0
n:phase2-keylen:256
n:phase2-life-secs:3600
n:phase2-life-kbytes:0
n:policy-nailed:0
n:policy-list-auto:0
s:network-host:dyndns
s:client-auto-mode:pull
s:client-iface:virtual
s:network-natt-mode:enable
s:network-frag-mode:enable
s:auth-method:mutual-psk
s:ident-client-type:ufqdn
s:ident-server-type:address
s:ident-client-data:myusername
b:auth-mutual-psk:long_code
s:phase1-exchange:aggressive
s:phase1-cipher:aes
s:phase1-hash:sha1
s:phase2-transform:esp-aes
s:phase2-hmac:sha1
s:ipcomp-transform:deflate
n:phase2-pfsgroup:2
s:policy-list-include:192.168.178.0 / 255.255.255.0
vpnuser.cfg
Code:
/*
* C:\Users\myname\AppData\Roaming\AVM\FRITZ!Fernzugang\dyndns\user\vpnuser.cfg
* Tue Feb 16 11:18:33 2010
*/
version {
revision = "$Revision: 1.30 $";
creatversion = "1.1";
}
pwcheck {
}
datapipecfg {
security = dpsec_quiet;
icmp {
ignore_echo_requests = no;
destunreach_rate {
burstfactor = 6;
timeout = 1;
}
timeexceeded_rate {
burstfactor = 6;
timeout = 1;
}
echoreply_rate {
burstfactor = 6;
timeout = 1;
}
}
masqtimeouts {
tcp = 15m;
tcp_fin = 2m;
tcp_rst = 3s;
udp = 5m;
icmp = 30s;
got_icmp_error = 15s;
any = 5m;
tcp_connect = 6m;
tcp_listen = 2m;
}
ipfwlow {
input {
}
output {
}
}
ipfwhigh {
input {
}
output {
}
}
NAT_T_keepalive_interval = 20;
}
targets {
policies {
name = "mydyn.dns";
connect_on_channelup = no;
always_renew = no;
reject_not_encrypted = no;
dont_filter_netbios = yes;
localip = 0.0.0.0;
virtualip = 192.168.178.201;
remoteip = 0.0.0.0;
remotehostname = "mydyn.dns";
localid {
user_fqdn = "username";
}
mode = mode_aggressive;
phase1ss = "all/all/all";
keytype = keytype_pre_shared;
key = "long code";
cert_do_server_auth = no;
use_nat_t = yes;
use_xauth = no;
use_cfgmode = no;
phase2localid {
ipaddr = 192.168.178.201;
}
phase2remoteid {
ipnet {
ipaddr = 192.168.178.0;
mask = 255.255.255.0;
}
}
phase2ss = "esp-all-all/ah-none/comp-all/pfs";
accesslist = "permit ip any 192.168.178.0 255.255.255.0";
wakeupremote = no;
}
}
policybindings {
}
// EOF
can someone help me? thanks in advance
..any updates on this ?
I'm facing the same problem
,Wolfgang
never seen anything like that
this may help you
show post#775248 there is a solution for vpnc and fritzbox
mp1405 said:
show post#775248 there is a solution for vpnc and fritzbox
Click to expand...
Click to collapse
Where is this post#775248?
Hello there,
1. It is necessary that your device is rooted.
2. In order to connect via Fritz!VPN you need to use VPNC Widget. If "check prerequisites" states that it should work you are good to go.
3. The config file for FritzBox needs to look like this in order to work with Android devices. You need to change the UPPERCASE values *and IF changed from the 192.168.178.X default also change IP settings* afterwards enter these values in VPNC Widget and it should work.
/*
/*
*C:\Users\tom\AppData\Roaming\AVM\FRITZ!Fernzugang\fritzbox_avmvpn_dyndns_org.cfg
* Mon Mar 07 17:49:59 2011
*/
vpncfg {
connections {
enabled = yes;
conn_type = conntype_user;
name = "NAMEINFRITZGUI";
always_renew = no;
reject_not_encrypted = no;
dont_filter_netbios = yes;
localip = 0.0.0.0;
local_virtualip = 0.0.0.0;
remoteip = 0.0.0.0;
remote_virtualip = 192.168.100.201;
remoteid {
key_id = "USER";
}
mode = phase1_mode_aggressive;
phase1ss = "all/all/all";
keytype = connkeytype_pre_shared;
key = "PASSWORD";
cert_do_server_auth = no;
use_nat_t = yes;
use_xauth = yes;
use_cfgmode = no;
xauth {
valid = yes;
username = "USER1";
passwd = "PASSWORT1";
}
phase2localid {
ipnet {
ipaddr = 0.0.0.0;
mask = 0.0.0.0;
}
}
phase2remoteid {
ipaddr = 192.168.100.201;
}
phase2ss = "esp-all-all/ah-none/comp-all/no-pfs";
accesslist = "permit ip 0.0.0.0 0.0.0.0 192.168.100.201 255.255.255.255";
}
ike_forward_rules = "udp 0.0.0.0:500 0.0.0.0:500",
"udp 0.0.0.0:4500 0.0.0.0:4500";
}
// EOF
Click to expand...
Click to collapse
Greetings
Geniac
@geniac
Thank you
Hello all ...
I'd like to connect my HTC1s via VPN to my Fritzbox 3170.
The connection works, I have access to my homenetwork and a small bandwidth to check my emails, but when I start the browser or speedtest there's no connection.
I use cm9 alpha14 and I tried VPNC Widget and vpncilla as well as onboard vpn.
Do I have to make further modifications to my Fritzbox?
for the cfg - file I used the code posted by geniac
thanks 4 ur help
greetz
Tomcatz
Code:
private static string Post(string url, string data)
{
System.Net.WebRequest request1 = WebRequest.Create(url);
request1.Method = "POST";
request1.ContentType = "application/json";
byte[] byteData = Encoding.UTF8.GetBytes(data);
request1.ContentLength = byteData.Length;
using (Stream s = request1.GetRequestStream())
{
s.Write(byteData, 0, byteData.Length);
s.Close();
}
string replyData;
using (HttpWebResponse response = (HttpWebResponse)request1.GetResponse())
{
using (Stream dataStream = response.GetResponseStream())
{
using (StreamReader reader = new StreamReader(dataStream))
{
replyData = reader.ReadToEnd();
}
}
}
I am receiving an error on [request1.ContentLength] and using (Stream s = request1.GetRequestStream())
pls i really need assistance on this
Hello,
I have a trouble with a string text encode after decompile an APK file.
I used APK Tool decompile. The origin file http_//file.9app.info/files/tuan/tuan2india/9-apps.apk
The code was encoded here:
Code:
public class API
extends Activity
{
public static String a = "081b11458016006d513b0290cc7be0b39c28626ea506b9ed291b125114f2a38369a42e77a066a7789e5883ed47113fc3";
public static String b = "081b11458016006d513b0290cc7be0b36f01584bcfccde8bd9e2bd628ca804e7056b175ad6a1fa1bf3cf31d8a28b94e9";
public static String c = "081b11458016006d513b0290cc7be0b36f01584bcfccde8bd9e2bd628ca804e7056b175ad6a1fa1bf3cf31d8a28b94e9";
public static JSONObject d = new JSONObject();
public static String e = "";
private static int h = 0;
private boolean f = false;
private ProgressDialog g;
private JSONObject a(JSONObject paramJSONObject)
{
int i = 0;
Iterator localIterator = paramJSONObject.keys();
int[] arrayOfInt = new int[paramJSONObject.length()];
int j = 0;
JSONObject localJSONObject1;
int m;
if (!localIterator.hasNext())
{
Arrays.sort(arrayOfInt);
localJSONObject1 = new JSONObject();
m = arrayOfInt.length;
}
for (;;)
{
if (i >= m)
{
return localJSONObject1;
int k = j + 1;
arrayOfInt[j] = Integer.parseInt(((String)localIterator.next()).toString());
j = k;
break;
}
String str1 = Integer.toString(arrayOfInt[i]);
try
{
JSONObject localJSONObject2 = (JSONObject)paramJSONObject.get(str1);
if (((paramJSONObject.get(str1) instanceof JSONObject)) && (!a(localJSONObject2.get("package").toString())))
{
String str2 = localJSONObject2.get("package").toString();
if (!getApplicationContext().getSharedPreferences("listpacks", 0).getBoolean(str2, false)) {
if (localJSONObject2.get("type").toString().equals("1"))
{
if (!this.f)
{
this.f = true;
d = localJSONObject2;
}
}
else
{
e = e + localJSONObject2.get("package").toString() + "|";
localJSONObject1.put(str1, localJSONObject2);
}
}
}
}
catch (JSONException localJSONException)
{
localJSONException.printStackTrace();
}
i++;
}
}
Anybody can help me decode 3 text string a,b,c please?
Hello,
Try posting your question in the forum linked below.
http://forum.xda-developers.com/android/help
The experts there may be able to help. Good luck.
Hello,
I'm newbie so I don't know where to post right. Thank you for your advice!
Hi all,
I'm developing an application that captures the information of the LTE and 5G NR network information. I have created two different services (Kotlin services that are very similar to pool threads) which captures the information of the LTE and its neighbours in one service and the same for 5G NR in another service. The transformation to obtain the same information is very similar from LTE to 5G, and it is supposed to work. In the LTE service I obtain the information of the LTE serving cell information below (First quote) and the 5G NR service in the other quote. I would like to point out from the 5G service provides me the information of ONLY the serving cell, however, I need the information of all the cells. Does anyone have any clue?
Thanks for anyone who stops for reading this =)
package com.mobilenet.monitoring.services
import android.Manifest
import android.annotation.SuppressLint
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.ConnectivityManager
import android.os.Binder
import android.os.Handler
import android.os.IBinder
import android.telephony.*
import android.util.Log
import androidx.core.app.ActivityCompat
import com.mobilenet.monitoring.R
import com.mobilenet.monitoring.app.preferences
import org.json.JSONObject
import java.text.DateFormat
import java.util.*
import kotlin.collections.HashMap
class ServiceLte : Service() {
val TAG = "TESTING"
private var mBinder: IBinder = MyBinder()
private var mHandler = Handler()
/* Lte Parameters */
var mSignalStrength: SignalStrength? = null
var mListSignalStrength: List<CellSignalStrength>? = null
var mSignalStrengthLte: CellSignalStrengthLte? = null
var mManager: TelephonyManager? = null
/* LteConnection */
private var mLteData: JSONObject = JSONObject()
private var mLteNeighbourData: JSONObject = JSONObject()
var infos: MutableList<CellInfo>? = null
private lateinit var mContext:Context
private var jsonObject:JSONObject = JSONObject()
private var dataNeighbour = HashMap< String, String>()
private var lte:CellSignalStrengthLte? = null
private var identityLte:CellIdentityLte? = null
private var ci:Int = -1
private var MCC:String? = ""
private var MNC:String? = ""
private var PLMN:String? = ""
private var cellidHex: String = ""
private var eNBHex:String = ""
private var eNB: Int = -1
override fun onBind(intent: Intent): IBinder? {
return mBinder
}
@SuppressLint("MissingPermission")
override fun onCreate() {
super.onCreate()
Log.d(TAG, "onCreate")
mContext = this
/* LTE */
mManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
//mManager!!.listen( mListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS or PhoneStateListener.LISTEN_CELL_INFO)
update()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.d(TAG, "onStartCommand")
if(intent?.getStringExtra("action") == "Destroy"){
onDestroy()
}
val CHANNELID = "Foreground Service ID"
val channel = NotificationChannel(
CHANNELID,
CHANNELID,
NotificationManager.IMPORTANCE_LOW
)
getSystemService(NotificationManager::class.java).createNotificationChannel(channel)
val notification: Notification.Builder = Notification.Builder(this, CHANNELID)
.setContentText("Monitoring is running")
.setContentTitle("Monitoring enabled")
.setSmallIcon(R.drawable.ic_launcher_background)
startForeground(1001, notification.build())
return super.onStartCommand(intent, flags, startId)
}
fun getLteData(): JSONObject {
return mLteData
}
fun getNeighbourLteData(): JSONObject {
return mLteNeighbourData
}
// Listener for signal strength.
private val mListener: PhoneStateListener = object : PhoneStateListener() {
override fun onSignalStrengthsChanged(sStrength: SignalStrength) {
mSignalStrength = sStrength
Log.d(TAG,"SignalStrength cambia HOLAA")
if (ActivityCompat.checkSelfPermission(mContext,Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
infos = mManager!!.allCellInfo
}
}
override fun onCellInfoChanged(cellInfo: MutableList<CellInfo>) {
Log.d(TAG,"CellInfo cambia")
infos = cellInfo
}
}
private fun update() {
val runnable = object : Runnable {
@SuppressLint("MissingPermission", "NewApi")
override fun run() {
mLteData = JSONObject()
mLteNeighbourData = JSONObject()
infos = null
jsonObject = JSONObject()
mManager!!.requestCellInfoUpdate( mContext.mainExecutor,
object : TelephonyManager.CellInfoCallback() {
override fun onCellInfo(cellInfo: MutableList<CellInfo>) {
Log.d(TAG, "Requesting cell update")
getData(cellInfo)
}
})
mHandler.postDelayed(this, 500)//preferences.periodicity.toLong())
}
}
mHandler.postDelayed(runnable, 500)//preferences.periodicity.toLong())
}
@SuppressLint("NewApi")
private fun getData(cellInfo: MutableList<CellInfo>){
try {
mSignalStrengthLte = (cellInfo[0] as CellInfoLte).cellSignalStrength
//LTE connected
if (preferences.LteEnable) {
if (preferences.LteCQI) mLteData.put("LteCqi", "${mSignalStrengthLte!!.cqi}")
if (preferences.LteLevel) mLteData.put("LteLevel","${mSignalStrengthLte!!.level}")
if (preferences.LteRSRP) mLteData.put("LteRSRP", "${mSignalStrengthLte!!.rsrp}")
if (preferences.LteRSRQ) mLteData.put("LteRSRQ", "${mSignalStrengthLte!!.rsrq}")
if (preferences.LteRSSI) mLteData.put("LteRSSI", "${mSignalStrengthLte!!.rssi}")
if (preferences.LteRSSNR) mLteData.put("LteRSSNR","${mSignalStrengthLte!!.rssnr}")
if (preferences.LteTA) mLteData.put("LteTimingAdvance", "${mSignalStrengthLte!!.timingAdvance}")
if (preferences.LteDbm) mLteData.put("LteDbm", "${mSignalStrengthLte!!.dbm}")
if (preferences.LteAsuLevel) mLteData.put("LteAsuLevel", "${mSignalStrengthLte!!.asuLevel}")
}
}catch (ex: Exception) {
Log.i(TAG, ex.message)
}
//LTE neighbours
@SuppressLint("MissingPermission")
infos = mManager!!.allCellInfo
jsonObject = JSONObject()
dataNeighbour = HashMap< String, String>()
if (preferences.NeighbourLteEnable){
jsonObject.put("NumberOfSites", "${infos!!.size}")
}
for (i in infos!!.indices) {
try {
val info = infos!!
if (info is CellInfoLte) //if LTE connection
{
//mManager!!.getNetworkOperator()
lte = info.cellSignalStrength
identityLte = info.cellIdentity
ci = identityLte!!.ci
MCC = identityLte!!.mccString
MNC = identityLte!!.mncString
if(MNC == null || MCC == null) PLMN = "XXXX"
else if (MNC!!.length == 3) {
PLMN = "${MCC!![1]}${MCC!![0]}${MNC!![2]}${MCC!![2]}${MNC!![1]}${MNC!![0]}"
} else {
PLMN = "${MCC!![1]}${MCC!![0]}F${MCC!![2]}${MNC!![1]}${MNC!![0]}"
}
cellidHex = String.format("%x", ci)
eNBHex = cellidHex.substring(0, cellidHex.length - 2)
eNB = Integer.parseInt(eNBHex, 16)
//ECI = 256 * eNBId + Cellid
dataNeighbour["Registered"] = "${info!!.isRegistered()}"
if (preferences.NeighbourLteRsrp) dataNeighbour["RSRP"] = "${lte!!.rsrp}"
if (preferences.NeighbourLteRssi) dataNeighbour["RSSI"] = "${lte!!.rssi}" //Unavailable
if (preferences.NeighbourLteCqi) dataNeighbour["CQI"] = "${lte!!.cqi}" //Unavailable
if (preferences.NeighbourLteDbm) dataNeighbour["Dbm"] = "${lte!!.dbm}"
if (preferences.NeighbourLteLevel) dataNeighbour["LevelSignalStrength"] = "${lte!!.level}"
if (preferences.NeighbourLteRsrq) dataNeighbour["RSRQ"] = "${lte!!.rsrq}"
if (preferences.NeighbourLteRssnr) dataNeighbour["RSSNR"] = "${lte!!.rssnr}"
if (preferences.NeighbourLtePci) dataNeighbour["PCI"] = "${identityLte!!.pci}"
if (preferences.NeighbourLteCi) dataNeighbour["CI"] = "${ci}"
if (preferences.NeighbourLteMnc) dataNeighbour["MNC"] = "${MNC}"
if (preferences.NeighbourLteMcc) dataNeighbour["MCC"] = "${MCC}"
if (preferences.NeighbourLtePlmn) dataNeighbour["PLMN"] = "${PLMN}"
if (preferences.NeighbourLteEnb) dataNeighbour["eNB"] = "${eNB}"
if (preferences.NeighbourLteMobileNetworkOperator) dataNeighbour["MobileNetworkOperatorID"] = "${identityLte!!.mobileNetworkOperator}"
if (preferences.NeighbourLteMobileNetworkOperator) dataNeighbour["MobileNetworkOperatorName"] = "${identityLte!!.operatorAlphaLong}"
if (preferences.NeighbourLteTac) dataNeighbour["TAC"] = "${identityLte!!.tac}"
if (preferences.NeighbourLteBandwith) dataNeighbour["Bandwidth"] = "${identityLte!!.bandwidth}"
if (preferences.NeighbourLteEarfcn){
dataNeighbour["EarFCN"] = "${identityLte!!.earfcn}"
dataNeighbour["Band"] = "${getBand(identityLte!!.earfcn)}"
}
}else{
if (info is CellInfoGsm){
var gsm = info.cellSignalStrength
var identityGsm = info.cellIdentity
Log.d(TAG,gsm.toString())
Log.d(TAG,"identityGsm.cid: ${identityGsm.cid}")
Log.d(TAG,identityGsm.toString())
}else if (info is CellInfoCdma){
var gsm = info.cellSignalStrength
var identityGsm = info.cellIdentity
Log.d(TAG,gsm.toString())
Log.d(TAG,"identityCdma.networkId: ${identityGsm.networkId}, identityCdma.systemId: ${identityGsm.systemId}")
Log.d(TAG,identityGsm.toString())
}else if (info is CellInfoWcdma){
var gsm = info.cellSignalStrength
var identityGsm = info.cellIdentity
Log.d(TAG,gsm.toString())
Log.d(TAG,"identityWcdma.cid: ${identityGsm.cid}")
Log.d(TAG,identityGsm.toString())
}else if (info is CellInfoTdscdma){
var gsm = info.cellSignalStrength
var identityGsm = info.cellIdentity
Log.d(TAG,gsm.toString())
Log.d(TAG,"identityTdscdma.cid: ${identityGsm.cid}")
Log.d(TAG,identityGsm.toString())
}
}
} catch (ex: Exception) {
Log.i("TESTING: ", ex.message)
}
jsonObject.putOpt("Site$i", JSONObject(dataNeighbour as Map<*, *>))
}
mLteNeighbourData = jsonObject
}
override fun onTaskRemoved(rootIntent: Intent?) {
super.onTaskRemoved(rootIntent)
stopSelf() //a hard stop for the service (si no queremos que siga en funcionamiento al cerrar)
}
override fun onDestroy() {
Log.d(TAG, "onDestroy")
super.onDestroy()
}
inner class MyBinder : Binder() {
fun getService(): ServiceLte? {
return [email protected]
}
}
private fun getBand(arfcn:Int):Int{
when {
arfcn<600 -> return 1
arfcn<1200 -> return 2
arfcn<1950 -> return 3
arfcn<2400 -> return 4
arfcn<2650 -> return 5
arfcn<2750 -> return 6
arfcn<3450 -> return 7
arfcn<3800 -> return 8
arfcn<4150 -> return 9
arfcn<4750 -> return 10
arfcn<5010 -> return 11
arfcn<5180 -> return 12
arfcn<5280 -> return 13
arfcn<5380 -> return 14
arfcn<5730 -> return -1
arfcn<5850 -> return 17
arfcn<6000 -> return 18
arfcn<6150 -> return 19
arfcn<6450 -> return 20
arfcn<6600 -> return 21
arfcn<7500 -> return 22
arfcn<7700 -> return 23
arfcn<8040 -> return 24
arfcn<8690 -> return 25
arfcn<9040 -> return 26
arfcn<9210 -> return 27
arfcn<9660 -> return 28
arfcn<9770 -> return 29
arfcn<9870 -> return 30
arfcn<9920 -> return 31
else -> return 9999
}
}
}
Click to expand...
Click to collapse
Here I also post the 5G NR service to obtain the information:
package com.mobilenet.monitoring.services
import android.Manifest
import android.annotation.SuppressLint
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Binder
import android.os.Build
import android.os.Handler
import android.os.IBinder
import android.telephony.*
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.core.app.ActivityCompat
import com.mobilenet.monitoring.R
import com.mobilenet.monitoring.app.preferences
import org.json.JSONObject
class ServiceNr : Service() {
val TAG = "TESTING"
private var mBinder: IBinder = MyBinder()
private var mHandler = Handler()
/* Lte Parameters */
var mSignalStrength: SignalStrength? = null
var mListSignalStrength: List<CellSignalStrength>? = null
var mSignalStrengthNr: CellSignalStrengthNr? = null
var mManager: TelephonyManager? = null
/* LteConnection */
private var mNrData: JSONObject = JSONObject()
private var mNrNeighbourData: JSONObject = JSONObject()
var infos: MutableList<CellInfo>? = null
private lateinit var mContext:Context
private var jsonObject:JSONObject = JSONObject()
private var dataNeighbour = HashMap<String, String>()
private var nr:CellSignalStrengthNr? = null
private var identityNr:CellIdentityNr? = null
private var ci:Int = -1
private var MCC:String? = ""
private var MNC:String? = ""
private var PLMN:String? = ""
private var cellidHex: String = ""
private var eNBHex:String = ""
private var eNB: Int = -1
override fun onBind(intent: Intent): IBinder? {
return mBinder
}
@RequiresApi(Build.VERSION_CODES.Q)
@SuppressLint("MissingPermission")
override fun onCreate() {
super.onCreate()
Log.d(TAG, "onCreate")
mContext = this
/* NR */
mManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
// Register the listener with the telephony manager
// mManager!!.listen( mListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS or PhoneStateListener.LISTEN_CELL_LOCATION)
/*
SSB es el beam
*/
update()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if(intent?.getStringExtra("action") == "Destroy"){
onDestroy()
}
val CHANNELID = "Foreground Service ID"
val channel = NotificationChannel(
CHANNELID,
CHANNELID,
NotificationManager.IMPORTANCE_LOW
)
getSystemService(NotificationManager::class.java).createNotificationChannel(channel)
val notification: Notification.Builder = Notification.Builder(this, CHANNELID)
.setContentText("Monitoring is running")
.setContentTitle("Monitoring enabled")
.setSmallIcon(R.drawable.ic_launcher_background)
startForeground(1001, notification.build())
return super.onStartCommand(intent, flags, startId)
}
fun getNrData(): JSONObject {
return mNrData
}
fun getNeighbourNrData(): JSONObject {
return mNrNeighbourData
}
fun destroy(){
stopSelf();
}
// Listener for signal strength.
private val mListener: PhoneStateListener = object : PhoneStateListener() {
override fun onSignalStrengthsChanged(sStrength: SignalStrength) {
mSignalStrength = sStrength
if (ActivityCompat.checkSelfPermission(
mContext,
Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED) {
infos = mManager!!.allCellInfo
}
}
override fun onCellInfoChanged(cellInfo: MutableList<CellInfo>) {
infos = cellInfo
}
}
private fun update() {
val runnable = object : Runnable {
@SuppressLint("MissingPermission", "NewApi")
override fun run() {
mManager!!.requestCellInfoUpdate( mContext.mainExecutor,
object : TelephonyManager.CellInfoCallback() {
override fun onCellInfo(cellInfo: MutableList<CellInfo>) {
mNrData = JSONObject()
mNrNeighbourData = JSONObject()
infos = null
jsonObject = JSONObject()
getData(cellInfo)
}
})
mHandler.postDelayed(this, 500)//preferences.periodicity.toLong())
}
}
mHandler.postDelayed(runnable, 500)//preferences.periodicity.toLong())
}
@SuppressLint("MissingPermission")
@RequiresApi(Build.VERSION_CODES.Q)
private fun getData(cellInfo: MutableList<CellInfo>){
try {
// Log.d(TAG, "$cellInfo") //Pondría esto para ver qué obtengo a ver si hay aquí algo mal
mSignalStrengthNr = (cellInfo[0] as CellInfoNr).cellSignalStrength as CellSignalStrengthNr
//Nr connected
if (preferences.NeighbourNrEnable) {
if (preferences.NeighbourNrRsrp) mNrData.put(
"NrRsrp",
"${mSignalStrengthNr!!.ssRsrp}"
)
if (preferences.NeighbourNrRsrq) mNrData.put(
"NrRsrq",
"${mSignalStrengthNr!!.ssRsrq}"
)
if (preferences.NeighbourNrSinr) mNrData.put(
"NrSinr",
"${mSignalStrengthNr!!.ssSinr}"
)
if (preferences.NeighbourNrAsulevel) mNrData.put(
"NrAsulevel",
"${mSignalStrengthNr!!.asuLevel}"
)
if (preferences.NeighbourNrDbm) mNrData.put(
"NrDbm",
"${mSignalStrengthNr!!.dbm}"
)
if (preferences.NeighbourNrLevel) mNrData.put(
"NrLevel",
"${mSignalStrengthNr!!.level}"
)
}
}catch (ex: Exception) {
Log.i(TAG, ex.message)
}
infos = mManager!!.allCellInfo
// Log.d(TAG, "$infos") //Pondría esto para ver qué obtengo a ver si hay aquí algo mal
jsonObject = JSONObject()
dataNeighbour = HashMap<String, String>()
if (preferences.NeighbourNrEnable){
jsonObject.put("NumberOfSites", "${infos!!.size}")
}
for (i in infos!!.indices) {
try {
val cell = infos!!
nr = (cell as CellInfoNr).cellSignalStrength as CellSignalStrengthNr
identityNr = (cell as CellInfoNr).cellIdentity as CellIdentityNr
// nr = (cellInfo[0] as CellInfoNr).cellSignalStrength as CellSignalStrengthNr
// identityNr = (cellInfo[0] as CellInfoNr).cellIdentity as CellIdentityNr
// Log.d(TAG,"${infos!!.indices}")
// Log.d(TAG,nr.toString())
// Log.d(TAG,identityNr.toString())
ci = identityNr!!.pci
MCC = identityNr!!.mccString
MNC = identityNr!!.mncString
if(MNC == null || MCC == null)
{
PLMN = "XXXX"
}
else if (MNC!!.length == 3) {
PLMN = "${MCC!![1]}${MCC!![0]}${MNC!![2]}${MCC!![2]}${MNC!![1]}${MNC!![0]}"
} else {
PLMN = "${MCC!![1]}${MCC!![0]}F${MCC!![2]}${MNC!![1]}${MNC!![0]}"
}
if (preferences.NeighbourNrRsrp){
var rsrp = nr!!.ssRsrp
dataNeighbour["RSRP"] = "${rsrp}"
}
if (preferences.NeighbourNrRsrq){
var rsrq = nr!!.ssRsrq
dataNeighbour["RSRP"] = "${rsrq}"
}
if (preferences.NeighbourNrSinr){
var sinr = nr!!.ssSinr
dataNeighbour["Sinr"] = "${sinr}"
}
if (preferences.NeighbourNrAsulevel){
var asulevel = nr!!.asuLevel
dataNeighbour["Asulevel"] = "${asulevel}"
}
if (preferences.NeighbourNrDbm){
var dbm = nr!!.dbm
dataNeighbour["Dbm"] = "${dbm}"
}
if (preferences.NeighbourNrLevel){
var level = nr!!.level
dataNeighbour["Level"] = "${level}"
}
dataNeighbour["PCI"] = "${identityNr!!.pci}"
dataNeighbour["CI"] = "${ci}"
dataNeighbour["MNC"] = "${MNC}"
dataNeighbour["MCC"] = "${MCC}"
dataNeighbour["PLMN"] = "${PLMN}"
dataNeighbour["MobileNetworkOperatorName"] = "${identityNr!!.operatorAlphaLong}"
dataNeighbour["TAC"] = "${identityNr!!.tac}"
dataNeighbour["EarFCN"] = "${identityNr!!.nrarfcn}"
} catch (ex: Exception) {
Log.i("TESTING: ", ex.message)
}
jsonObject.putOpt("Site$i", JSONObject(dataNeighbour as Map<*, *>))
}
mNrNeighbourData = jsonObject
}
override fun onTaskRemoved(rootIntent: Intent?) {
super.onTaskRemoved(rootIntent)
stopSelf() //a hard stop for the service (si no queremos que siga en funcionamiento al cerrar)
}
override fun onDestroy() {
Log.d(TAG, "onDestroy")
super.onDestroy()
}
inner class MyBinder : Binder() {
fun getService(): ServiceNr? {
return [email protected]ServiceNr
}
}
private fun getBand(arfcn: Int):Int{
when {
arfcn<600 -> return 1
arfcn<1200 -> return 2
arfcn<1950 -> return 3
arfcn<2400 -> return 4
arfcn<2650 -> return 5
arfcn<2750 -> return 6
arfcn<3450 -> return 7
arfcn<3800 -> return 8
arfcn<4150 -> return 9
arfcn<4750 -> return 10
arfcn<5010 -> return 11
arfcn<5180 -> return 12
arfcn<5280 -> return 13
arfcn<5380 -> return 14
arfcn<5730 -> return -1
arfcn<5850 -> return 17
arfcn<6000 -> return 18
arfcn<6150 -> return 19
arfcn<6450 -> return 20
arfcn<6600 -> return 21
arfcn<7500 -> return 22
arfcn<7700 -> return 23
arfcn<8040 -> return 24
arfcn<8690 -> return 25
arfcn<9040 -> return 26
arfcn<9210 -> return 27
arfcn<9660 -> return 28
arfcn<9770 -> return 29
arfcn<9870 -> return 30
arfcn<9920 -> return 31
else -> return 9999
} //Ya paso de seguir haciendo la tabla https://5g-tools.com/4g-lte-earfcn-calculator/
}
}
Click to expand...
Click to collapse