Run Powershell Command from Oracle Procedure - android

I need to print pdf documents to my network printer from my android studio application. I want to print the pdf as is with all images and formatting, however, the solutions I have found only allow for the extraction and printing of text from the pdf.
I have also seen solutions mentioning tools like Ghostscript etc which are supposed to convert the pdf to a postscript file, but these tools do not work with Android Studio or at-least I haven't figured out how to integrate them into my application. I cannot pay for tools like jPDFPrint which does exactly what I need.
I started thinking about a work around and came upon the idea of sending my pdf as a blob to my oracle database and invoke a power shell command from a procedure to print it to a specific printer.
I've created and tested the below command to print to my network printer from my PC which works great.
Start-Process -FilePath “c:\test.pdf” –Verb PrintTo '\\PrintServer\PrinterName' -PassThru | %{sleep 10;$_} | kill
Now I need help with the oracle part. Is it possible to invoke or run a powershell command from within oracle 12c and pass it the pdf blob as well as the printer name?

To extract the BLOB to a PDF.
Create you system folder, eg c:\printthis.
Then create the Oracle directory object mapped to this folder:
CREATE OR REPLACE DIRECTORY print_dir AS 'C:\print_this';
GRANT READ WRITE ON DIRECTORY print_dir TO PUBLIC;
This procedure to extract the BLOB to a file.
CREATE OR REPLACE PROCEDURE extract_pdf ( p_id IN VARCHAR2 ) AS
CURSOR c1 IS
SELECT doc_blob, doc_name
FROM doc_table
WHERE doc_id = p_id;
r1 c1%ROWTYPE;
v_size NUMBER( 5,0) := 32000;
v_len NUMBER(38,0);
v_buffer RAW(32000);
v_file UTL_FILE.FILE_TYPE;
BEGIN
OPEN c1;
FETCH c1 INTO r1;
v_file := UTL_FILE.FOPEN('PRINT_DIR', r1.doc_name, 'wb', 32760 );
v_start := 1;
v_len := DBMS_LOB.GETLENGTH( r.bbl_fic );
WHILE v_start <= v_len LOOP
DBMS_LOB.READ(
r.bbl_fic,
LEAST( v_len - v_start + 1, v_size ),
v_start,
v_buffer
);
UTL_FILE.PUT_RAW( v_file, v_buffer );
UTL_FILE.FFLUSH( v_file );
v_start := v_start + v_size;
END LOOP;
UTL_FILE.FCLOSE( v_file );
-- Write the CMD file
v_file := UTL_FILE.FOPEN('PRINT_DIR', r1.doc_name || '.bat', 'w' );
UTL_FILE.PUT_LINE( 'Start-Process -FilePath “c:\print_this\' || r1.doc_name || '” –Verb PrintTo '\\PrintServer\PrinterName' -PassThru | %{sleep 10;$_} | kill' );
UTL_FILE.CLOSE(v_file);
END;
/
A Windows At job that runs, polls the c:\print_this folder for files and runs the .bat command, then deletes it.
#ECHO OFF
setlocal enabledelayedexpansion
for %%f in (c:\print_this\*.bat) do (
echo "Name: %%f"
powershell %%f
del %%f
)
The question remains of how to stitch this together. Your Android app calls your procedure to store the PDF as a BLOB. It must also be able to call the procedure suggested above to extract the saved BLOB to a database server file, so this procedure to extract the ODF AND create the print bat script is called after the save BLOB.
The Task Scheduler job polls the directory for the bat scripts, runs them deletes them.
You cannot directly issue a command to the server host from within Oracle. You can use DBMS_SCHEDULER. In the above example, the job would take the doc_id as a parameter, and execute this via DBMS_SCHEDULER.RUN_JOB. I cant remember how to do this precisely, but I hope my other suggestion with the Task Scheduler in Windows is fruitful for you.

You can use the PL/SQL package DBMS_SCHEDULER procedure create_program, using the program_type=>'EXECUTABLE' to do what you want. Then you would have your process that sends the data to oracle create a job to invoke that program. The DBMS_SCHEDULER package is pretty complex so you'll probably need to hunt around for tutorials/tips; you may want to search https://asktom.oracle.com for starters.

Related

Talking clock on old laptop or an Android app

I want to program a "talking clock" for my blind father and I have an very old laptop, 768 RAM. I have tried many different things, from making an app on android with kivy, without any success, because on my laptop (a different one) seems to work like a charm but when I'm "buildoze" it just doesn't play any mp3. I've tried some answers provided on SO with no success. Now I thought to try to install different things, like Python libraries for 2.79 and even Java on my old laptop, but seems that because Linux Mint 2.0 it's no longer supported can't install anything...
Does anyone have any suggestion if I can use that old laptop for such a thing or I can make an app for Android that plays mp3's?
I quite a noobie 😛
Thanks
Quick, dirty, and simple: install espeak and run something like the following in a cron job as often as you like:
dt=$(date +'%A, %B %d, %Y. The time is %l %M %p.'); espeak "Today is $dt"
EDIT: On reflection, It might be better to write a shell script and call that from cron. Assuming your father's only challenge is blindness, he probably doesn't need to be reminded of the date every, say, fifteen minutes. A script could speak the date every eight hours, perhaps, and the time as often as is useful.
EDIT AGAIN: Here's a script I threw together for fun. Give it a try.
#!/bin/bash
# If espeak isn't installed, complain and quit
command -v espeak > /dev/null 2>&1 ||\
{ echo -e "$0 requires espeak to be installed. Exiting..." ; exit 1; }
# ** Set variables
date_now=$(date +'%A, %B %d, %Y')
military_time=$(date +'%R') # 24-hour time
minute=$(date +'%M')
# We don't need espeak to say "zero zero" for the minutes
if [ $minute = "00" ]; then
time_now=$(date +'%l %p')
else
time_now=$(date +'%l %M %p')
fi
# Speak the date only if it's 9am or 5pm
[[ $military_time = "09:00" || $military_time = "17:00" ]] && espeak "Today is $date_now."
espeak "The time is $time_now."
Here's a speaking-clock in JS - just load it into a WebView or something - but you don't even need to package an app: just put it in a HTML page with a PWA manifest and save that as a home-screen icon so it will work while offline.
Click "Run code snippet" and then the button.
It will work in any modern web-browser available for Android and Linux desktops (except Opera and the stock (non-Chrome) Android Browser - it will also work in any modern Linux desktop environment - or any desktop OS, really.
I hope the code is self-explanatory.
It uses the Web Speech Synthesis API which is widely supported (except by the not-Google-Chrome Android Browser for some reason).
Note that it is not possible to make it play automatically or on-load (so need to click the button first to make speech synthesis work), as most browsers (including Chrome) block scripts from auto-playing sounds without user-interaction; the same applies to <video>, <audio>, etc.
Eta voila:
function sayTime() {
if( window.speechSynthesis.speaking ) return;
const now = new Date();
var tts = new SpeechSynthesisUtterance();
tts.text = "The time is now " + now.toLocaleTimeString();
window.speechSynthesis.speak( tts );
}
let timerId = null;
function toggleSpeakingClock() {
if( timerId ) {
window.speechSynthesis.cancel();
window.clearInterval( timerId );
timerId = null;
btn.textContent = "Click me to start";
}
else {
timerId = window.setInterval( sayTime, 1000 );
const btn = document.getElementById('btn');
btn.textContent = "Click me to stop";
}
}
document.addEventListener( 'DOMContentLoaded', function() {
const btn = document.getElementById('btn');
btn.disabled = !( typeof window.speechSynthesis === 'object' ) && ( window.speechSynthesis !== null );
if( btn.disabled ) btn.textContent = "Your browser doesn't support TTS";
} );
<button id="btn" onclick="toggleSpeakingClock()" disabled>Please wait...</button>

What is the purpose of using double underscore ( __ ) before the start and after the end of an file name in c?

I'm studying the android kernel as a beginner. I can read the messages thrown from the macro ERROR() inside the function main() at system/core/init/init.c using dmesg command through adb. I observed that after calling the function open_devnull_stdio() inside main(), dmesg no longer displays the messages thrown by ERROR().
To find the reason, I started digging into the declaration of open_devnull_stdio() inside system/core/init/util.c and I found this line I can't understand
static const char *name = "/dev/__null__";
Actually there was no file named __null__ inside /dev/ in the device, but there was a file named null and I was able to grab it using adb pull and it was a 0 byte (empty) file.
So why is a file name wrapped with double underscore (__) ?
Here is the link for the util.c
There is no special purpose of using double underscore before the start, after the end or both in C. From the point of view of C the file name is just a string, the operating system is free to interpret in whatever way it chooses. From the point of view of Linux, the same applies. Underscores in file names are just characters. They are not treated differently from the letters b and t.
If I guessed right and I'm reading the same file as you (it might be a good idea to link to the source code you're reading) then it should be pretty obvious what the code does on the lines after the one you mentioned. The next lines are:
if (mknod(name, S_IFCHR | 0600, (1 << 8) | 3) == 0) {
fd = open(name, O_RDWR);
unlink(name);
Which creates the null device which is then opened and immediately deleted again.
I suspect this is done so that programs can run without access to the root filesystem and still be able to open the equivalent of /dev/null.
I don't know the answer but I have an idea:
The following page shows an "strace" output where /dev/__null__ is used:
https://gist.github.com/tetsu-koba/1522515
Under Linux device files have a 33-bit (?) number which identifies the device. (At least under old Linux versions) you could delete some file in /dev and you could restore it or even create it in another directory (!) when you know the 33-bit number! (So you can delete the device /dev/sda2 and create the device (not file!) /home/myuser/sda2 instead.)
The trace in the link above shows the following three lines:
mknod("/dev/__null__", S_IFCHR|0600, makedev(1, 3)) = 0
open("/dev/__null__", O_RDWR|O_LARGEFILE) = 3
unlink("/dev/__null__") = 0
These lines will create the device file /dev/__null__ (with the 33-bit number identifying /dev/null). Then it opens that file and then it removes the file again.
Maybe this is done because the tool shall be able to run both on Linux installations where the device file "/dev/null" is present (in this case the file should not be overwritten) and on installations where that file is missing (in this case a replacement file must be created using the known 33-bit number).
As other people have pointed out this just tells it's the "null device", not a regular file called "null". null is supposed to act like an information sink, not like a normal file where you dump your data to. Hope this helps.

Storing android adb shell screencap as variable

Making an app at the moment for my personal use (rooted) and it requires getting certain pixels colors from the screen. I was trying to accomplish this through the Runtime.
Process p = Runtime.getRuntime().exec("screencap");
p.waitFor();
InputStream is = p.getInputStream()
BitmapFactory.decodeStream(is);
and I get factory returned null.
but if I dump the process to my sd card through adb -d shell screencap /sdcard/ss.dump and access it from my app
BitmapFactory.decodeFile("/sdcard/ss.dump");
all goes well.
So it there anyway to dump the stream straight into BitmapFactory within my app?
Thanks SO and please excuse the generally laziness/shortcuts of the example code.
This might help if not too far off your intended path. (I think you are using node / javascript). I spawned the ADB.EXE command producing a stream (and being 'jailed' on Windows the program must transform the stream to account for linefeed ending differences. So with that, I have working the following:
exports.capture = function(filename) {
// you'll need to map your requirement (decodeStream) instead
// of streaming to a file
var strm = fs.createWriteStream(path);
var cv = new Convert();
cv.pipe(strm);
var capture = spawn(cmd, args);
capture.stdout.on('data', function(data) {
cv.write(data);
});
capture.stdout.on('exit', function(data) {
cv.end();
});
}
To explain the process, spawn is running the ADB command, on windows, CR-LF are inserted (being a PNG stream), and stream is chunked / piped through a fs-transformation. Others on the web have described the process as adb.exe shell screencap -p | sed 's/\r$//' > output.file. And it does work. To be clear the conversion is CR-CR-LF => LF for us window jailed birds. And if you don't want to implement a SED and not use javascript regular expressions converting binary->strings->binary, you may follow my path. There is probably a simpler way, I just don't know what it is...
So, Convert() is an object with methods that converts the byte stream on the fly.
See the codewind blog link is: http://codewinds.com/blog/2013-08-20-nodejs-transform-streams.html to build your convert.
When using screencap from inside an app you must use su, i.e. root. When you do this via adb it runs under a different user id, which has more permissions than a normal Android app.
There are several examples how to use screencap, e.g. here.

Converting .db to .vcf

I accidentally deleted my contacts and i don't have a backup for that now i got the contacts2.db and i am trying to covert the .db to .vcf. Now i am using Ruby to convert the file and here is what i did
gem install sqlite3
gem install vpim
path to contacts2-to-vcard.rb/contacts2-to-vcard.rb > contacts.vcf
i always says 'Access Denied.' And i set the folder to full control but whenever i run that command it change to read only, by the way i am using windows 8. Any help? Or is there a alternate why to convert .db to .vcf? TIA
Yank it out of the DB (this is all in Ruby):
require 'sqlite3'
path_to_contactsdb_file = "/SAMPLE/PATH/TO/contacts2.db"
db = SQLite3::Database.new path_to_contactsdb_file
raw_contacts = db.execute("select _id,display_name from raw_contacts")
contacts = {}
raw_contacts.each do |x|
contacts[x[1]] = {}
contacts[x[1]]['rcid'] = x[0]
contacts[x[1]]['nums'] = db.execute("select normalized_number from phone_lookup where raw_contact_id=" + x[0].to_s)
end
Pull it to CSV:
output_filepath = "/SAMPLE/EXAMPLE/FILEPATH"
csv = ""
contacts.each do |k,v|
csv += '"' + k + '",'
v['nums'].each do |num|
csv += '"' + num[0] + '",'
end
csv += "\n"
end
File.open(output_filepath,"w") {|file| file.write(csv) }
Then you can use a CSV import app, do it through Google contacts import through CSV, etc.. You can send me a fruit basket.
If it MUST be in a VCF format, then just change the output syntax of the CSV. Look up a sample VCF file, I couldn't be bothered.
I've been trying to use Dustin van Schouwen's code to do this task. I wanted to thank him for it, first of all, and then mention a few details I needed to add/change to make it work for me:
This line:
db = SQLite3::Database.new path_to_contactsdb_file
I changed to:
db = SQLite3::Database.new ("contacts2.db")
As when using the previous one, even though it doesn't give an error, it doesn't seem to actually connect to the database (I think it creates an empty one).
The other change I needed to do was at this other line:
csv += '"' + k + '",
If "k" is nil, the code will fail, so I introduced an if (ternary syntax) to solve it, and it worked fine:
csv += '"' + (k == nil ? "" : k) + '",'
A bit late for OP sorry. I can't give tips on ruby anyway.
But I stumbled here when searching a solution for my own needs.
I finally came up with a python solution:
https://gitlab.com/Arnaudv6/contacts2.db-2-vcard
based on previous works documented on above page.
Please refer to "todo" section at beginning of the script
for details on what is not implemented to date.

How to make org-mobile work in android?

I want to view and edit my org-file in my Android phone, I synchronize files with Ubuntu one. I added such code in .emacs
(setq org-mobile-directory "~/Documents")
and I also set Org Mobile Directory as ~/Documents in Org Mobile Group. But I can't push any org-file to my phone. When I open an org-file in Emacs and C-c-x RET p, Emacs shows this message.
Please set 'org-direcory' to the directory where your org files live
I don't know why after I did such setting above Emacs still gave me this message.
All I can do in my phone is simply capture a new note, I input something and they can be synchronized with my PC under the ~/Ubuntu One/mobileorg.org. But I can't read what I load into my phone.
I read the web:synchronizing, I found I can't find those three files in my dirctory: checksum.dat, index.org and agendas.org.
What do I need to view org-files in my phone, and push org-files into my phone?
Where do you store your .org files, which you want to export to org-mobile? For example, i store mine in ~/labor and export file ~/labor/tasks.org, and also use OwnCloud WebDAV to synchronize with MobileOrg, so i have set:
(setq org-directory "~/labor")
(setq org-mobile-directory "~/dl/owncloud/mobileorg")
(setq org-agenda-files '("~/labor/tasks.org"))
(setq org-mobile-inbox-for-pull "~/labor/from-mobile.org")
As Pushing to MobileOrg says, pushing stages only the files listed in org-agenda-files or org-mobile-files and puts them in org-mobile-directory retaining the same structure, as it where in org-directory. As Pulling from MobileOrg says, org-mobile-inbox-for-pull is a file in org-directory, in which captured notes are pulled from the phone, which you will need to manually add wherever you want.
To setup:
Put a list of .org files, that you want to have on your phone, in org-agenda-files or org-mobile-files variables;
Set org-directory and org-mobile-directory - you've done that;
Setup MobileOrg on the phone with Ubuntu One directory;
Set org-mobile-inbox-for-pull to some file in org-directory
Your usual workflow will look like:
Execute org-mobile-push (C-c C-x RET p) in Emacs;
Synchronize the phone;
Do something in MobileOrg;
Synchronize the phone;
Execute org-mobile-pull (C-c C-x RET g) in Emacs;

Categories

Resources