我尝试在我的应用程序中实现一个客户管理器,以避免用户每次打开应用程序时都必须登录。
所以基本上,我已经有了我的身份验证 Activity ,用户可以在其中放置其登录名和密码,以及我们从服务器接收 token 的地方(身份验证目前是基本的)。现在我想添加 AccountManager 但我真的不明白哪个部分会去哪里。
我需要的是非常基本的:
这是我的代码:
AuthenticationActivity.java
public class AuthenticationActivity extends Activity {
private EditText editTextUsername;
private EditText editTextPassword;
private Button buttonLogin;
private ProgressBar spinner;
private TextView error;
private TextView register;
private boolean accountRegistred;
AccountManager accountManager;
public static final String AUTHENTICATION = "authentication"; //action
private ConnectionSuccessReceiver connectionSuccessReceiver = new ConnectionSuccessReceiver();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.authentification);
accountManager = AccountManager.get(this);
Account[] accounts = accountManager.getAccountsByType("login");
if (accounts.length > 0) {
//If there is an account
} else {
accountRegistred = false;
editTextUsername = (EditText) findViewById(R.id.editText_login);
editTextUsername.setVisibility(View.VISIBLE);
editTextPassword = (EditText) findViewById(R.id.editText_password);
editTextPassword.setVisibility(View.VISIBLE);
buttonLogin = (Button) findViewById(R.id.button_connection);
buttonLogin.setVisibility(View.VISIBLE);
error = (TextView) findViewById(R.id.textView_error);
register = (TextView) findViewById(R.id.textView_register);
register.setVisibility(View.VISIBLE);
spinner = (ProgressBar) findViewById(R.id.progressBar);
buttonLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Here we start the service which will reach the server
Intent i = new Intent(getApplicationContext(), AuthenticationService.class);
i.putExtra("username", editTextUsername.getText().toString());
i.putExtra("password", editTextPassword.getText().toString());
getApplication().startService(i);
spinner.setVisibility(View.VISIBLE);
error.setVisibility(View.INVISIBLE);
}
});
register.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(AuthenticationActivity.this, RegisterActivity.class));
}
});
}
registerReceiver(connectionSuccessReceiver, new IntentFilter(AUTHENTICATION));
}
private class ConnectionSuccessReceiver extends BroadcastReceiver {
//Called when the server returns success after authentication, we get the TOKEN here
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getStringExtra("STATE").equals("CONNECTED")) {
Intent i = new Intent(AuthenticationActivity.this, MainActivity.class);
i.putExtra("TOKEN", intent.getStringExtra("TOKEN"));
startActivity(i);
} else {
spinner.setVisibility(View.INVISIBLE);
error.setVisibility(View.VISIBLE);
}
finish();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(connectionSuccessReceiver);
}
}
AuthenticatorService.java
public class AuthenticatorService extends Service {
/**
* The implementation of the class |AccountAuthenticatorImpl|.
* It is implemented as a singleton
*/
private static AccountAuthenticator accountAuthenticator = null;
/**
* The main constructor.
*/
public AuthenticatorService() {
super();
}
/**
* The bind method of the service.
* @param intent The intent used to invoke the service
* @return The binder of the class which has implemented |AbstractAccountAuthenticator|
*/
@Override
public IBinder onBind(Intent intent) {
IBinder ret = null;
if (intent.getAction().equals(android.accounts.AccountManager.ACTION_AUTHENTICATOR_INTENT)) {
ret = getAuthenticator().getIBinder();
}
return ret;
}
/**
* The method used to obtain the authenticator. It is implemented as a singleton
* @return The implementation of the class |AbstractAccountAuthenticator|
*/
private AccountAuthenticator getAuthenticator() {
if (AuthenticatorService.accountAuthenticator == null) {
AuthenticatorService.accountAuthenticator = new AccountAuthenticator(this);
}
return AuthenticatorService.accountAuthenticator;
}
public class AccountAuthenticator extends AbstractAccountAuthenticator {
private Context context;
public AccountAuthenticator(Context context) {
super(context);
this.context = context;
}
@Override
public Bundle editProperties(AccountAuthenticatorResponse accountAuthenticatorResponse, String s) {
return null;
}
@Override
public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) throws NetworkErrorException {
Bundle reply = new Bundle();
Intent i = new Intent(context, AuthenticationActivity.class);
i.setAction("com.readyo.app.authentication.addnewaccount");
i.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
i.putExtra("AuthTokenType", authTokenType);
reply.putParcelable(AccountManager.KEY_INTENT, i);
return reply;
}
@Override
public Bundle confirmCredentials(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, Bundle bundle) throws NetworkErrorException {
return null;
}
@Override
public Bundle getAuthToken(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, String s, Bundle bundle) throws NetworkErrorException {
return null;
}
@Override
public String getAuthTokenLabel(String s) {
return null;
}
@Override
public Bundle updateCredentials(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, String s, Bundle bundle) throws NetworkErrorException {
return null;
}
@Override
public Bundle hasFeatures(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, String[] strings) throws NetworkErrorException {
return null;
}
}
}
我也有通过 HTTP 访问服务器的代码,但我不确定它在这里是否重要。
感谢您的宝贵时间。
最佳答案
回复有点晚,但也许这个示例可以帮助您: https://github.com/dawidgdanski/AccountAuthenticatorExample
我之前创建过它,但注册/登录的逻辑可能会有帮助
add an account if I never logged in before:
验证和验证用户凭据后,调用 AccountManager.addAccountExcplicitly() 方法。
请记住,您也可以从系统设置中创建特定于应用程序的帐户。
log automatically if my account exists
嗯,我不确定我是否正确理解了你的需求。一旦您将帐户存储在 AccountManager 的元数据中,一旦您调用 AccountManager.getAccountsByType("my.account.type"),它就可用。 如果您想自动登录,那么您必须在某个地方存储您的凭据,这显然面临敏感数据泄露的威胁。
if the auto authentication doesn't work get a new token on the server
有一个 AccountManager.invalidateAuthToken() 方法可以删除当前存储的 authToken 并调用另一个。
您可以启动示例应用程序,我认为它至少可以解决您的一些问题,因为它涵盖了以下逻辑:
干杯
关于android - 如何在我的应用程序中实现 AccountManager,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27927252/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits
我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我怎样才能完成http://php.net/manual/en/function.call-user-func-array.php在ruby中?所以我可以这样做:classAppdeffoo(a,b)putsa+benddefbarargs=[1,2]App.send(:foo,args)#doesn'tworkApp.send(:foo,args[0],args[1])#doeswork,butdoesnotscaleendend 最佳答案 尝试分解数组App.send(:foo,*args)
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚