HTC Lock Screen API Sample Code

The HTC Lock Screen API allows apps to offer people interactive customizations for the lock screen on some of HTC's latest devices like the One X. For example, the LockScreenDemo sample code downloaded with the SDK add-on from the Android SDK manager generates a touchable alarm clock in the center of the lock screen in the screenshot below:


The user chooses to use a lock screen provided by an app in their phone settings, under the personalization option. The app must not have a registered remote control client via the AudioManager.registerRemoteControlClient method for the chosen lock screen to appear. This is because registering a remote control client causes media information and playback controls to appear in the same area instead..





The app uses the AndroidManifest.xml to define the services it provides to render the lock screen. One service provides the lock screen for normal use. The other service provides the lock screen when the user is previewing it in the personalization settings. Permissions and libraries required by the lock screen also have to be declared in this file. The lock screen service should be defined in the manifest as disabled and only enabled when the lockscreen API is detected to prevent issues with older phones that had an incomplete API. Here is the relevant section of the manifest of the LockScreenDemo sample code with examples of the needed services:

=================================================================================
<uses-permission a:name="android.permission.WAKE_LOCK"/>
<
uses-permission a:name="com.htc.idlescreen.permission.IDLESCREEN_SERVICE" />

<
application a:icon="@drawable/icon"
  
a:label="@string/app_name">

    <!-- 
Libraries needed for the lockscreen API. -->
    <
uses-library a:name="com.htc.lockscreen.fusion"
    
a:required="false" />
  <
uses-library a:name="com.htc.fusion.fx"
    
a:required="false" />

  <!-- 
Activity to enable lockscreen service and prompt user on how to select it. -->
  <
activity a:name="com.htc.sample.idlescreen.SetupActivity">
    <
intent-filter>
      <
action a:name="android.intent.action.MAIN" />
      <
category a:name="android.intent.category.DEFAULT" />
      <
category a:name="android.intent.category.LAUNCHER" />
    </
intent-filter>
  </
activity>

  <!-- 
Service to show user a preview of the lockscreen in the lockscreen chooser. -->
  <
service a:name="SamplePreviewService"
      
a:process=":preview" >
    <
intent-filter>
      <
action a:name="com.htc.lockscreen.idlescreen.preview.IdleScreenService"/>
    </
intent-filter>
  </
service>

  <!-- 
Service to show user custom interactive lockscreen content before they unlock their phone. -->
  <!-- 
Disabled by default so does not break on earlier versions of OpenSense where the API was different. --> 
  <
service a:name="SampleService"
        
a:permission="com.htc.idlescreen.permission.IDLESCREEN_SERVICE"
    
a:enabled="false">
    <
intent-filter>
      <
action a:name="com.htc.lockscreen.idlescreen.IdleScreenService"/>
    </
intent-filter>
    <!-- 
Data that describes your lockscreen to the user in the lockscreen chooser. -->
    <
meta-data a:name="com.htc.lockscreen.idlescreen"
        
a:resource="@xml/idlescreen"/>
  </
service>

</
application

=================================================================================

The defined service must extend SimpleIdleScreenService and return a class that extends SimpleEngine from the onCreateEngine method. This engine sets the content view to use and defines how the lockscreen reacts to events. Compared to an Activity set to show in front of the system keyguard, using the HTC Lock Screen API allows working with the rest of the HTC lock screen functionality such as dragging user chosen apps into the circle to start them quickly. Compared to Live Wallpapers, the HTC Lock Screen API allows using full View hierarchies with click listeners. Live Wallpapers only support detecting touch to the entire surface at once and requires the developer to handle fine grained details. MotionEvents for ACTION_DOWN are limited, however, due to the need not to respond inside user's pockets. An example touch interaction is visible at the bottom of the LockScreenDemo service source code:

=================================================================================
public class SampleService extends SimpleIdleScreenService {

  
@Override
  
public SimpleEngine onCreateEngine() {
    
return new IdleScreenRemoteEngine();
  
}

  
public class IdleScreenRemoteEngine extends SimpleEngine implements OnClickListenerOnTouchListener{

    
private Button mButton;
  
    private 
AlarmAnime mClock;

    private 
boolean mStart false;

    public 
IdleScreenRemoteEngine() {
    }
  
    
public void onCreate(SurfaceHolder holder{
      this
.setContent(R.layout.lockscreen);
      
this.setShowLiveWallpaper(false);
      
this.setBackground(R.drawable.background);
    
      
mClock = (AlarmAnime)this.findViewById(R.id.clock);
      
mButton = (Button)this.findViewById(R.id.button1);
      
mButton.setOnClickListener(this);
      
mButton.setOnTouchListener(this);
    
}
  
    
public void onStart() {   
    }
  
    
public void onResume() {
    }
  
    
public void onPause() {
    }
  
    
public void onStop() {
    }
  
    
public void onDestroy() {
    }
  
    
@Override
    
public void onClick(View view{
      
if (!mStart{
        mClock
.startAnime();
        
mButton.setText(R.string.button2);
        
mStart true;
      
}
      
else {
        mClock
.stopAnime();
        
mButton.setText(R.string.button1);
        
mStart false;
      
}
    }

    
@Override
    
public boolean onTouch(View arg0MotionEvent event{
      
if (event.getAction() == MotionEvent.ACTION_DOWN{
        skipShowHint
();
      
}
      
return false;
    
}
  }
=================================================================================
For this sample code, when touched, the alarm clock starts to animate bouncing side to side:





An Activity in the application should detect the lockscreen API, enable the service, and prompt the user to use the lockscreen if desired. The lock screen offered by the app will be offered in the phone's personalization settings once the service is enabled. Here is the Activity that does that from the LockScreenDemo sample code:


public class SetupActivity extends Activity {

  
private static final String LOG_TAG "LockScreenDemo SetupActivity";

  private static final 
String NEW_LOCKSCREEN_API_CLASS_NAME "com.htc.lockscreen.fusion.open.SimpleEngine";

  @
Override
  
protected void onCreate(final Bundle savedInstanceState{
    super
.onCreate(savedInstanceState);
    
setContentView(R.layout.setup);
    final 
TextView text = (TextViewfindViewById(R.id.text);

    
// Check for lockscreen API.
    
final boolean isNewLockscreenApiSupported isNewLockscreenApiSupported();
    
Log.i(LOG_TAG"isNewLockscreenApi: " isNewLockscreenApiSupported);

    
// If not supported, let the user know and finish executing.
    
if ( !isNewLockscreenApiSupported {
      text
.setText(R.string.setup_prompt_not_supported);
      return;
    
}
  
    
// Otherwise enable lockscreen service and let user know how to enable.
    
text.setText(R.string.setup_prompt_supported);
    final 
ComponentName name = new ComponentName(thisSampleService.class);
    
Log.i(LOG_TAG"enabling service: " name);
    final 
PackageManager pm = (PackageManagergetPackageManager(); 
    
pm.setComponentEnabledSetting(namePackageManager.COMPONENT_ENABLED_STATE_ENABLEDPackageManager.DONT_KILL_APP);
  
}

  
/**
   * @return true if the lockscreen API is supported
   */
    
public static final boolean isNewLockscreenApiSupported() {
        
try {
            
Class.forName(NEW_LOCKSCREEN_API_CLASS_NAME);
            return 
true;
        
catch (final ClassNotFoundException e{
        }
        
return false;
    
}






The second sample project, LockScreenSupportDemo wraps the current API to provide the ability to test your code in the emulator as well as testing on current Sense 4 roms that have not yet been updated to the current lock screen API. The older API (referred to as legacy in the sample project) is deprecated but provided for early access testing on current devices.
The following code illustrates the common code implementation of the lock screen example found in the previous example with one minor change, instead of using a button, a touch event is handled to toggle the clock's movement.
public class LockScreenImpl extends LockScreenImplBase implements LockScreenListenerOnTouchListener {

  
private AlarmAnime mClock;
    private 
boolean mStart;

  public 
LockScreenImpl(SampleService.IdleScreenRemoteEngine context{
    super
(context);
  
}
  
// support for older deprecated API
  
public LockScreenImpl(SampleServiceLegacy.IdleScreenRemoteEngine context{
    super
(context);
  
}
  
// support for running in an activity (emulator)
  
public LockScreenImpl(Activity context{
    super
(context);
  
}

  
@Override
  
public void onCreate(SurfaceHolder holder{
  
    setContent
(R.layout.main);
    
setShowLiveWallpaper(true);

    
mClock = (AlarmAnimefindViewById(R.id.clock);
        
mClock.setOnTouchListener(this);
  
}

  
@Override
  
public boolean onTouch(View viewMotionEvent event{
        
if (view.getId() == R.id.clock{
            
if (event.getAction() == MotionEvent.ACTION_UP{
                
if (!mStart{
                    Log
.w("SampleService""START animation");
                    
mClock.startAnime();
                    
mStart true;
                
else {
                    Log
.w("SampleService""STOP animation");
                    
mClock.stopAnime();
                    
mStart false;
                
}
            }
            
else if (event.getAction() == MotionEvent.ACTION_DOWN{
        skipShowHint
();
            
}
            
return true;
        
}
        
return false;
  
}
  
@Override
  
public void onStart() {
  }
  
@Override
  
public void onResume() {
  }
  
@Override
  
public void onPause() {
  }
  
@Override
  
public void onStop() {
  }
  
@Override
  
public void onDestroy() {
  }
As with the previous sample, life cycle methods are provided here but as overridden methods. The full source code for the wrapper is available as part of the sample project.

Emulator test mode:


Source: HTCDEV






Hitesh Patel

Greetings! I'm Hitesh Patel, an enthusiastic educator and tech aficionado with a fervent love for all things computer science. My journey in academia has been intertwined with my deep-seated passion for exploring the intricacies of mobile and web technologies. Beyond the classroom, I immerse myself in the vibrant world of IT innovation, constantly seeking to unravel the mysteries behind emerging trends and breakthroughs. Join me as I embark on a quest to decode the wonders of technology and share my discoveries along the way.

Post a Comment

Previous Post Next Post