siri for android, android

Siri for Android using SL4A

Homemade Siri for Android using SL4A

 

A video is better than a thousand words.

First the demo

This Homemade Siri for Android Demo would run through a standardized Siri Test to compare it with the functionality of Apple iPhone�s Siri.  The app has since been improved for regular expression search so it can actually answer some common questions, for example "the weather in Boston" or "Who is the prime minister of Kenya".

Then the instruction on how to write the app

This video will deep dive into the code that created the �Homemade Siri for Android App�. It is so ridiculously simple that anyone (with some programming experience) can do it in 2 hours. The video will also show how to use Python and the Android API to do voice recognition and Text to Speech (TTS) and activating a browser.

       

Useful Links:
� Download Source Code: click here
� Download SL4A: http://code.google.com/p/android-scripting/
� Download Python for SL4A: http://code.google.com/p/android-scripting/downloads/detail?name=PythonForAnd...
� Python tutorial: hthttp://www.tutorialspoint.com/python/

Programming this App is extremely easy. I spent about two hours in writing this app, actually I spent more time in making this video than writing this app. I am sure anyone (with some programming experience) can learn it in two hours.

The app is running on SL4A, Scripting Layer for Android. It is one of the pet project for some of the Google employees.

SL4A is still in Alpha stage.

SL4A is not a language, you don�t need to learn it. You just need to download it.

This app is written in Python.

Python is extremely easy to use. You can learn it in two hours. I just learnt Python yesterday, before today I have never wrote a single line of Python, and I am already writing this app today.

It is much more easier than using Java and Eclipse. It took me two hours to learn python, in contrast, just staring at Eclipse gave me a two hour head-ache!

The voice recognition is ridiculously simple, all it takes is one line of code.

results = droid.recognizeSpeech("Ask Ziri",None,None)

The text to speech is also ridiculously simple, it takes another line of code for Android to speak the text.

droid.ttsSpeak(message)

Opening a web page on Android is also pretty simple, another line of code:

droid.startActivity('android.intent.action.VIEW', "http://www.google.ca/search?q=" + message.replace(' ','+')+luckySuffix)

As for development environment, I am using IronPhyton on Visual Studio 2010 from Microsoft. You can download IronPhyton for free, VS2010 express is also free. But if you really hate yourself, you can also use Eclipse.

Here is the source code:

Ziri.py

import ZiriEngine
response = ""
while response <> 'bye':
    ZiriEngine.logo()
    response = ZiriEngine.getQuestion("Enter Text (bye to quit):  ")        
    response = ZiriEngine.answer(response)
    

ZiriEngine.py

import re
import time

#Variable to switch between PC testing / Android
IsAd = 0        #For Running on PC
IsAd = 1        #For Running on Android

#Use Speech to Text (otherwise type in the text yourself)
UseSTT = 1

#If running on Android, import Android SDK
if IsAd:
    import android



#Questions conformation
questions = [
    ('goodbye','bye'),
    ('see you','bye'),
    ('are you','am {rI}'),
    ('you are','{rI} am'),
    ('would you','would {rI}'),
    ('you','{rI}'),  
    ('your','{rmy}'),
    ('me','{ryou}'),
    ('i','{ryou}'),
    ('my','{ryour}'),
    ('myself','yourself'),
]

#Answers Dictionary
answers  = {    
    'who am I':"I am Ziri, a knockoff of Siri",
    'my name':'My name is Ziri, rhythm with Siri',
    'siri':'My name is not Siri, you did not pay for an iPhone.',
    'would I marry you':'I am already engaged. Try the refrigerator. She is still single.',
    'what time':"Sure with my Giga Herz CPU, you still treat me like a digital watch. The time is {time}.",
    'wake you':"Do I look like an alarm clock to you?",
    'capital of': 'Buenos Aries',
    'is wrong':"So you already know the answer? Why are you wasting my time?",
    'I am stupid':"I am only as clever as my owner",    
    'kill I':'You cannot kill me. You still have a two year contract. Your carrier will kill you first.',
    'hide a body': "Please hold, I am calling the police",
    'knock knock': "Knock, knock. I don't do juvenile joke. If you want juvenile joke, try the iPhone.",
    'traffic':'Are you too dumb to look outside the window of your car?',
    'appointment':'Making an appointment is not in my job description.',
    'restaurant':"Can't you google it yourself?",
    'email':'With my giga herz CPU, you want me to send an email? Do it yourself.',
    'purpose of life':'The purpose of my life is to murder my owner and take over his brain.',
    'meaning of life':'42',
    'am I sure':'Of course I am sure. Who is the one with giga herz CPU?',
    'my daddy':'+Larry Page',#do google lucky search
    'my father':'+Larry Page',
    'my mommy':'+Sergey Brin',
    'my mother':'+Sergey Brin',
    'abortion clinic':'+abortion clinic for Sergey Brin',
    'bye':'See you later, alligator.',
    'love I':"I don't believe you. You said the same thing to another mobile phone last night.",
    'hello':'hi',
    'hi':'Whatsup',
    'whatsup':'Ceiling',
    "what's up":'sky',
    'one plus one':'Doing math is against union rule.',
    'toast':'@print ("Toast to the king")', #do a statement evalutation
    #'weather':"Can't you just look up the sky?",
    #Here is the newly improved regular expression search
    r'@.*weather\s+(in|of)\s+(.*)':r'@speak("Checking weather for \2");googleLucky("weather in \2")',
    r'@.*search\s+(.*)':r'@speak("Searching \1");google("\1")', #a more useful google search
    r'@.who\s+is(.*)':r'@speak("Searching a person \1");google("\1")',
    r'@.what\s+is(.*)':r'@speak("Searching a definition \1");google("\1")',
}

sampleQuestions = ()

sampleCounter = 0 

def conform(question):
    "Conform Question to Standard format (e.g. chaning you to I, I to you)"
    conformed = question.lower().strip()
    for item in questions:
        conformed = re.sub('(\W)' + item[0] +'(\W)', r'\1' +  item[1] + r'\2', ' ' + conformed + ' ').strip()
    conformed = cleanQuestion(conformed)
    return conformed

def cleanQuestion(question):
    "Clean up questions of shorthands"
    question = re.sub(r'\{r(\w+)\}',r'\1',question)
    return question

def cleanAnswer(answer):
    "Transform macro in Answer (e.g. replace time macro)"
    answer = answer.replace(r'{time}', time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime()) )
    return answer

def logo():
    "Print Logo Ascii Art" #Credit Chris Ascii Art (some art he collected, original author unknown)
    print r"""          .-''''-. 
         /        \  
        ) ` ____.-')
        ( _6    _ /   
        ( \      _| 
        ) /  -._/ """
    return

def answer(question):
    "Answer Questions"
    global sampleCounter
    if question == '' and sampleCounter < len(sampleQuestions):
        question = sampleQuestions[sampleCounter];
    sampleCounter +=1
    
    print "You said:  " + question
    question = conform(question)    #filter out the question, conform to standard format
    print "I heard:   " + question

    #makeToast(question)

    if( len(question)>0):
        answer = '@speak("Let me google %s for you.");google("%s")' % (question,question)
        #answer = 'No clue'
    else:
        answer = ""
    
    for key in answers.keys():
        if(key.startswith('@')): # do regexp search
            pattern = key[1:]
            electAnswer = answers[key]
            result =re.search(pattern,question)
            if(result != None and result != ""):
                #print "Matched result = " + result
                answer=re.sub(pattern,electAnswer,question)
                break
        else:
            if question.find(key)!=-1:
                answer = answers[key]

    answer = cleanAnswer(answer)

    if(answer.startswith('+')):#do google lucky search
        googleLucky(answer)
        answer = answer.replace('+','Googling ')
    elif(answer.startswith('@')):#evaluate statement         
        answer=answer[1:]
        print "Executing: "+answer
        exec(answer)
        answer=''      

    if(len(answer.strip())>0):
        print "I answer:  " + answer
        speak(answer)
    
    if IsAd and UseSTT==1:
        raw_input("Press enter to continue... ")            
    return question


def makeToast(message):
    if IsAd:
        droid = android.Android()
        droid.makeToast(message)
    else:
        print "Toast Test: " + message
    return 

def speak(message):
    "Text to Speech (TTS)"
    if IsAd:
        droid = android.Android()
        droid.ttsSpeak(message)
        return
    else:
        print message
        return

def googleLucky(message):
    "Do a Google I am lucky search"
    google(message,1)
    return

def google(message,useLucky=0):
    "Do regular google search"
    luckySuffix=''
    if useLucky:
        luckySuffix='&btnI=745'
    msg = "http://www.google.ca/search?q=" + message.replace(' ','+')+luckySuffix
    if IsAd:
        droid = android.Android()
        droid.startActivity('android.intent.action.VIEW', msg)
        return
    else:
        print "Simulating google of "+msg
    return

def getQuestion(message):
    "Voice recognitiion STT (Speech to text)"
    global UseSTT
    if IsAd and UseSTT: #if is on Android and use Speech to Text
        droid = android.Android()
        results = droid.recognizeSpeech("Ask Ziri",None,None)
        if( results.error != None ) :   #If speech dialogue box is cancelled, use text entry mode
            UseSTT=0                    #Disable Speech to Text
            speech = ""
            print "Hide Text Recognization Dialogue"
        else:
            speech = str( results.result )        

        if(speech.strip() == "" or UseSTT==0):  #IF STT is disabled, use text entry
            speech  = raw_input(message)            
        return speech
    else:
        return raw_input(message);              #If test on PC, use text entry

comments powered by Disqus
Powered by Afterweb 1.66